| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 | 
							- #pragma once
 
- #include <atomic>
 
- #include <mutex>
 
- #include <thread>
 
- #include <cinttypes>
 
- // left_right based on
 
- // https://github.com/pramalhe/ConcurrencyFreaks/blob/master/papers/left-right-2014.pdf
 
- // see concurrencyfreaks.com
 
- namespace left_right {
 
- template<typename T> struct left_right {
 
- 	template<typename Func> void update(Func &&f)
 
- 	{
 
- 		std::lock_guard<std::mutex> lock(write_mutex);
 
- 		auto cur = current.load();
 
- 		auto next = (cur + 1) & 1;
 
- 		while (readers[next] != 0)
 
- 			std::this_thread::yield();
 
- 		f(data[next]);
 
- 		current = (std::uint_fast8_t)next;
 
- 		while (readers[cur] != 0)
 
- 			std::this_thread::yield();
 
- 		f(data[cur]);
 
- 	}
 
- 	T read()
 
- 	{
 
- 		auto cur = current.load();
 
- 		for (;;) {
 
- 			readers[cur] += 1;
 
- 			auto cur_ = current.load();
 
- 			if (cur_ == cur)
 
- 				break;
 
- 			readers[cur] -= 1;
 
- 			cur = cur_;
 
- 		}
 
- 		auto val = data[cur];
 
- 		readers[cur] -= 1;
 
- 		return val;
 
- 	}
 
- private:
 
- 	std::atomic_uint_fast8_t current;
 
- 	std::atomic_long readers[2];
 
- 	std::mutex write_mutex;
 
- 	T data[2] = {{}, {}};
 
- };
 
- }
 
 
  |