std::atomic_flag
Материал из cppreference.com
<tbody>
</tbody>
| Определено в заголовочном файле <atomic>
|
||
class atomic_flag; |
(начиная с C++11) | |
std::atomic_flag атомарный логический тип. В отличие от всех специализаций std::atomic, он гарантированно свободен от блокировок. В отличие от std::atomic<bool>, std::atomic_flag не предоставляет операций load или store.
Функции-элементы
| создаёт atomic_flag (public функция-элемент) | |
| оператор присваивания (public функция-элемент) | |
атомарно устанавливает флаг в false (public функция-элемент) | |
атомарно устанавливает флаг в true и получает его предыдущее значение (public функция-элемент) | |
(C++20) |
атомарно возвращает значение флага (public функция-элемент) |
| блокирует поток до тех пор, пока не получит уведомление и не изменится атомарное значение (public функция-элемент) | |
| уведомляет хотя бы один поток, ожидающий атомарный объект (public функция-элемент) | |
| уведомляет все потоки, заблокированные в ожидании атомарного объекта (public функция-элемент) |
Пример
Демонстрация мьютекса спин-блокировки может быть реализована в пользовательском пространстве с помощью atomic_flag. Обратите внимание, что мьютексы спин-блокировки крайне сомнительны на практике.
Запустить этот код
#include <thread>
#include <vector>
#include <iostream>
#include <atomic>
std::atomic_flag lock = ATOMIC_FLAG_INIT;
void f(int n)
{
for (int cnt = 0; cnt < 40; ++cnt) {
while (lock.test_and_set(std::memory_order_acquire)) { // запрос блокировки
// Начиная с C++20, можно обновить значение atomic_flag
// только тогда, когда есть возможность получить блокировку.
// Смотрите также: https://stackoverflow.com/questions/62318642
#if defined(__cpp_lib_atomic_flag_test)
while (lock.test(std::memory_order_relaxed)) // тестирование блокировки
#endif
; // spin
}
static int out{};
std::cout << n << ((++out % 40) == 0 ? '\n' : ' ');
lock.clear(std::memory_order_release); // освобождение блокировки
}
}
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();
}
}
Возможный вывод:
0 1 1 2 0 1 3 2 3 2 0 1 2 3 2 3 0 1 3 2 0 1 2 3 2 3 0 3 2 3 2 3 2 3 1 2 3 0 1 3
2 3 2 0 1 2 3 0 1 2 3 2 0 1 2 3 0 1 2 3 2 3 2 3 2 0 1 2 3 2 3 0 1 3 2 3 0 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 3 2 0 2 3 2 3 2 3 2 3 2 3 0 3
2 3 0 3 0 3 2 3 0 3 2 3 2 3 0 2 3 0 3 2 0 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
Смотрите также
атомарно устанавливает флаг в true и возвращает его предыдущее значение (функция) | |
(C++11)(C++11) |
атомарно устанавливает значение флага в false (функция) |
(C++20)(C++20) |
блокирует поток до тех пор, пока не получит уведомление и не изменится флаг (функция) |
(C++20) |
уведомляет поток, заблокированный в atomic_flag_wait (функция) |
(C++20) |
уведомляет все потоки, заблокированные в atomic_flag_wait (функция) |
(C++11) |
инициализирует std::atomic_flag значением false (макроконстанта) |
Документация C по atomic_flag
| |