YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
base_core.cpp
Go to the documentation of this file.
2
3namespace yaclib::detail {
4
5template <bool Shared>
7 YACLIB_ASSERT(reinterpret_cast<std::uintptr_t>(&callback) != kEmpty);
8 YACLIB_ASSERT(reinterpret_cast<std::uintptr_t>(&callback) != kResult);
9 if constexpr (Shared) {
10 auto next = _callback.load(std::memory_order_acquire);
11 do {
12 if (next == kResult) {
13 return false;
14 }
15 callback.next = reinterpret_cast<InlineCore*>(next);
16 } while (!_callback.compare_exchange_weak(next, reinterpret_cast<std::uintptr_t>(&callback),
17 std::memory_order_release, std::memory_order_acquire));
18 return true;
19 } else {
20 std::uintptr_t expected = kEmpty;
21 return _callback.load(std::memory_order_acquire) == expected &&
22 _callback.compare_exchange_strong(expected, reinterpret_cast<std::uintptr_t>(&callback),
23 std::memory_order_release, std::memory_order_acquire);
24 }
25}
26
27template bool BaseCore::SetCallbackImpl<false>(InlineCore&) noexcept;
28template bool BaseCore::SetCallbackImpl<true>(InlineCore&) noexcept;
29
31 // Resetting a callback is not supported in shared cores
32 auto expected = _callback.load(std::memory_order_relaxed);
33 return expected != kResult && _callback.compare_exchange_strong(expected, kEmpty, std::memory_order_relaxed);
34}
35
36template <bool SymmetricTransfer, bool Shared>
43
44template Transfer<false> BaseCore::SetInlineImpl<false, false>(InlineCore&) noexcept;
45template Transfer<false> BaseCore::SetInlineImpl<false, true>(InlineCore&) noexcept;
46
47#if YACLIB_SYMMETRIC_TRANSFER != 0
48template Transfer<true> BaseCore::SetInlineImpl<true, false>(InlineCore&) noexcept;
49template Transfer<true> BaseCore::SetInlineImpl<true, true>(InlineCore&) noexcept;
50#endif
51
52template <bool SymmetricTransfer, bool Shared>
54 const auto expected = _callback.exchange(kResult, std::memory_order_acq_rel);
56 if constexpr (Shared) {
57 auto* head = reinterpret_cast<InlineCore*>(expected);
58 if (head) {
59 while (auto* next = head->next) {
60 Loop(this, head);
61 head = static_cast<InlineCore*>(next);
62 }
63 DecRef();
64 // If the refcount here is 2, the callback is the last one for
65 // this core (no Shared futures left), so the value may be moved
66 Loop(this, head);
67 } else {
68 DecRef();
69 }
70 DecRef();
71 DecRef();
73 } else {
74 if (expected != kEmpty) {
75 auto* const callback = reinterpret_cast<InlineCore*>(expected);
76 return Step<SymmetricTransfer>(*this, *callback);
77 } else {
79 }
80 }
81}
82
83template Transfer<false> BaseCore::SetResultImpl<false, false>() noexcept;
85
86#if YACLIB_SYMMETRIC_TRANSFER != 0
87template Transfer<true> BaseCore::SetResultImpl<true, false>() noexcept;
88template Transfer<true> BaseCore::SetResultImpl<true, true>() noexcept;
89#endif
90
91} // namespace yaclib::detail
virtual void DecRef() noexcept
Decrements reference counter.
Definition ref.hpp:21
bool SetCallbackImpl(InlineCore &callback) noexcept
Definition base_core.cpp:6
bool ResetImpl() noexcept
Definition base_core.cpp:30
Transfer< SymmetricTransfer > SetInlineImpl(InlineCore &callback) noexcept
Definition base_core.cpp:37
yaclib_std::atomic_uintptr_t _callback
Definition base_core.hpp:73
Transfer< SymmetricTransfer > SetResultImpl() noexcept
Definition base_core.cpp:53
#define YACLIB_ASSERT(cond)
Definition log.hpp:85
YACLIB_INLINE void Loop(InlineCore *prev, InlineCore *curr) noexcept
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25