runsisi's

technical notes

C++ atomic_flag

2019-03-02 runsisi#cpp

只能使用如下的初始化方式将 flag 初始化成 false,任何其他初始化方法得到的值都是未定义的,且不支持赋值操作:

std::atomic_flag flag = ATOMIC_FLAG_INIT; // 1. ok
std::atomic_flag flag2(ATOMIC_FLAG_INIT); // 2. no!
std::atomic_flag flag3 = flag;            // 3. no!

ATOMIC_FLAG_INIT 定义如下,它不是一个标量(scalar type),因此这是上面第二种初始化方式不对的原因。

#define ATOMIC_FLAG_INIT {0}

只支持 test_and_set 以及 clear 这两个接口:

  • test_and_set 以原子操作的形式设置 flag 的值为 true,并返回前值;
  • clear 以原子操作的形式设置 flag 的值为 false。

示例代码如下:

#include <thread>
#include <vector>
#include <iostream>
#include <atomic>

std::atomic_flag lock = ATOMIC_FLAG_INIT;

void f(int n)
{
    for (int cnt = 0; cnt < 100; ++cnt) {
        while (lock.test_and_set(std::memory_order_acquire))  // acquire lock
             ; // spin
        std::cout << "Output from thread " << n << '\n';
        lock.clear(std::memory_order_release);               // release lock
    }
}

int main()
{
    std::vector<std::thread> v;
    for (int n = 0; n < 10; ++n) {
        v.emplace_back(f, n);
    }
    for (auto& t : v) {
        t.join();
    }
}

参考资料

C++11 Implementation of Spinlock using

https://stackoverflow.com/questions/26583433/c11-implementation-of-spinlock-using-atomic

C++11 spinlock

http://anki3d.org/spinlock/

The Atomic Flag

http://www.modernescpp.com/index.php/the-atomic-flag

Simple C11 atomics: atomic_flag

https://gustedt.wordpress.com/2012/01/22/simple-c11-atomics-atomic_flag/

std::atomic_flag

https://en.cppreference.com/w/cpp/atomic/atomic_flag