Program Listing for File lock_policy.h
↰ Return to documentation for file (liberate/concurrency/lock_policy.h
)
/*
* This file is part of liberate.
*
* Author(s): Jens Finkhaeuser <jens@finkhaeuser.de>
*
* Copyright (c) 2021 Jens Finkhaeuser.
* Copyright (c) 2022 Interpeer gUG (haftungsbeschränkt)
*
* SPDX-License-Identifier: GPL-3.0-only
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBERATE_CONCURRENCY_LOCK_POLICY_H
#define LIBERATE_CONCURRENCY_LOCK_POLICY_H
#ifndef __cplusplus
#error You are trying to include a C++ only header file
#endif
#include <liberate.h>
#include <memory>
namespace liberate::concurrency {
namespace detail {
struct null_mutex
{
};
template <typename mutexT>
struct null_lock
{
template <typename discardT>
inline null_lock(discardT &)
{
}
};
template<class T, class R = void>
struct enable_if_smart_ptr_type { typedef R type; };
template<class T, class Enable = void>
struct is_smart_ptr : std::false_type {};
template<class T>
struct is_smart_ptr<
T,
typename enable_if_smart_ptr_type<
typename T::element_type
>::type
> : std::true_type
{};
template <typename mutex_ptrT, typename lockT>
struct mutex_ptr_lock_proxy
{
template <typename... argsT>
inline mutex_ptr_lock_proxy( mutex_ptrT & mutex_ptr, argsT &&... args)
: m_lock{*mutex_ptr, std::forward<argsT>(args)...}
{
}
static inline lockT & lock_ref(mutex_ptr_lock_proxy & proxy)
{
return proxy.m_lock;
}
lockT m_lock;
};
template <
typename mutexT,
typename lockT,
bool IS_POINTER,
bool IS_SMART_POINTER
>
struct lock_selector
{
// Also selected for IS_POINTER && IS_SMART_POINTER, which should never
// happen, so it's good that it fails.
};
template <
typename mutexT,
typename lockT
>
struct lock_selector<mutexT, lockT, false, false>
{
using mutex_type = mutexT;
using lock_type = lockT;
static inline lockT & lock_ref(lockT & lock)
{
return lock;
}
};
template <
typename mutexT,
typename lockT
>
struct lock_selector<mutexT, lockT, true, false>
{
using mutex_type = mutexT;
using lock_type = mutex_ptr_lock_proxy<
mutexT, lockT
>;
static inline lockT & lock_ref(lockT & lock)
{
return lock_type::lock_ref(lock);
}
};
template <
typename mutexT,
typename lockT
>
struct lock_selector<mutexT, lockT, false, true>
{
using mutex_type = mutexT;
using lock_type = mutex_ptr_lock_proxy<
mutexT, lockT
>;
static inline lockT & lock_ref(lockT & lock)
{
return lock_type::lock_ref(lock);
}
};
} // namespace detail
struct null_lock_policy
{
using mutex_type = detail::null_mutex;
using lock_type = detail::null_lock<mutex_type>;
using _passed_lock_type = lock_type;
};
template <typename mutexT, typename lockT>
struct lock_policy
{
using _selector = detail::lock_selector<
mutexT,
lockT,
std::is_pointer<mutexT>::value,
detail::is_smart_ptr<mutexT>::value
>;
using mutex_type = typename _selector::mutex_type;
using lock_type = typename _selector::lock_type;
using _passed_lock_type = lockT;
};
template <typename lock_policyT>
inline typename lock_policyT::_passed_lock_type &
lock_ref(typename lock_policyT::lock_type & lock)
{
return lock_policyT::_selector::lock_ref(lock);
}
template <>
inline typename null_lock_policy::_passed_lock_type &
lock_ref<null_lock_policy>(typename null_lock_policy::lock_type & lock)
{
return lock;
}
} // namespace liberate::concurrency
#endif // guard