Наивное булево отрицание
std::atomic_bool b;
b = !b;
не кажется атомарным. Я подозреваю, что это потому, что operator!
запускает трансляцию в обычный bool
. Как бы атомно выполнить эквивалентное отрицание? Следующий код иллюстрирует, что наивное отрицание не является атомарным:
#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
typedef std::atomic_bool Bool;
void flipAHundredThousandTimes(Bool& foo) {
for (size_t i = 0; i < 100000; ++i) {
foo = !foo;
}
}
// Launch nThreads std::threads. Each thread calls flipAHundredThousandTimes
// on the same boolean
void launchThreads(Bool& foo, size_t nThreads) {
std::vector<std::thread> threads;
for (size_t i = 0; i < nThreads; ++i) {
threads.emplace_back(flipAHundredThousandTimes, std::ref(foo));
}
for (auto& thread : threads) thread.join();
}
int main() {
std::cout << std::boolalpha;
Bool foo{true};
// launch and join 10 threads, 20 times.
for (int i = 0; i < 20; ++i) {
launchThreads(foo, 10);
std::cout << "Result (should be true): " << foo << "\n";
}
}
Код запускает 10 потоков, каждый из которых переворачивает atom_bool larrge, даже, количество раз (100000) и выводит булев. Это повторяется 20 раз.
EDIT. Для тех, кто хочет запустить этот код, я использую моментальный снимок GCC 4.7 на ubuntu 11.10 с двумя ядрами. Возможны следующие варианты компиляции:
-std=c++0x -Wall -pedantic-errors -pthread