/* * 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; }; }