Last active
August 29, 2015 14:21
-
-
Save 3noch/b680f1107c6ae769f448 to your computer and use it in GitHub Desktop.
Atomic Variables in C++ (akin to Haskell's MVar)
This file contains 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
#pragma once | |
#include <memory> | |
#include <boost/thread.hpp> | |
#include <boost/utility.hpp> | |
#include <CeFunctional.h> | |
#include <CeMemory.h> | |
#include <FunctionObject.h> | |
namespace ce | |
{ | |
template<typename T, typename Mtx, typename ScopedLock> | |
struct Locked : FunctionObject<T &> | |
{ | |
using Value = T; | |
Locked(T & t, Mtx & mtx) | |
: t_ (t) | |
, lock_(box<ScopedLock>(mtx)) {} | |
T & get() const { return t_; } | |
T & operator()() const { return t_; } | |
T & operator*() const { return t_; } | |
T * operator->() const { return &t_; } | |
private: | |
T & t_; | |
Boxed<ScopedLock> lock_; | |
}; | |
/** | |
* Wraps any type and provides a thread-safe interface to it. | |
* | |
* Modeled after Haskell's MVar (mutable variable) | |
* | |
* @tparam ConstT is the @c const form of the type. | |
*/ | |
template<typename T, typename ConstT = const T> | |
struct Atomic : private boost::noncopyable | |
{ | |
using Value = T; | |
using ConstValue = ConstT; | |
using _Mutex = boost::shared_mutex; | |
using _WriteLock = boost::unique_lock<Mutex>; | |
using _ReadLock = boost::shared_lock<Mutex>; | |
using WriteLocked = Locked<T, _Mutex, _WriteLock>; | |
using ReadLocked = Locked<ConstT, _Mutex, _ReadLock>; | |
Atomic() {} | |
Atomic(T t) : t_(t) {} | |
/** | |
* Provides thread-safe read-only access from within the provided function. | |
*/ | |
template<typename R = void> | |
R readWithR(function<R (ConstT &)> f) const | |
{ | |
_ReadLock lock(mtx_); | |
return f(t_); | |
} | |
template<typename Fn> | |
void readWith(Fn fn) const { return readWithR<void>(fn); } | |
/** | |
* Provides thread-safe read/write access from within the provided function. | |
*/ | |
template<typename R = void> | |
R writeWithR(function<R (T &)> f) | |
{ | |
_WriteLock lock(mtx_); | |
return f(t_); | |
} | |
template<typename Fn> | |
void writeWith(Fn fn) { return writeWithR<void>(fn); } | |
/** | |
* Provides thread-safe read-only access through a @c ReadLocked object. | |
* | |
* The mutex is unlocked when the @c ReadLocked object goes out of scope. | |
*/ | |
ReadLocked read() const { return ReadLocked(t_, mtx_); } | |
/** | |
* Provides thread-safe read/write access through a @c WriteLocked object. | |
* | |
* The the mutex is unlocked when the @c WriteLocked object goes out of scope. | |
*/ | |
WriteLocked write() { return WriteLocked(t_, mtx_); } | |
/** | |
* Overloaded versions of read and write. | |
*/ | |
ReadLocked use() const { return read(); } | |
WriteLocked use() { return write(); } | |
private: | |
T t_; | |
mutable _Mutex mtx_; | |
}; | |
} // namespace ce |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment