From 90d6f8bf62bca97dc911b30505252becd8ef7520 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 13 Oct 2014 18:52:45 -0400 Subject: Adding libglim as an external library libglim is an Apache-licensed C++ wrapper for lmdb, and rather than rolling our own it seems prudent to use it. Note: lmdb is not included in it, and unless something happens as did with libunbound, should be installed via each OS' package manager or equivalent. --- external/glim/channel.hpp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 external/glim/channel.hpp (limited to 'external/glim/channel.hpp') diff --git a/external/glim/channel.hpp b/external/glim/channel.hpp new file mode 100644 index 000000000..e5ca23bdf --- /dev/null +++ b/external/glim/channel.hpp @@ -0,0 +1,40 @@ +#ifndef _GLIM_CHANNEL_INCLUDED +#define _GLIM_CHANNEL_INCLUDED + +#include +#include +#include + +namespace glim { + +/// Unbuffered channel. +/// Optimized for a single value (busy-waits on a second one). +template +struct Channel { + V _v; + std::mutex _mutex; // Locked when there is no value. + std::atomic_int_fast8_t _state; enum State {EMPTY = 0, WRITING = 1, FULL = 2}; + Channel(): _state (EMPTY) {_mutex.lock();} + // Waits until the Channel is empty then stores the value. + template void send (VA&& v) { + for (;;) { + int_fast8_t expectEmpty = EMPTY; if (_state.compare_exchange_weak (expectEmpty, WRITING)) break; + std::this_thread::sleep_for (std::chrono::milliseconds (20)); + } + try {_v = std::forward (v);} catch (...) {_state = EMPTY; throw;} + _state = FULL; + _mutex.unlock(); // Allows the reader to proceed. + } + // Waits untill there is a value to receive. + V receive() { + _mutex.lock(); // Wait. + V tmp = std::move (_v); + assert (_state == FULL); + _state = EMPTY; + return tmp; + } +}; + +} // namespace glim + +#endif -- cgit v1.2.3