Simple mutexes with lambdas


I absolutely love lambdas.

A very nice use case for lambdas popped up while I was working with mutexes. Albeit simple, it makes sure you can't forget to unlock a resource that is hidden behind a mutex, and it also makes sure you don't forget to lock it.

Of course, there are a number of locks in the standard library that utilise RAII, but sometimes you want to lock the mutex without creating a new scope, and without keeping the lock for the entirety of the current scope.

Very small and very simple:

template<typename T>
class ConcurrentData
{
mutable std::mutex mutex;
T data;

public:
template<typename F>
void modify(F func)
{
std::lock_guard lock(mutex);
func(std::ref(data));
}

template<typename F>
void view(F func) const
{
std::lock_guard lock(mutex);
func(std::cref(data));
}
};

And in case the data should be waitable, a hold function can be introduced, which lets the user call condition.wait by supplying the unique_lock:

template<typename T>
class WaitableConcurrentData
{
mutable std::mutex mutex;
std::condition_variable condition;
T data;

public:
template<typename F>
void modify(F func)
{
std::lock_guard lock(mutex);
func(std::ref(data));
}

template<typename F>
void hold(F func)
{
std::unique_lock lock(mutex);
func(lock, condition, std::ref(data));
}

template<typename F>
void view(F func) const
{
std::lock_guard lock(mutex);
func(std::cref(data));
}

void notify()
{
condition.notify_all();
}
};

Two small examples of - I'm sure - a very common pattern. One downside, which is just a general downside with lambdas in C++, is that autocompletion will not be able to tell you the signature of the template parameter F. Oh well.