HelenOS sources
This source file includes following definitions.
- try_lock_for
- try_lock_until
- try_lock_for
- try_lock_until
- lock
- try_lock
- try_lock_for
- try_lock_until
- unlock
- swap
- release
- owns_lock
- swap
- try_lock_tail
- try_lock_tail
- try_lock
- lock_tail
- lock_tail
- lock
- call_once
#ifndef LIBCPP_BITS_THREAD_MUTEX
#define LIBCPP_BITS_THREAD_MUTEX
#include <__bits/thread/threading.hpp>
#include <functional>
#include <thread>
namespace std
{
class mutex
{
public:
constexpr mutex() noexcept
: mtx_{}
{
aux::threading::mutex::init(mtx_);
}
~mutex() = default;
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
void lock();
bool try_lock();
void unlock();
using native_handle_type = aux::mutex_t*;
native_handle_type native_handle();
private:
aux::mutex_t mtx_;
};
class recursive_mutex
{
public:
constexpr recursive_mutex() noexcept
: mtx_{}, lock_level_{}, owner_{}
{
aux::threading::mutex::init(mtx_);
}
~recursive_mutex();
recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete;
void lock();
bool try_lock() noexcept;
void unlock();
using native_handle_type = aux::mutex_t*;
native_handle_type native_handle();
private:
aux::mutex_t mtx_;
size_t lock_level_;
thread::id owner_;
};
class timed_mutex
{
public:
timed_mutex() noexcept;
~timed_mutex();
timed_mutex(const timed_mutex&) = delete;
timed_mutex& operator=(const timed_mutex&) = delete;
void lock();
bool try_lock();
void unlock();
template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
auto time = aux::threading::time::convert(rel_time);
return aux::threading::mutex::try_lock_for(time);
}
template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
auto dur = (abs_time - Clock::now());
auto time = aux::threading::time::convert(dur);
return aux::threading::mutex::try_lock_for(time);
}
using native_handle_type = aux::mutex_t*;
native_handle_type native_handle();
private:
aux::mutex_t mtx_;
};
class recursive_timed_mutex
{
public:
recursive_timed_mutex() noexcept
: mtx_{}, lock_level_{}, owner_{}
{
aux::threading::mutex::init(mtx_);
}
~recursive_timed_mutex();
recursive_timed_mutex(const recursive_timed_mutex&) = delete;
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
void lock();
bool try_lock() noexcept;
void unlock();
template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
if (owner_ == this_thread::get_id())
return true;
auto time = aux::threading::time::convert(rel_time);
auto ret = aux::threading::mutex::try_lock_for(time);
if (ret)
++lock_level_;
return ret;
}
template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
if (owner_ == this_thread::get_id())
return true;
auto dur = (abs_time - Clock::now());
auto time = aux::threading::time::convert(dur);
auto ret = aux::threading::mutex::try_lock_for(time);
if (ret)
++lock_level_;
return ret;
}
using native_handle_type = aux::mutex_t*;
native_handle_type native_handle();
private:
aux::mutex_t mtx_;
size_t lock_level_;
thread::id owner_;
};
struct defer_lock_t
{ };
struct try_to_lock_t
{ };
struct adopt_lock_t
{ };
constexpr defer_lock_t defer_lock
{ };
constexpr try_to_lock_t try_to_lock
{ };
constexpr adopt_lock_t adopt_lock
{ };
template<class Mutex>
class lock_guard
{
public:
using mutex_type = Mutex;
explicit lock_guard(mutex_type& mtx)
: mtx_{mtx}
{
mtx.lock();
}
lock_guard(mutex_type& mtx, adopt_lock_t)
: mtx_{mtx}
{ }
~lock_guard()
{
mtx_.unlock();
}
lock_guard(const lock_guard&) = delete;
lock_guard& operator=(const lock_guard&) = delete;
private:
mutex_type& mtx_;
};
template<class Mutex>
class unique_lock
{
public:
using mutex_type = Mutex;
unique_lock() noexcept
: mtx_{nullptr}, owns_{false}
{ }
explicit unique_lock(mutex_type& mtx)
: mtx_{&mtx}, owns_{true}
{
mtx_->lock();
}
unique_lock(mutex_type& mtx, defer_lock_t) noexcept
: mtx_{&mtx}, owns_{false}
{ }
unique_lock(mutex_type& mtx, try_to_lock_t)
: mtx_{&mtx}, owns_{}
{
owns_ = mtx_->try_lock();
}
unique_lock(mutex_type& mtx, adopt_lock_t)
: mtx_{&mtx}, owns_{true}
{ }
template<class Clock, class Duration>
unique_lock(mutex_type& mtx, const chrono::time_point<Clock, Duration>& abs_time)
: mtx_{&mtx}, owns_{}
{
owns_ = mtx_->try_lock_until(abs_time);
}
template<class Rep, class Period>
unique_lock(mutex_type& mtx, const chrono::duration<Rep, Period>& rel_time)
: mtx_{&mtx}, owns_{}
{
owns_ = mtx_->try_lock_for(rel_time);
}
~unique_lock()
{
if (owns_)
mtx_->unlock();
}
unique_lock(const unique_lock&) = delete;
unique_lock& operator=(const unique_lock&) = delete;
unique_lock(unique_lock&& other) noexcept
: mtx_{move(other.mtx_)}, owns_{move(other.owns_)}
{
other.mtx_ = nullptr;
other.owns_ = false;
}
unique_lock& operator=(unique_lock&& other)
{
if (owns_)
mtx_->unlock();
mtx_ = move(other.mtx_);
owns_ = move(other.owns_);
other.mtx_ = nullptr;
other.owns_ = false;
}
void lock()
{
mtx_->lock();
owns_ = true;
}
bool try_lock()
{
owns_ = mtx_->try_lock();
return owns_;
}
template<class Rep, class Period>
bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
{
owns_ = mtx_->try_lock_for(rel_time);
return owns_;
}
template<class Clock, class Duration>
bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
{
owns_ = mtx_->try_lock_until(abs_time);
return owns_;
}
void unlock()
{
mtx_->unlock();
}
void swap(unique_lock& other) noexcept
{
std::swap(mtx_, other.mtx_);
std::swap(owns_, other.owns_);
}
mutex_type* release() noexcept
{
auto ret = mtx_;
mtx_ = nullptr;
owns_ = false;
return ret;
}
bool owns_lock() const noexcept
{
return owns_;
}
explicit operator bool() const noexcept
{
return owns_;
}
mutex_type* mutex() const noexcept
{
return mtx_;
}
private:
mutex_type* mtx_;
bool owns_;
};
template<class Mutex>
void swap(unique_lock<Mutex>& lhs, unique_lock<Mutex>& rhs) noexcept
{
lhs.swap(rhs);
}
namespace aux
{
template<class L>
int try_lock_tail(int idx, L& l)
{
if (!l.try_lock())
return idx;
else
return -1;
}
template<class L1, class... L2>
int try_lock_tail(int idx, L1& l1, L2&... ls)
{
if (!l1.try_lock())
return idx;
auto ret = try_lock_tail(idx + 1, ls...);
if (ret != -1)
l1.unlock();
return ret;
}
}
template<class L1, class L2, class... L3>
int try_lock(L1& l1, L2& l2, L3&... ls)
{
return aux::try_lock_tail(0, l1, l2, ls...);
}
namespace aux
{
template<class L>
bool lock_tail(L& l)
{
return l.try_lock();
}
template<class L1, class... L2>
bool lock_tail(L1& l1, L2&... ls)
{
if (l1.try_lock())
{
auto ret = lock_tail(ls...);
if (ret)
return true;
l1.unlock();
}
return false;
}
}
template<class L1, class L2, class... L3>
void lock(L1& l1, L2& l2, L3&... ls)
{
do
{
l1.lock();
if (aux::lock_tail(l2, ls...))
return;
l1.unlock();
} while (true);
}
struct once_flag
{
constexpr once_flag() noexcept
: called_{false}, mtx_{}
{ }
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
private:
bool called_;
mutex mtx_;
template<class Callable, class... Args>
friend void call_once(once_flag&, Callable&&, Args&&...);
};
template<class Callable, class... Args>
void call_once(once_flag& flag, Callable&& func, Args&&... args)
{
flag.mtx_.lock();
if (!flag.called_)
{
aux::INVOKE(forward<Callable>(func), forward<Args>(args)...);
flag.called_ = true;
}
flag.mtx_.unlock();
}
}
#endif
HelenOS homepage, sources at GitHub