Skip to content

Instantly share code, notes, and snippets.

@3noch
Last active August 29, 2015 14:21
Show Gist options
  • Save 3noch/b680f1107c6ae769f448 to your computer and use it in GitHub Desktop.
Save 3noch/b680f1107c6ae769f448 to your computer and use it in GitHub Desktop.
Atomic Variables in C++ (akin to Haskell's MVar)
#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