YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
any.hpp
Go to the documentation of this file.
1#pragma once
2
7
8#include <atomic>
9
10namespace yaclib::when {
11
12template <FailPolicy F, typename OutputValue, typename OutputError, typename InputCore>
13struct Any;
14
15template <typename OutputValue, typename OutputError, typename InputCore>
16struct Any<FailPolicy::None, OutputValue, OutputError, InputCore> {
18
19 static constexpr ConsumePolicy kConsumePolicy = ConsumePolicy::Unordered;
20 static constexpr CorePolicy kCorePolicy = CorePolicy::Managed;
21
22 Any(std::size_t count, PromiseType p) : _p{std::move(p)} {
23 }
24
25 template <typename Result>
27 if (!_done.load(std::memory_order_relaxed) && !_done.exchange(true, std::memory_order_acq_rel)) {
28 if (result) {
29 std::move(_p).Set(std::forward<Result>(result).Value());
30 } else if (result.State() == ResultState::Error) {
31 std::move(_p).Set(std::forward<Result>(result).Error());
32 } else {
33 std::move(_p).Set(std::forward<Result>(result).Exception());
34 }
35 }
36 }
37
40};
41
42template <typename OutputValue, typename OutputError, typename InputCore>
43struct Any<FailPolicy::FirstFail, OutputValue, OutputError, InputCore> {
45
46 static constexpr ConsumePolicy kConsumePolicy = ConsumePolicy::Unordered;
47 static constexpr CorePolicy kCorePolicy = CorePolicy::Managed;
48
49 Any(std::size_t count, PromiseType p) : _p{std::move(p)} {
50 }
51
52 template <typename Result>
54 if (result) {
55 if (_state.load(std::memory_order_relaxed) != State::kValue &&
56 _state.exchange(State::kValue, std::memory_order_acq_rel) != State::kValue) {
57 std::move(_p).Set(std::forward<Result>(result).Value());
58 }
59 } else {
60 State expected = State::kEmpty;
61 if (_state.load(std::memory_order_relaxed) == expected &&
62 _state.compare_exchange_strong(expected, State::kError, std::memory_order_acq_rel)) {
63 if (result.State() == ResultState::Error) {
64 error = std::forward<Result>(result).Error();
65 } else {
66 error = std::forward<Result>(result).Exception();
67 }
68 }
69 }
70 }
71
72 ~Any() {
73 if (_p.Valid()) {
74 if (error.State() == ResultState::Error) {
75 std::move(_p).Set(std::move(error).Error());
76 } else {
77 std::move(_p).Set(std::move(error).Exception());
78 }
79 }
80 }
81
82 private:
83 enum class State {
84 kEmpty,
85 kError,
86 kValue,
87 };
88
89 yaclib_std::atomic<State> _state = State::kEmpty;
91 PromiseType _p;
92};
93
94template <typename OutputValue, typename OutputError, typename InputCore>
95struct Any<FailPolicy::LastFail, OutputValue, OutputError, InputCore> {
97
98 static constexpr ConsumePolicy kConsumePolicy = ConsumePolicy::Unordered;
99 static constexpr CorePolicy kCorePolicy = CorePolicy::Managed;
100
101 Any(std::size_t count, PromiseType p) : _state{2 * count}, _p{std::move(p)} {
102 }
103
104 template <typename Result>
106 if (!DoneImpl(_state.load(std::memory_order_acquire))) {
107 if (result) {
108 if (!DoneImpl(_state.exchange(1, std::memory_order_acq_rel))) {
109 std::move(_p).Set(std::forward<Result>(result).Value());
110 }
111 } else if (_state.fetch_sub(2, std::memory_order_acq_rel) == 2) {
112 if (result.State() == ResultState::Error) {
113 std::move(_p).Set(std::forward<Result>(result).Error());
114 } else {
115 std::move(_p).Set(std::forward<Result>(result).Exception());
116 }
117 }
118 }
119 }
120
121 private:
122 static bool DoneImpl(std::size_t value) noexcept {
123 return (value & 1U) != 0;
124 }
125
127 PromiseType _p;
128};
129
130} // namespace yaclib::when
Encapsulated return value from caller.
Definition result.hpp:90
atomic< bool > atomic_bool
Definition atomic.hpp:41
atomic< std::size_t > atomic_size_t
Definition atomic.hpp:86
FailPolicy
This Policy describe how algorithm interpret if Future will be fulfilled by fail (exception or error)
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25