Как атомарно отменить std::atomic_bool?

Наивное логическое отрицание

std::atomic_bool b;
b = !b;

не кажется атомарным. Я подозреваю, что это потому, что оператор ! запускает приведение к простому 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 потоков, каждый из которых переворачивает atomic_bool большое четное число раз (100000) и выводит логическое значение. Это повторяется 20 раз.

РЕДАКТИРОВАТЬ: Для тех, кто хочет запустить этот код, я использую моментальный снимок GCC 4.7 на Ubuntu 11.10 с двумя ядрами. Варианты компиляции:

-std=c++0x -Wall -pedantic-errors -pthread
40
задан juanchopanza 21 March 2012 в 15:29
поделиться