(22)类 _Atomic_padded《T》,该类就是可以存储一个数据:
++ 测试一下:
++ 由此可见,本 《atomic》 头文件中的内容很碎。全是一些很小的类与函数,而且都要学习与记录。
(23)模板类 _Atomic_storage_types《T》 与其特化版本:
(24) 函 _Atomic_wait_direct (),本函数可以让本线程等待,直到形参里的原子量的值发生改变。源代码如下:
template <class _Ty, size_t = sizeof(remove_reference_t<_Ty>)> // 模板类的前向声明,下面要用
struct _Atomic_storage;
#if _HAS_CXX20
template <class _Ty, class _Value_type> // 本函数会让本线程睡眠等待,直到形参 1 和 2 不等才返回
void _Atomic_wait_direct // 更准确的描述是等待原子量(形参1 ) 发生变化后才返回
( const _Atomic_storage<_Ty>* const _This, _Value_type _Expected_bytes, const memory_order _Order )
{
const auto _Storage_ptr = _STD addressof(_This->_Storage); // 形参2 可以是原子量形参1 的初值
for (;;)
{
// template <class _Integral, class _Ty> // 本函数只允许往内存变大或相等的方向转换类型
// _Integral _Atomic_reinterpret_as(const _Ty & _Source) noexcept // 不允许缩小内存范围
const _Value_type _Observed_bytes = _Atomic_reinterpret_as<_Value_type>(_This->load(_Order));
if (_Expected_bytes != _Observed_bytes) return; // 由下面的函数完成本函数的主要语义
// int __std_atomic_wait_direct( void* _Storage, void* _Comparand, size_t _Size, u_long _Remaining_timeout)
__std_atomic_wait_direct(_Storage_ptr, &_Expected_bytes, sizeof(_Value_type), _Atomic_wait_no_timeout);
// unsigned long _Atomic_wait_no_timeout = 0xFFFF'FFFF; // Pass as partial timeout
}
}
#endif // _HAS_CXX20
++完成上面函数的功能的主要函数是其调用的下列函数, C++ 里只有声明,没有定义:
++ 我们接着学习网上的对该函数介绍的资料:
++ 同时给出网上的举例代码,这只是示例代码,参考一下就可以:
#include <atomic>
#include <iostream>
#include <thread>
#include <chrono>
extern "C" { // 假设这是编译器提供的扩展函数
int _Atomic_wait_direct(volatile std::atomic<int>* object, int expected_value, int* timeout_ptr);
}
std::atomic<int> atomic_var(0); // 定义了一个原子类型的变量
void wait_thread()
{
int timeout = 1000000000; // 1秒超时,线程的睡眠等待时间
while (true) { // 本循环只进行一次
if (_Atomic_wait_direct(&atomic_var, 0, &timeout) != 0) {
std::cout << "Wait timed out or interrupted." << std::endl;
break;
}
std::cout << "Wait succeeded, new value: " << atomic_var.load() << std::endl;
break; // 假设只等待一次
}
}
void set_thread() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟一些工作
atomic_var.store(1); // 改变原子变量的值
}
int main() {
std::thread wait_t(wait_thread); std::thread set_t(set_thread);
wait_t.join(); set_t.join();
return 0;
}
(25) 按照上面的写的函数调用链, windows 平台上最终是调用 函数 WaitOnAddress ( ) 来完成 函 _Atomic_wait_direct () 的语义。 接着学习下这个最根本的函数,也是初步了解下 windows 平台上的多线程编程:
++ 给出使用该函数的代码举例:
#include <windows.h>
#include <iostream>
// 全局变量,可供所有线程访问
ULONG g_TargetValue = 0;
ULONG CapturedValue = 0;
ULONG UndesiredValue = 0;
DWORD WINAPI WaitThread(LPVOID lpParam) // 本函数在线程中执行
{
while (CapturedValue == UndesiredValue) {
// 等待g_TargetValue变为非0值
if (!WaitOnAddress(&g_TargetValue, &UndesiredValue, sizeof(ULONG), INFINITE)) {
std::cerr << "WaitOnAddress failed, error: " << GetLastError() << std::endl;
return 1;
}
CapturedValue = g_TargetValue; // 更新 CapturedValue 以反映 g_TargetValue 的新值
}
std::cout << "WaitThread: g_TargetValue changed to " << CapturedValue << std::endl;
return 0;
}
int main()
{
HANDLE hThread = CreateThread(NULL, 0, WaitThread, NULL, 0, NULL); // 创建等待线程
if (!hThread) { // 创建线程失败
std::cerr << "CreateThread failed, error: " << GetLastError() << std::endl;
return 1;
}
Sleep(1000); // 等待1秒 模拟一些工作,然后更改g_TargetValue的值
g_TargetValue = 1; // 更改全局变量的值
WaitForSingleObject(hThread, INFINITE); // 等待等待线程结束
CloseHandle(hThread); // 关闭线程句柄
return 0;
}
(26)
谢谢