21 static_assert(
sizeof...(Futures) > 0);
23 static_assert((... && std::is_same_v<Error, typename Futures::Core::Error>),
24 "All futures need to have the same error type");
33template <ConsumePolicy P>
36inline constexpr std::size_t
kDynamicTag = std::numeric_limits<std::size_t>::max();
38template <
typename Strategy,
typename Core>
43 st.Consume(core.Retire());
47template <std::
size_t Index,
typename Strategy,
typename Core>
56template <
typename Strategy,
typename Core>
59 st.Consume(index, core);
61 st.Consume(index, core.Retire());
65template <std::
size_t Index,
typename Strategy,
typename Core>
80template <
typename Strategy,
typename Core>
95template <
typename Combinator,
typename Core, std::
size_t Index>
105#if YACLIB_SYMMETRIC_TRANSFER != 0
106 [[
nodiscard]] yaclib_std::coroutine_handle<>
Next(InlineCore& caller)
noexcept final {
116 auto index =
this - _self->callbacks.data();
117 Consume(_self->st, core, index);
127template <
typename...
Cores>
132 static constexpr std::size_t
kUniqueCount = std::tuple_size_v<UniqueUniqueCores>;
133 static constexpr std::size_t
kSharedCount = std::tuple_size_v<SharedCores>;
137template <
typename Strategy,
typename Core>
143 template <
typename...
Cores>
145 static_assert((... && std::is_same_v<Core, Cores>));
146 std::size_t index = 0;
147 (..., SetCore(
cores, index++));
153 for (std::size_t
i = 0;
i < count; ++
i) {
154 auto& core = *
begin->GetCore().Release();
157 st.Register(
i, core);
160 if (!core.SetCallback(*
this)) {
174#if YACLIB_SYMMETRIC_TRANSFER != 0
175 [[
nodiscard]] yaclib_std::coroutine_handle<>
Next(InlineCore& caller)
noexcept final {
182 void SetCore(Core& core, std::size_t
i) {
184 st.Register(
i, core);
187 if (!core.SetCallback(*
this)) {
202template <
typename Strategy,
typename...
Cores>
205 template <
typename Sequence>
206 struct OrderedCallbacks;
208 template <std::size_t...
Is>
210 using Type = std::tuple<CombinatorCallback<StaticCombinator, Cores, Is>...>;
216 template <
typename UniqueTuple,
typename SharedTuple>
217 struct UnorderedCallbacks;
219 template <
typename...
UniqueCores,
typename... SharedCores>
220 struct UnorderedCallbacks<std::
tuple<UniqueCores...>, std::tuple<SharedCores...>> {
221 std::tuple<CombinatorCallback<StaticCombinator, UniqueCores, 0>...> unique_tuple;
222 std::tuple<CombinatorCallback<StaticCombinator, SharedCores, 0>...> shared_tuple;
226 std::conditional_t<kIsOrdered<Strategy::kConsumePolicy>,
227 typename OrderedCallbacks<
decltype(std::make_index_sequence<
sizeof...(Cores)>{})>::Type,
230 template <
typename Tuple, std::size_t...
Is>
231 void InitImpl(
Tuple&
tuple, std::index_sequence<Is...>) {
232 ((std::get<Is>(
tuple) = {
this}), ...);
235 template <
typename Tuple>
237 InitImpl(
tuple, std::make_index_sequence<std::tuple_size_v<Tuple>>{});
240 template <std::
size_t Index,
typename Core>
241 auto& GetCallbackHelper() {
247 return std::get<index_of_v<Core, UniqueUniqueCores>>(
callbacks.unique_tuple);
251 template <std::
size_t Index,
typename Core>
252 void SetCore(Core& core) {
256 st.Register(Index, core);
265 template <std::size_t...
Is>
266 void SetImpl(std::index_sequence<Is...>,
Cores&...
cores) {
281 SetImpl(std::make_index_sequence<
sizeof...(
Cores)>{},
cores...);
288template <
typename Strategy,
typename Core>
294 template <
typename Iterator>
296 for (std::size_t
i = 0;
i < count; ++
i) {
297 auto& core = *
begin->GetCore().Release();
300 st.Register(
i, core);
303 if (!core.SetCallback(callbacks[
i])) {
313 std::vector<CombinatorCallback<DynamicCombinator, Core, kDynamicTag>>
callbacks;
316template <
template <
FailPolicy,
typename...>
typename Strategy,
FailPolicy F,
typename OutputValue,
317 typename OutputError,
typename... Futures>
319 if constexpr (
sizeof...(Futures) == 0) {
322 auto [f, p] = MakeContract<OutputValue, OutputError>();
324 using Head =
typename head_t<Futures...>::Core;
325 using Value =
typename Head::Value;
326 using Error =
typename Head::Error;
329 std::conditional_t<(... && std::is_same_v<Head, typename Futures::Core>), Head,
330 std::conditional_t<(... && (std::is_same_v<Value, typename Futures::Core::Value> &&
331 std::is_same_v<Error, typename Futures::Core::Error>)),
334 using S = Strategy<F, OutputValue, OutputError, InputCore>;
336 using FinalCombinator =
337 std::conditional_t<
CoreSignature<
typename Futures::Core...>::kTotalCount == 1 && !kIsOrdered<S::kConsumePolicy>,
341 auto* combinator = MakeShared<FinalCombinator>(
sizeof...(Futures),
sizeof...(Futures), std::move(p)).Release();
342 combinator->
Set(*futures.GetCore().Release()...);
347template <
template <
FailPolicy,
typename...>
typename Strategy,
FailPolicy F,
typename OutputValue,
348 typename OutputError,
typename Iterator,
typename Value =
typename std::iterator_traits<Iterator>::value_type>
349auto When(Iterator begin, std::size_t count) {
354 auto [f, p] = MakeContract<OutputValue, OutputError>();
356 using Core =
typename Value::Core;
357 using S = Strategy<F, OutputValue, OutputError, Core>;
359 static_assert(S::kConsumePolicy != ConsumePolicy::Static);
364 auto* combinator = MakeShared<FinalCombinator>(count, count, std::move(p)).Release();
365 combinator->
Set(begin, count);
Provides a mechanism to access the result of async operations.
Reference counting interface.
virtual void DecRef() noexcept
Decrements reference counter.
detail::IsInstantiationOf< detail::UniqueCore, T > IsUniqueCore
constexpr bool kIsOrdered
detail::IsInstantiationOf< detail::SharedCore, T > IsSharedCore
YACLIB_INLINE void ConsumeImpl(Strategy &st, Core &core)
auto When(Futures... futures)
YACLIB_INLINE void CheckSameError()
constexpr std::size_t kDynamicTag
YACLIB_INLINE void Consume(Strategy &st, Core &core)
constexpr yaclib_std::coroutine_handle noop_coroutine() noexcept
typename detail::Head< Args... >::Type head_t
FailPolicy
This Policy describe how algorithm interpret if Future will be fulfilled by fail (exception or error)
constexpr std::size_t translate_index_v
Contract< V, E > MakeContract()
Creates related future and promise.
InlineCore * Here(InlineCore &caller) noexcept final
CombinatorCallback(Combinator *self=nullptr)
static constexpr std::size_t kSharedCount
static constexpr std::size_t kTotalCount
typename Filter< IsSharedCore, std::tuple< Cores... > >::Type SharedCores
static constexpr std::size_t kUniqueCount
typename Unique< typename Filter< IsUniqueCore, std::tuple< Cores... > >::Type >::Type UniqueUniqueCores
DynamicCombinator(std::size_t count, typename Strategy::PromiseType p)
void Set(Iterator begin, std::size_t count)
std::vector< CombinatorCallback< DynamicCombinator, Core, kDynamicTag > > callbacks
InlineCore * Here(InlineCore &caller) noexcept final
void Set(Cores &... cores)
SingleCombinator(std::size_t count, typename Strategy::PromiseType p)
void Set(Iterator begin, std::size_t count)
StaticCombinator(std::size_t count, typename Strategy::PromiseType p)
void Set(Cores &... cores)