Created
August 16, 2012 16:39
-
-
Save alexeiz/3371541 to your computer and use it in GitHub Desktop.
Thread-safe one-time initialization in C++11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// C++11 has thread-safe function local statics, but this code is just | |
// to illustrate how one would do a thread-safe one-time initialization | |
// using atomic variables. | |
#include <atomic> | |
#include <thread> | |
#include <cassert> | |
#include <vector> | |
using namespace std; | |
class singleton | |
{ | |
public: | |
singleton() { ++s_count; } | |
int count() const { return s_count; } | |
private: | |
static int s_count; | |
}; | |
int singleton::s_count = 0; | |
singleton & get_object() | |
{ | |
static atomic<singleton *> object{nullptr}; | |
// this is the fast path: | |
// use only minimal required memory consistency for atomic operations here | |
if (object.load(memory_order_acquire)) | |
return *object.load(memory_order_relaxed); | |
// this is the slow path: | |
// atomic operations can be done with sequential consistency | |
static atomic<bool> initializing{false}; | |
bool expected{false}; | |
if (initializing.compare_exchange_strong(expected, true)) | |
{ | |
// static singleton s_object; | |
// object = &s_object; | |
object = new singleton(); // just for this example | |
} | |
else | |
{ | |
while (!object) | |
; | |
} | |
return *object; | |
} | |
void thr_test() | |
{ | |
singleton & s = get_object(); | |
assert(s.count() == 1); | |
} | |
int main() | |
{ | |
vector<thread> threads; | |
for (int i = 0; i != 100; ++i) | |
threads.emplace_back(thr_test); | |
for (auto & thr: threads) | |
thr.join(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment