#include <iostream>
#include<atomic>
//为了对自定义类型 (UDT) 使用 std::atomic<>,这个类型必须有一个微不足道的拷贝赋值运算符。
// 因此类型不能有虚函数或虚基类,且必须使用编译器生成的拷贝赋值运算符,
// 自定义类型的每个基类和非静态数据成员也必须有一个微不足道的拷贝赋值运算符。这允许编译器使用 memcpy() 或等效操作进行赋值操作
//自定义类型的接口和std::atomic<bool>类型一样
class MyClass {
private:
float val;//浮点类型没有提供标准的原子类型
int flag;
public:
//如果显式添加了空参构造函数,系统旧不会生成operator=,也就无法使用atomic封装,因为它要求至少有一个operator=
#if 0
MyClass() {}
#endif
MyClass(float val = 0.0f,int flag =0):val(val),flag(flag) {} //可以有赋值的构造函数
//如果自定义了拷贝构造函数,那么系统也会自动生成一个拷贝运算符(功能和拷贝构造一样),但atomic要求的拷贝构造必须是类似memcpy的微小拷贝
#if 0
MyClass(const MyClass& other) :val(other.val),flag (other.flag){}//可以有拷贝构造函数
#endif
bool operator ==(const MyClass& other)const {
return val == other.val; //忽略flag
}
#if 0
//不能有拷贝赋值运算符
MyClass& operator =(MyClass &other) {
return *this;
}
#endif
//也不能删除,必须使用系统自带的拷贝赋值运算符
#if 0
MyClass& operator=(MyClass&) = delete;
#endif
};
void Test() {
std::atomic<MyClass>atomicValue;
std::cout<<"原子操作是否为无锁的:"<< (atomicValue.is_lock_free() ? "true" : "false") << "\n";
atomicValue.store(MyClass(1.0f,0 ));
MyClass oldVal(MyClass(1.0f, 1)); //旧值
MyClass newVal(MyClass(1.0f, 0)); //新值
bool equal = oldVal == newVal;
std::cout << "oldVal == newVal,在值上相同:" << (equal ? "true" : "false") << "\n";
//这里不会调用operator==,而是会调用二进制的内存比较,即使用 memcmp 进行比较
bool status = atomicValue.compare_exchange_strong(oldVal, newVal);
if (!status) {
std::cout << "compare_exchange_strong 操作失败。" << "\n";
std::cout << "存储的值和旧的值在value上相等,但在表示形式上不相等。" << "\n";
}
else {
std::cout << "compare_exchange_strong 操作成功。" << "\n";
}
atomicValue.store(MyClass(1.0f, 1));
oldVal = MyClass(1.0f, 1); //旧值
status = atomicValue.compare_exchange_strong(oldVal, newVal); //这里不会调用operator==
if (!status) {
std::cout << "compare_exchange_strong 操作失败。" << "\n";
std::cout << "存储的值和旧的值在value上相等,但在表示形式上不相等。" << "\n";
}
else {
std::cout << "compare_exchange_strong 操作成功。" << "\n";
}
}
int main(){
Test();
return 0;
}
04-23
279
02-02
2602