具有获取和释放语义的联锁操作(多平台)
编辑: 好的,我有一个具体问题。我想通过获取和释放语义(伪代码)来实现“交换”功能:
interlocked_inc_32(target)
{
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
interlocked_inc_32_acq(target)
{
lfence
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
interlocked_inc_32_rel(target)
{
sfence
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
问题是:我不知道如何实现它。我正在使用 Microsoft Visual Studio 2010 在 Windows 下进行开发。当然,有“intrin.h”和“Windows.h”提供了这些函数/内在函数。但 InterlockedIncrementAcquire 只是 InterlockedIncrement 的定义,并提供完整的内存屏障。那不是我所追求的。
/**************************************** 原帖: /*********** *************** **************
我想编写一个像 C++0x std::atomic 这样的原子类。 我只是想确定我的想法是否正确。
我想实现以下代码: 编辑(替换了糟糕的实现)
enum memory_order { memory_order_acquire, memory_order_release, memory_order_acq_rel };
template<class T> class atomic;
template<class atomic_type, std::size_t = sizeof(typename ExtractType<atomic_type>::type)> struct interlocked;
template<template<class> class atomic_type> struct interlocked<atomic_type, 1>
{
typedef typename ExtractType<atomic_type>::type bit8_type;
void store(bit8_type value, memory_order order = memory_order_acq_rel) volatile {
interlocked_xchg_8<order>(&static_cast<atomic_type volatile*>(this)->m_value, value);
}
bit8_type load(memory_order order = memory_order_acq_rel) const volatile
{
interlocked_cmp_xchg_8<order>(
const_cast<bit8_type volatile*>(&static_cast<volatile const atomic_type *const>(this)->m_value),
static_cast<atomic_type const volatile*>(this)->m_value,
static_cast<atomic_type const volatile*>(this)->m_value
);
}
bit8_type exhange(bit8_type, memory_order order = memory_order_acq_rel) volatile {
return interlocked_xchg_8<order>(&static_cast<atomic_type volatile*>(this)->m_value, value);
}
bool compare_exchange(bit8_type comperand, bit8_type new_value, memory_order order = memory_order_acq_rel) volatile
{
return interlocked_cmp_xchg_8<order>(
&static_cast<atomic_type volatile*>(this)->m_value,
new_value,
comperand
) == comperand;
}
};
template<template<class> class atomic_type> struct interlocked<atomic_type, 2> { };
template<template<class> class atomic_type> struct interlocked<atomic_type, 4> { };
template<template<class> class atomic_type> struct interlocked<atomic_type, 8> { };
template<class T>
class atomic : public interlocked<atomic<T>> { T m_value; };
是否有我遗漏的东西,或者这是一个“好的”相当好的实现。
感谢您的任何评论。最好的问候:
PS: 我不想为此开始一个新问题: 使用 boost::uint32_t (在 boost\cstdint.h 中)而不是 uint32_t (在 stdint.h 中)有什么优点?
EDIT:
Okay, I've got a specific question. I want to implement 'exchange' functionality with acquire and release semantic (pseudo-code):
interlocked_inc_32(target)
{
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
interlocked_inc_32_acq(target)
{
lfence
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
interlocked_inc_32_rel(target)
{
sfence
mov ecx, 1
lea eax, target
lock xadd, [eax], ecx
}
The problem with that is: I have no idea how to implement this. I'm developing under windows using Microsofts Visual Studio 2010. Sure, there are "intrin.h" and "Windows.h" which provide exactly these functions / intrinsics. BUT there InterlockedIncrementAcquire is just a define for InterlockedIncrement and provides a full memory barrier. That's not wht I'm after.
/****************************************
original post:
/****************************************
I want to write a atomic class like C++0x std::atomic.
I just want to be sure if my thoughts about it are right.
I would like to implement the following code:
EDIT (replaced bad implementation)
enum memory_order { memory_order_acquire, memory_order_release, memory_order_acq_rel };
template<class T> class atomic;
template<class atomic_type, std::size_t = sizeof(typename ExtractType<atomic_type>::type)> struct interlocked;
template<template<class> class atomic_type> struct interlocked<atomic_type, 1>
{
typedef typename ExtractType<atomic_type>::type bit8_type;
void store(bit8_type value, memory_order order = memory_order_acq_rel) volatile {
interlocked_xchg_8<order>(&static_cast<atomic_type volatile*>(this)->m_value, value);
}
bit8_type load(memory_order order = memory_order_acq_rel) const volatile
{
interlocked_cmp_xchg_8<order>(
const_cast<bit8_type volatile*>(&static_cast<volatile const atomic_type *const>(this)->m_value),
static_cast<atomic_type const volatile*>(this)->m_value,
static_cast<atomic_type const volatile*>(this)->m_value
);
}
bit8_type exhange(bit8_type, memory_order order = memory_order_acq_rel) volatile {
return interlocked_xchg_8<order>(&static_cast<atomic_type volatile*>(this)->m_value, value);
}
bool compare_exchange(bit8_type comperand, bit8_type new_value, memory_order order = memory_order_acq_rel) volatile
{
return interlocked_cmp_xchg_8<order>(
&static_cast<atomic_type volatile*>(this)->m_value,
new_value,
comperand
) == comperand;
}
};
template<template<class> class atomic_type> struct interlocked<atomic_type, 2> { };
template<template<class> class atomic_type> struct interlocked<atomic_type, 4> { };
template<template<class> class atomic_type> struct interlocked<atomic_type, 8> { };
template<class T>
class atomic : public interlocked<atomic<T>> { T m_value; };
Is there anything what I'm missing or is this a "good" quite good implementation.
Thanks for any comment. Best regards:
PS:
I don't want to start a new question for this:
What's the advantage of using boost::uint32_t (in boost\cstdint.h) instead of uint32_t (in stdint.h)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的目标是 x86 硬件吗?它的缓存同步方案是否意味着您将获得完整的内存屏障?您正在如何改进这一点?
Are you targeting x86 hardware? Doesn't its cache synchronization scheme imply that full memory barriers is what you get? How are you trying to improve on that?
您在这里面临的问题是锁前缀意味着完整的内存屏障(mfence)。也就是说,因为在之前的 x86 处理器上,没有不同类型的内存屏障和单独的 sfence/lfence 指令。
The problem that you are facing here is that the lock prefix implies a full memory barrier (mfence). That is, because on the previous x86 processors there was not different kind of memory barriers and separate sfence/lfence instructions.