8#include <userver/engine/mutex.hpp>
10USERVER_NAMESPACE_BEGIN
16template <
typename Lock,
typename Data>
17class LockedPtr final {
19 using Mutex =
typename Lock::mutex_type;
21 LockedPtr(Mutex& mutex, Data& data) : lock_(mutex), data_(data) {}
22 LockedPtr(Lock&& lock, Data& data) : lock_(std::move(lock)), data_(data) {}
24 Data& operator*() & {
return data_; }
25 const Data& operator*()
const& {
return data_; }
28 Data&
operator*() && {
return *GetOnRvalue(); }
30 Data* operator->() & {
return &data_; }
31 const Data* operator->()
const& {
return &data_; }
34 Data*
operator->() && {
return GetOnRvalue(); }
36 Lock& GetLock() {
return lock_; }
39 const Data* GetOnRvalue() {
40 static_assert(!
sizeof(Data),
41 "Don't use temporary LockedPtr, store it to a variable");
58template <
typename Data,
typename Mutex = engine::Mutex>
61 template <
typename... Arg>
62 Variable(Arg&&... arg) : data_(std::forward<Arg>(arg)...) {}
64 LockedPtr<std::unique_lock<Mutex>, Data> UniqueLock() {
65 return {mutex_, data_};
68 LockedPtr<std::unique_lock<Mutex>,
const Data> UniqueLock()
const {
69 return {mutex_, data_};
72 std::optional<LockedPtr<std::unique_lock<Mutex>,
const Data>> UniqueLock(
73 std::try_to_lock_t)
const {
74 return DoUniqueLock(*
this, std::try_to_lock);
77 std::optional<LockedPtr<std::unique_lock<Mutex>, Data>> UniqueLock(
79 return DoUniqueLock(*
this, std::try_to_lock);
82 std::optional<LockedPtr<std::unique_lock<Mutex>,
const Data>> UniqueLock(
83 std::chrono::milliseconds try_duration)
const {
84 return DoUniqueLock(*
this, try_duration);
87 std::optional<LockedPtr<std::unique_lock<Mutex>, Data>> UniqueLock(
88 std::chrono::milliseconds try_duration) {
89 return DoUniqueLock(*
this, try_duration);
92 LockedPtr<std::shared_lock<Mutex>,
const Data> SharedLock()
const {
93 return {mutex_, data_};
96 LockedPtr<std::lock_guard<Mutex>, Data> Lock() {
return {mutex_, data_}; }
98 LockedPtr<std::lock_guard<Mutex>,
const Data> Lock()
const {
99 return {mutex_, data_};
112 const Data& GetDataUnsafe()
const {
return data_; }
115 mutable Mutex mutex_;
122 template <
typename VariableType,
typename... StdUniqueLockArgs>
123 static auto DoUniqueLock(VariableType& concurrent_variable,
124 StdUniqueLockArgs&&... args) {
125 std::unique_lock<Mutex> lock(concurrent_variable.mutex_,
126 std::forward<StdUniqueLockArgs>(args)...);
127 return lock ? std::optional{LockedPtr{std::move(lock),
128 concurrent_variable.data_}}