0

如果我们有:

__int32 some_var = 0;

什么是最好的(如果有的话)调用方式InterlockedExchangeInterlockedIncrement以及其他需要LONG*的联锁功能some_var

因为,在任何 Windows 上都可以保证LONG32 位,所以通过(long*) some_var. 但是,在我看来,这很丑陋,我无法确认它是安全的。

请注意,我无法将类型更改为,long因为它不可移植。我正好需要 32 位类型。

更新:对提供可移植原子操作的库的一些研究表明,没有人会为转换而烦恼。一些例子:

Apache 便携式运行时 (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;
}
4

6 回答 6

2

嗯,这是一块岩石和一个坚硬的地方。原子增量是重型平台实现细节。这就是为什么首先存在 LONG typedef 的原因。20 或 50 年后的某些未来操作系统可能会重新定义该类型。例如,当 256 位内核很常见并且原子增量的工作方式不同时。谁知道。

如果您想编写真正可移植的代码,那么您应该使用真正可移植的类型。喜欢龙。让它发挥作用将是微软的负担,而不是你的。

在很长一段时间内它将是一个 32 位整数,我建议你不要担心。

于 2010-09-03T16:20:56.753 回答
1

您不妨将类型更改为 long,留下可移植性,因为整个“互锁”原子操作系列也不是可移植的。

顺便说一句,我认为 interlocked 支持整数重载。也许那只是在.net中。

于 2010-09-03T15:14:54.333 回答
1

嗯,__int32也不是便携类型。所以我让问题消失的建议是使用 typedef。在 Windows 上,您可以执行以下操作:

typedef LONG my_int32;

...并安全地将指向这种类型的指针传递给InterlockedExchange(). 在其他系统上,使用 32 位类型 - 例如,如果它们有stdint.h,您可以执行以下操作:

typedef int32_t my_int32;
于 2010-09-04T03:52:56.910 回答
0

有趣的是,有InterlockedExchange - 一个需要 LONG* 的 Windows API 和_InterlockedExchange一个 msvc 编译器内在函数,需要很长时间 *。

由于调用了可移植性,我还将链接一个关于GCC atomic intrinsics的页面。

然而,这一点很好理解:MSVC 将 ILP32LLP64数据模型用于 32 位构建,将 LLP64 数据模型用于 64 位构建。Windows 确实存在基于 GCC 的工具链(例如 MinGW),并且可以很好地实现 LP64 模型——这很有趣!例如 'long' 是 64 位,但 LONG 是 32。

如果您坚持使用 Microsoft 编译器,则无需担心。

所以,总而言之: 1. 被传递的值必须用'volatile'限定。2. 因为您 (a) 使用 32 位数量(这是您的要求)和 (b) 使用 InterlockedXXX API 的显式 32 位形式 - 它 100% 安全地进行血腥转换并完成它:InterlockedIncrement将对所有位大小的 32 位值进行操作,您的变量将在所有位大小上显式地为 32 位 - 即使使用不同的数据模型。

演员是安全的,不要无缘无故地把事情复杂化。

于 2010-09-04T20:29:32.430 回答
0

当断言失败时,只做assert(sizeof(LONG) == sizeof(some_var))并且只担心问题。雅格尼。只要断言成立,您就可以使用reinterpret_cast<LONG*>(&some_var).

于 2010-09-03T16:44:09.487 回答
0

Hans Passant表达得非常好:

“原子增量是一个重型平台实现细节。”

这就是实现提供类型特定重载的原因。

atomic_ops就是这样一个项目。

从理论上讲,每个 Interlocked 功能都可以通过使用成熟的锁来实现——这反过来又依赖于平台细节:-)——但这对于目标硬件平台上支持的类型和功能来说是一个真正的性能过度杀伤。

在这方面正在进行一些标准化,请参见此处此处回答的类似问题。

于 2010-09-05T01:00:40.707 回答