/*
* Copyright (C) Nemirtingas
* This file is part of System.
*
* System is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* System is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with System; if not, see
* .
*/
#pragma once
#include
#include
namespace System {
class scoped_lock {
struct value_holder
{
virtual ~value_holder() noexcept {}
};
template
struct templated_value_holder : value_holder
{
template
inline typename std::enable_if::type unlock(std::tuple& t) { }
template
inline typename std::enable_if::type unlock(std::tuple& t)
{
std::get(t).unlock();
unlock(t);
}
explicit templated_value_holder(Args&... mutexes) : _mutexes(mutexes...) { std::lock(mutexes...); }
explicit templated_value_holder(std::adopt_lock_t, Args&... mutexes) : _mutexes(mutexes...) {} // construct but don't lock
virtual ~templated_value_holder() noexcept { unlock(_mutexes); }
std::tuple _mutexes;
};
template
struct templated_value_holder : value_holder
{
explicit templated_value_holder(Arg& mutex) : _mutex(mutex) { _mutex.lock(); }
explicit templated_value_holder(std::adopt_lock_t, Arg& mutex) : _mutex(mutex) {} // construct but don't lock
virtual ~templated_value_holder() noexcept { _mutex.unlock(); }
Arg& _mutex;
};
value_holder* _val;
public:
template
explicit scoped_lock(Args&... mutexes) : _val(new templated_value_holder(mutexes...)) { }
template
explicit scoped_lock(std::adopt_lock_t, Args&... mutexes) : _val(new templated_value_holder(std::adopt_lock, mutexes...)) { }
explicit scoped_lock(scoped_lock && other):
_val(other._val)
{
other._val = nullptr;
}
scoped_lock() noexcept:
_val(nullptr)
{}
~scoped_lock() noexcept { delete _val; }
scoped_lock& operator=(scoped_lock && other)
{
_val = other._val;
other._val = nullptr;
return *this;
}
scoped_lock(const scoped_lock&) = delete;
scoped_lock& operator=(const scoped_lock&) = delete;
};
}