YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
await_on_awaiter.hpp
Go to the documentation of this file.
1#pragma once
2
9
10namespace yaclib::detail {
11
12template <bool Single>
14 std::conditional_t<Single, OneCounter<NopeBase, NopeDeleter>, AtomicCounter<NopeBase, NopeDeleter>>;
15
16template <bool Single>
17class AwaitOnEvent final : public InlineCore, public AwaitOnCounterT<Single> {
18 public:
19 explicit AwaitOnEvent(std::size_t n) noexcept : AwaitOnCounterT<Single>{n} {
20 }
21
22 BaseCore* job{nullptr};
23
24 private:
25 template <bool SymmetricTransfer>
26 [[nodiscard]] YACLIB_INLINE auto Impl(InlineCore& /*caller*/) noexcept {
27 if constexpr (Single) {
29 } else {
30 if (this->SubEqual(1)) {
31 YACLIB_ASSERT(job != nullptr);
33 }
34 }
36 }
37 [[nodiscard]] InlineCore* Here(InlineCore& caller) noexcept final {
38 return Impl<false>(caller);
39 }
40#if YACLIB_SYMMETRIC_TRANSFER != 0
41 [[nodiscard]] yaclib_std::coroutine_handle<> Next(InlineCore& caller) noexcept final {
42 return Impl<true>(caller);
43 }
44#endif
45};
46
47template <bool Single>
49 explicit AwaitOnAwaiter(IExecutor& e, BaseCore& caller) noexcept : _executor{e}, _event{1} {
50 _event.job = &caller;
51 }
52
53 constexpr bool await_ready() const noexcept {
54 return false;
55 }
56
57 template <typename Promise>
58 YACLIB_INLINE void await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
59 auto& core = handle.promise();
60 core._executor = &_executor;
61 auto* caller = _event.job;
62 _event.job = &core;
63
64 if (!caller->SetCallback(_event)) {
65 _executor.Submit(core);
66 }
67 }
68
69 constexpr void await_resume() const noexcept {
70 }
71
72 private:
73 IExecutor& _executor;
74 AwaitOnEvent<true> _event;
75};
76
77template <>
79 public:
80 template <typename... Cores>
81 explicit AwaitOnAwaiter(IExecutor& e, Cores&... cores) noexcept;
82
83 template <typename It>
84 explicit AwaitOnAwaiter(IExecutor& e, It it, std::size_t count) noexcept;
85
86 constexpr bool await_ready() const noexcept {
87 return false;
88 }
89
90 template <typename Promise>
91 YACLIB_INLINE void await_suspend(yaclib_std::coroutine_handle<Promise> handle) noexcept {
92 auto& core = handle.promise();
93 core._executor = &_executor;
94 _event.job = &core;
95
96 if (_event.SubEqual(1)) {
97 _executor.Submit(core);
98 }
99 }
100
101 constexpr void await_resume() const noexcept {
102 }
103
104 private:
105 IExecutor& _executor;
106 AwaitOnEvent<false> _event;
107};
108
109template <typename... Cores>
111 : _executor{e}, _event{sizeof...(cores) + 1} {
112 static_assert(sizeof...(cores) >= 2, "Number of futures must be at least two");
113 static_assert((... && std::is_same_v<BaseCore, Cores>), "Futures must be Future in Wait function");
114 const auto wait_count = (... + static_cast<std::size_t>(cores.SetCallback(_event)));
115 _event.count.fetch_sub(sizeof...(cores) - wait_count, std::memory_order_relaxed);
116}
117
118template <typename It>
120 : _executor{e}, _event{count + 1} {
121 std::size_t wait_count = 0;
122 for (std::size_t i = 0; i != count; ++i) {
123 wait_count += static_cast<std::size_t>(it->GetCore()->SetCallback(_event));
124 ++it;
125 }
126 _event.count.fetch_sub(count - wait_count, std::memory_order_relaxed);
127}
128
129} // namespace yaclib::detail
virtual void Submit(Job &job) noexcept=0
Submit given job.
YACLIB_INLINE void await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
constexpr void await_resume() const noexcept
constexpr bool await_ready() const noexcept
AwaitOnEvent(std::size_t n) noexcept
#define YACLIB_ASSERT(cond)
Definition log.hpp:85
std::conditional_t< Single, OneCounter< NopeBase, NopeDeleter >, AtomicCounter< NopeBase, NopeDeleter > > AwaitOnCounterT
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25
constexpr void await_resume() const noexcept
YACLIB_INLINE void await_suspend(yaclib_std::coroutine_handle< Promise > handle) noexcept
AwaitOnAwaiter(IExecutor &e, BaseCore &caller) noexcept
constexpr bool await_ready() const noexcept