YACLib
C++ library for concurrent tasks execution
Loading...
Searching...
No Matches
wait_impl.hpp
Go to the documentation of this file.
1#pragma once
2
10
11#include <cstddef>
12#include <iterator>
13#include <type_traits>
14
15namespace yaclib::detail {
16
18
19template <typename Event, typename Timeout, typename Range>
20bool WaitRange(const Timeout& timeout, Range&& range, std::size_t count) noexcept {
21 Event event{count + 1};
22 // event ref counter = n + 1, it is optimization: we don't want to notify when return true immediately
23 const auto wait_count = range([&](BaseCore& core) noexcept {
24 return core.SetCallback(event.GetCall());
25 });
26 if (wait_count == 0 || event.SubEqual(count - wait_count + 1)) {
27 return true;
28 }
29 auto token = event.Make();
30 std::size_t reset_count = 0;
31 if constexpr (!std::is_same_v<Timeout, NoTimeoutTag>) {
32 // If you have problem with TSAN here, check this link: https://github.com/google/sanitizers/issues/1259
33 // TLDR: new pthread function is not supported by thread sanitizer yet.
34 if (event.Wait(token, timeout)) {
35 return true;
36 }
37 reset_count = range([](BaseCore& core) noexcept {
38 return core.Reset();
39 });
40 if (reset_count != 0 && (reset_count == wait_count || event.SubEqual(reset_count))) {
41 return false;
42 }
43 // We know we have `wait_count - reset_count` Results, but we must wait until event was not used by cores
44 }
45 event.Wait(token);
46 return reset_count == 0; // LCOV_EXCL_LINE shitty gcov cannot parse it
47}
48
49template <typename Event, typename Timeout, typename... Cores>
50bool WaitCore(const Timeout& timeout, Cores&... cores) noexcept {
51 static_assert(sizeof...(cores) >= 1, "Number of futures must be at least one");
52 static_assert((... && std::is_same_v<BaseCore, Cores>), "Futures must be Future in Wait function");
53 auto range = [&](auto&& func) noexcept {
54 return (... + static_cast<std::size_t>(func(cores)));
55 };
56 using FinalEvent = std::conditional_t<sizeof...(cores) == 1, MultiEvent<Event, OneCounter, CallCallback>,
58 return WaitRange<FinalEvent>(timeout, range, sizeof...(cores));
59}
60
61template <typename Event, typename Timeout, typename Iterator>
62bool WaitIterator(const Timeout& timeout, Iterator it, std::size_t count) noexcept {
64 "Wait function Iterator must be point to some FutureBase");
65 if (count == 0) {
66 return true;
67 }
68 if (count == 1) {
69 auto range = [&](auto&& func) noexcept {
70 YACLIB_ASSERT(it->Valid());
71 return static_cast<std::size_t>(func(*it->GetCore()));
72 };
74 }
75 auto range = [&](auto&& func) noexcept {
76 std::size_t wait_count = 0;
77 std::conditional_t<std::is_same_v<Timeout, NoTimeoutTag>, Iterator&, Iterator> range_it = it;
78 for (std::size_t i = 0; i != count; ++i) {
79 YACLIB_ASSERT(range_it->Valid());
80 wait_count += static_cast<std::size_t>(func(*range_it->GetCore()));
81 ++range_it;
82 }
83 return wait_count;
84 };
86}
87
90 BaseCore&) noexcept;
91
92} // namespace yaclib::detail
#define YACLIB_ASSERT(cond)
Definition log.hpp:85
bool WaitCore(const Timeout &timeout, Cores &... cores) noexcept
Definition wait_impl.hpp:50
template bool WaitCore< DefaultEvent, NoTimeoutTag, BaseCore, BaseCore >(const NoTimeoutTag &, BaseCore &, BaseCore &) noexcept
template bool WaitCore< DefaultEvent, NoTimeoutTag, BaseCore >(const NoTimeoutTag &, BaseCore &) noexcept
bool WaitRange(const Timeout &timeout, Range &&range, std::size_t count) noexcept
Definition wait_impl.hpp:20
bool WaitIterator(const Timeout &timeout, Iterator it, std::size_t count) noexcept
Definition wait_impl.hpp:62
Contract< V, E > MakeContract()
Creates related future and promise.
Definition contract.hpp:25