Skip to content

Instantly share code, notes, and snippets.

/concurrency.cpp Secret

Created March 26, 2017 00:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/eb6d02a2c383936d2f0d2ec005aaa19a to your computer and use it in GitHub Desktop.
Save anonymous/eb6d02a2c383936d2f0d2ec005aaa19a to your computer and use it in GitHub Desktop.
#include <type_traits>
#include <atomic>
#include <thread>
#include <mutex>
#include <random>
#include <new>
#include <iostream>
#include <functional>
using namespace std;
template<class T> struct fearless {
static_assert(is_nothrow_copy_constructible_v<T>);
static_assert(is_nothrow_destructible_v<T>);
atomic_uint state{ 0 };
aligned_storage_t<sizeof(T), alignof(T)> data[2];
void spooky_action(T& my_value) {
T* ptr = reinterpret_cast<T*>(data);
auto i = state.fetch_add(1, memory_order_relaxed);
if (i != 2) {
new (ptr + i) T{ my_value };
if (state.fetch_add(1, memory_order_release) != 3)
return;
(ptr + i)->~T();
ptr += 1-i;
}
atomic_thread_fence(memory_order_acquire);
my_value.~T();
new (&my_value) T{ *ptr };
ptr->~T();
}
};
void the_function(fearless<mt19937>& f, mutex& mtx) {
random_device r;
seed_seq seed{ r(), r(), r(), r(), r(), r(), r() };
mt19937 rng{ seed };
f.spooky_action(rng);
auto result = rng();
lock_guard<mutex> g{ mtx };
cout << "-> " << result;
cout << " (thd " << this_thread::get_id() << ")";
cout << endl;
}
int main() {
cout << "two threads, one result:" << endl;
fearless<mt19937> f; mutex mtx;
thread thd{ the_function, ref(f), ref(mtx) };
the_function(f, mtx);
thd.join();
cout << "spooky :S" << endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment