我需要在char或short上使用_Interlocked ***函数,但它需要长指针作为输入。似乎有函数_InterlockedExchange8,我没有看到任何文档。看起来这是无证件的功能。编译器也无法找到_InterlockedAdd8函数。 我将非常感谢有关该功能的任何信息,使用/不使用的建议以及其他解决方案。
更新1
我会尝试简化问题。 我怎样才能做到这一点?
struct X
{
char data;
};
X atomic_exchange(X another)
{
return _InterlockedExchange( ??? );
}
我看到两种可能的解决方案
_InterlockedExchange8
another
转换为long,进行交换并将结果转换回X 第一个显然是糟糕的解决方案。 第二个看起来更好,但如何实现呢?
更新2
你怎么看待这样的事情?
template <typename T, typename U>
class padded_variable
{
public:
padded_variable(T v): var(v) {}
padded_variable(U v): var(*static_cast<T*>(static_cast<void*>(&v))) {}
U& cast()
{
return *static_cast<U*>(static_cast<void*>(&var));
}
T& get()
{
return var;
}
private:
T var;
char padding[sizeof(U) - sizeof(T)];
};
struct X
{
char data;
};
template <typename T, int S = sizeof(T)> class var;
template <typename T> class var<T, 1>
{
public:
var(): data(T()) {}
T atomic_exchange(T another)
{
padded_variable<T, long> xch(another);
padded_variable<T, long> res(_InterlockedExchange(&data.cast(), xch.cast()));
return res.get();
}
private:
padded_variable<T, long> data;
};
感谢。
答案 0 :(得分:2)
制作8位和16位互锁功能非常容易,但它们未包含在WinAPI中的原因是由于IA64的可移植性。如果你想支持Win64,汇编程序不能内联,因为MSVC不再支持它。作为外部功能单元,使用MASM64,它们不会像内联代码或内在函数那样快,因此您更明智地研究促进算法使用32位和64位原子操作。
示例互锁API实施:intrin.asm
答案 1 :(得分:1)
为什么要使用较小的数据类型?那么你可以将它们放在一个小的内存空间中吗?这只会导致错误的共享和缓存行争用。
无论您使用锁定算法还是无锁算法,最好将数据保存在至少128字节(或CPU上的任何高速缓存行大小)的块中,这些块一次只能由一个线程使用。
答案 2 :(得分:1)
嗯,你必须使用可用的功能。 _InterlockedIncrement
和`_InterlockedCompareExchange提供16位和32位变体(后者也是64位变体),也许其他一些互锁内在函数也可用于16位版本,但InterlockedAdd不具备此功能。似乎是,似乎根本没有字节大小的互锁内在函数/函数。
所以......你需要退后一步,找出如何在没有IntrinsicAdd8
的情况下解决问题。
在任何情况下,为什么要使用单个字节?坚持int
大小的对象,除非你有充分的理由使用更小的东西。
答案 3 :(得分:1)
创建新答案,因为您的编辑稍微改变了一点:
- 使用_InterlockedExchange8
- 将另一个转换为long,进行交换并将结果转换回X
第一个根本行不通。即使函数存在,它也允许您一次原子地更新一个字节。这意味着对象作为一个整体将在一系列步骤中更新,不会是原子的。
除非X
是long
大小的POD类型,否则第二个也不起作用。 (除非它在sizeof(long)
边界上对齐,除非它与long
的大小相同)
为了解决这个问题,您需要缩小X
类型的范围。首先,当然,它是否保证是POD类型?如果没有,你有一个完全不同的问题,因为你无法安全地将非POD类型视为原始内存字节。
其次,X
可能具有哪些尺寸?互锁功能可以处理16,32,并根据情况,可能是64位甚至128位宽。
这是否涵盖了您可能遇到的所有情况?
如果没有,你可能不得不放弃这些原子操作,并解决普通的旧锁。锁定互斥锁以确保一次只有一个线程接触这些对象。