YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
guard_sticky.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <yaclib/config.hpp>
7
8namespace yaclib {
9namespace detail {
10
11template <typename M>
13 public:
14 explicit LockStickyAwaiter(M& m, IExecutor*& e) noexcept : _mutex{m}, _executor{e} {
15 }
16
17 YACLIB_INLINE bool await_ready() noexcept {
18 _executor = nullptr;
19 return _mutex.TryLockAwait();
20 }
21
22 template <typename Promise>
23 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
24 auto& promise = handle.promise();
25 _executor = promise._executor.Get();
26 if (_mutex.AwaitLock(promise)) {
27 return true;
28 }
29 _executor = nullptr;
30 return false;
31 }
32
33 constexpr void await_resume() noexcept {
34 }
35
36 protected:
39};
40
41template <typename M>
43 public:
44 explicit UnlockStickyAwaiter(M& m, IExecutor* e) noexcept : _mutex{m}, _executor{e} {
45 }
46
47 YACLIB_INLINE bool await_ready() noexcept {
48 if (_executor != nullptr) {
49 return false;
50 }
51 _mutex.UnlockHere();
52 return true;
53 }
54
55 template <typename Promise>
56 YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
57 YACLIB_ASSERT(_executor != nullptr);
58 return _mutex.AwaitUnlockOn(handle.promise(), *_executor);
59 }
60
61 constexpr void await_resume() noexcept {
62 }
63
64 private:
65 M& _mutex;
66 IExecutor* _executor;
67};
68
69template <typename>
70class GuardStickyAwaiter;
71;
72} // namespace detail
73
74template <typename M>
75class [[nodiscard]] StickyGuard : public detail::Guard<M, false> {
77
78 public:
79 using MutexType = M;
80 using Base::Base;
81
82 StickyGuard(StickyGuard&& other) noexcept : Base{std::move(other)}, _executor{other._executor} {
83 }
84
86 Swap(other);
87 return *this;
88 }
89
90 auto Lock() noexcept {
91 auto* m = static_cast<M*>(Base::LockState());
92 auto& base = M::template Cast<typename M::Base>(*m);
93 return detail::LockStickyAwaiter{base, _executor};
94 }
95
97 auto* m = static_cast<M*>(Base::UnlockState());
98 auto& base = M::template Cast<typename M::Base>(*m);
99 return detail::UnlockStickyAwaiter{base, _executor};
100 }
101
102 void Swap(StickyGuard& other) noexcept {
103 Base::Swap(other);
104 std::swap(_executor, other._executor);
105 }
106
107 private:
108 IExecutor* _executor = nullptr;
109
110 template <typename>
112};
113
114namespace detail {
115
116template <typename M>
118 public:
119 explicit GuardStickyAwaiter(M& m) : _guard{m, std::adopt_lock} {
120 }
121
122 YACLIB_INLINE bool await_ready() noexcept {
123 auto& mutex_impl = M::template Cast<typename M::Base>(*_guard.Mutex());
124 LockStickyAwaiter awaiter{mutex_impl, _guard._executor};
125 return awaiter.await_ready();
126 }
127
128 template <typename Promise>
129 YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
130 auto& mutex_impl = M::template Cast<typename M::Base>(*_guard.Mutex());
131 LockStickyAwaiter awaiter{mutex_impl, _guard._executor};
132 return awaiter.await_suspend(handle);
133 }
134
135 YACLIB_INLINE auto await_resume() noexcept {
136 YACLIB_ASSERT(_guard);
137 return std::move(_guard);
138 }
139
140 private:
141 StickyGuard<M> _guard;
142};
143
144} // namespace detail
145} // namespace yaclib
StickyGuard(StickyGuard &&other) noexcept
auto Lock() noexcept
StickyGuard & operator=(StickyGuard &&other) noexcept
auto Unlock() noexcept
void Swap(StickyGuard &other) noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
YACLIB_INLINE auto await_resume() noexcept
YACLIB_INLINE bool await_ready() noexcept
YACLIB_INLINE bool await_ready() noexcept
YACLIB_INLINE bool await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
constexpr void await_resume() noexcept
LockStickyAwaiter(M &m, IExecutor *&e) noexcept
YACLIB_INLINE bool await_ready() noexcept
constexpr void await_resume() noexcept
YACLIB_INLINE auto await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
UnlockStickyAwaiter(M &m, IExecutor *e) noexcept
#define YACLIB_ASSERT(cond)
Definition log.hpp:85
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25