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.