C++11中CAS实现:
template< class T>
struct atomic
{
public:
bool compare_exchange_weak( T& expected, T desired,
std::memory_order success,
std::memory_order failure );
bool compare_exchange_weak( T& expected, T desired,
std::memory_order success,
std::memory_order failure ) volatile;
bool compare_exchange_weak( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst );
bool compare_exchange_weak( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst ) volatile;
bool compare_exchange_strong( T& expected, T desired,
std::memory_order success,
std::memory_order failure );
bool compare_exchange_strong( T& expected, T desired,
std::memory_order success,
std::memory_order failure ) volatile;
bool compare_exchange_strong( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst );
bool compare_exchange_strong( T& expected, T desired,
std::memory_order order =
std::memory_order_seq_cst ) volatile;
...
};
自动的比较*this的值和expect的值,如果相等,那么将*this的值替换为desired的值(进行读-修改-写操作)。如果不相等,那么将*this的值存到expected处。
success对应于read-modify-write的内存模型;failure则对应于失败时的load。
weak形式允许假失败,该函数直接比较原子对象所封装的值与参数 expected 的物理内容,所以某些情况下,对象的比较操作在使用 operator==() 判断时相等,但 compare_exchange_weak 判断时却可能失败,因为对象底层的物理内容中可能存在位对齐或其他逻辑表示相同但是物理表示不同的值(比如 true 和 2 或 3,它们在逻辑上都表示"真",但在物理上两者的表示并不相同)。可以虚假的返回false(和expected相同)。若本atomic的T值和expected相同则用val值替换本atomic的T值,返回true;若不同则用本atomic的T值替换expected,返回false。
strong版本的不允许(spuriously 地)返回 false,即原子对象所封装的值与参数 expected 的物理内容相同,比较操作一定会为 true。不过在某些平台下,如果算法本身需要循环操作来做检查, compare_exchange_weak 的性能会更好。因此对于某些不需要采用循环操作的算法而言, 通常采用compare_exchange_strong 更好
#ifndef TG_STACK_LOCK_FREE_H
#define TG_STACK_LOCK_FREE_H
#include <atomic>
template<typename T>
class tg_stack_lock_free
{
public:
tg_stack_lock_free():_head(nullptr)
{
}
void push(const T& data)
{
node* new_node = new node(data);
new_node->next = _head.load();
while(!_head.compare_exchange_weak(new_node->next, new_node));
}
bool pop(T& data)
{
auto result = _head.load();
while( result != nullptr && !_head.compare_exchange_weak(result,result->next));
if( !result )
{
return false;
}
data = result->data;
delete result;
return true;
}
private:
struct node
{
T data;
node* next;
node(const T& data) : data(data), next(nullptr) {}
};
std::atomic<node*> _head;
};
#endif // TG_STACK_LOCK_FREE_H