C++ 是否有Windows API来自动设置16字节数组?

C++ 是否有Windows API来自动设置16字节数组?,c++,multithreading,winapi,atomic,C++,Multithreading,Winapi,Atomic,我想知道是否有windows API可以自动设置16字节数组 我真的不想为了实现这个操作而引入关键部分或互斥体,所以我试图找到一个更简单的解决方案 我需要这个,因为这个16字节的数组可以从工作线程写入,并且主要从主线程读取。以下所有内容都假设为64位x86_64体系结构。我相信在32位x86上通常不可能实现您要求的功能 实际上有两种选择。第一个是,它转换为锁CMPXCHG16B。要使用它复制16字节存储的功能,您需要执行以下操作: __int64* dest = ...; __int64* or

我想知道是否有windows API可以自动设置16字节数组

我真的不想为了实现这个操作而引入关键部分或互斥体,所以我试图找到一个更简单的解决方案


我需要这个,因为这个16字节的数组可以从工作线程写入,并且主要从主线程读取。

以下所有内容都假设为64位x86_64体系结构。我相信在32位x86上通常不可能实现您要求的功能

实际上有两种选择。第一个是,它转换为锁CMPXCHG16B。要使用它复制16字节存储的功能,您需要执行以下操作:

__int64* dest = ...;
__int64* orig = ...;
unsigned char ok;
do
{
    __int64 high = dest[0];
    __int64 low  = dest[1];
    ok = _InterlockedCompareExchange128(dest, high, low, orig);
}
while (!ok);
__m128i* dest = ...;
_mm_mfence();
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig));
_mm_mfence();
请注意,由于这是一个联锁操作,因此它意味着等效于。这通常就是所谓的“原子”操作

如果您想要纯存储,而不是比较交换,那么您可以在硬件上使用任何转换为对齐的16字节存储的东西。例如,
MOVDQA
指令将符合条件。在C++中,它看起来像这样:

__int64* dest = ...;
__int64* orig = ...;
unsigned char ok;
do
{
    __int64 high = dest[0];
    __int64 low  = dest[1];
    ok = _InterlockedCompareExchange128(dest, high, low, orig);
}
while (!ok);
__m128i* dest = ...;
_mm_mfence();
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig));
_mm_mfence();

除非您有理由避免使用SSE指令,否则我认为第二个版本的性能可能会更好。您还可能需要根据实际需要决定是否要放松这两个内存屏障。

以下所有内容均假定为64位x86_64体系结构。我相信在32位x86上通常不可能实现您要求的功能

实际上有两种选择。第一个是,它转换为锁CMPXCHG16B。要使用它复制16字节存储的功能,您需要执行以下操作:

__int64* dest = ...;
__int64* orig = ...;
unsigned char ok;
do
{
    __int64 high = dest[0];
    __int64 low  = dest[1];
    ok = _InterlockedCompareExchange128(dest, high, low, orig);
}
while (!ok);
__m128i* dest = ...;
_mm_mfence();
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig));
_mm_mfence();
请注意,由于这是一个联锁操作,因此它意味着等效于。这通常就是所谓的“原子”操作

如果您想要纯存储,而不是比较交换,那么您可以在硬件上使用任何转换为对齐的16字节存储的东西。例如,
MOVDQA
指令将符合条件。在C++中,它看起来像这样:

__int64* dest = ...;
__int64* orig = ...;
unsigned char ok;
do
{
    __int64 high = dest[0];
    __int64 low  = dest[1];
    ok = _InterlockedCompareExchange128(dest, high, low, orig);
}
while (!ok);
__m128i* dest = ...;
_mm_mfence();
_mm_store_si128(dest, _mm_loadu_si128((__m128i*)&orig));
_mm_mfence();

除非您有理由避免使用SSE指令,否则我认为第二个版本的性能可能会更好。您还可能需要根据实际需要决定是否放宽这两个内存限制。

16字节数组?意味着16字节元素的数量不定?这基本上意味着一个原子操作,可以设置一个任意大的内存块,而这个内存块并不存在。@JohnCalsbeek:那是16位。@JamesMcNellis啊,该死,误读了这个问题。
\u InterlocatedCompareeExchange 128
的存在似乎表明答案是“是”。。。假设您的数据对齐。@ahmd0是的,它确实需要64位CPU。事实上,AMD早期的一些64位CPU甚至不支持它。当然,问题是您需要知道这些字节中的前一个值,因此完整的原子写入需要在循环中使用该操作。@ahmd0顺便说一句,如果您想要一个不充当内存屏障的原子存储(您可以自己添加屏障),那么您可以使用对齐的SSE存储,也应该是原子的。一个16字节的数组?意味着16字节元素的数量不定?这基本上意味着一个原子操作,可以设置一个任意大的内存块,而这个内存块并不存在。@JohnCalsbeek:那是16位。@JamesMcNellis啊,该死,误读了这个问题。
\u InterlocatedCompareeExchange 128
的存在似乎表明答案是“是”。。。假设您的数据对齐。@ahmd0是的,它确实需要64位CPU。事实上,AMD早期的一些64位CPU甚至不支持它。当然,问题是您需要知道这些字节中的前一个值,因此完整的原子写入需要在循环中使用该操作。@ahmd0顺便说一句,如果您想要一个不充当内存屏障的原子存储(您可以自己添加屏障),那么您可以使用对齐的SSE存储,我希望.net中有一个“objectPair”类型,它包含两个对象引用,并且可以进行比较交换。由于32位机器具有32位对象引用和64位比较交换,而64位机器具有64位对象引用但具有128位比较交换,因此.net似乎可以允许一对对象引用的比较交换。不像68020上的真正的双比较和交换操作那样有用,但在今天的硬件上可用。我希望.net中有一个“objectPair”类型,它包含两个对象引用,并且可以进行比较交换。由于32位机器具有32位对象引用和64位比较交换,而64位机器具有64位对象引用但具有128位比较交换,因此.net似乎可以允许一对对象引用的比较交换。不像68020上的真正双比较和交换操作那样有用,但在今天的硬件上可用。