如果我们有:
__int32 some_var = 0;
调用InterlockedExchange
,InterlockedIncrement
以及LONG*
需要some_var
的其他互锁功能的最佳方法(如果有)是什么?
因为,保证LONG
在任何Windows上都是32位,所以传递(long*) some_var
可能是安全的。然而,在我看来它很难看,我无法确认这是安全的。
注意,我无法将类型更改为long
,因为它不可移植。我需要32位类型。
更新:对提供便携式原子操作的图书馆的一些研究表明,没有人会厌倦施法。一些例子:
Apache Portable Runtime (APR):
typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_fn)
(apr_uint32_t volatile *,
apr_uint32_t);
APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
{
#if (defined(_M_IA64) || defined(_M_AMD64))
return InterlockedExchangeAdd(mem, val);
#elif defined(__MINGW32__)
return InterlockedExchangeAdd((long *)mem, val);
#else
return ((apr_atomic_win32_ptr_val_fn)InterlockedExchangeAdd)(mem, val);
#endif
}
AO_INLINE AO_t
AO_fetch_and_sub1_full (volatile AO_t *p)
{
return _InterlockedDecrement64((LONGLONG volatile *)p) + 1;
}
答案 0 :(得分:2)
嗯,这是一块岩石和一块坚硬的地方。原子增量是重型平台实现细节。这就是为什么LONG typedef首先存在的原因。未来20或50年后的某些未来操作系统可能会重新定义该类型。比方说,当256位核心是常见的,原子增量的工作方式不同。谁知道呢。
如果你想编写真正可移植的代码,那么你应该使用真正的可移植代码。像LONG一样。微软的负担是让它成功,而不是你的。
它将在未来一段时间内成为一个32位整数,我建议你不要担心它。
答案 1 :(得分:1)
您也可以将类型更改为long,留下可移植性,因为整个“互锁”原子操作系列也不可移植。
顺便提一下,作为旁注,我认为联锁支持整数重载。也许仅仅是在.net中。
答案 2 :(得分:1)
好吧,__int32
不是便携式 。所以我的建议是让问题消失,就是使用typedef。在Windows上,您可以执行以下操作:
typedef LONG my_int32;
...并安全地将指向此类型的指针传递给InterlockedExchange()
。在其他系统上,使用32位类型的任何东西 - 例如,如果它们有stdint.h
,您可以这样做:
typedef int32_t my_int32;
答案 3 :(得分:0)
只做assert(sizeof(LONG) == sizeof(some_var))
并且只在断言失败时担心问题。 YAGNI。只要断言成立,您就可以使用reinterpret_cast<LONG*>(&some_var)
。
答案 4 :(得分:0)
有趣的是,有InterlockedExchange - 一个Windows API,需要一个LONG *和_InterlockedExchange msvc编译器内在函数,需要很长时间*。
由于已调用可移植性,我还会链接GCC atomic intrinsics上的页面。
然而,重点是:MSVC使用ILP32LLP64 data model进行32位构建,使用LLP64进行64位构建。基于GCC的工具链(如MinGW)确实存在于Windows中,可能很好地实现了LP64模型 - 导致有趣!诸如'long'之类的出现是64位,但LONG是32。
如果您坚持使用微软编译器,那么您无需担心。
所以,最后: 1.传递的值必须用'volatile'限定。 2.因为你是(a)使用32位数量(这是你的要求)和(b)使用明确的32位形式的InterlockedXXX API - 100%安全,只做血腥演员并完成它:InterlockedIncrement将在所有位大小上以32位值运行,即使使用不同的数据模型,您的变量在所有位大小上也将明确为32位。
演员是安全的,不要无缘无故地复杂化。答案 5 :(得分:0)
Hans Passant表达得非常好:
“原子增量是一个重型平台实现细节。”
这就是实现提供特定于类型的重载的原因。
atomic_ops
就是这样一个项目。
理论上,每个Interlocked功能都可以通过使用全面锁来实现 - 这反过来又依赖于平台细节:-) - 但这对于目标硬件平台支持的类型和功能来说是真正的性能过度杀伤