Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
UpdatableWaitForIOReady.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "TimeOutException.h"
5
7
8 /*
9 ********************************************************************************
10 ******************* Execution::UpdatableWaitForIOReady *************************
11 ********************************************************************************
12 */
13 template <typename T, typename TRAITS>
14 UpdatableWaitForIOReady<T, TRAITS>::UpdatableWaitForIOReady (const Traversal::Iterable<pair<T, TypeOfMonitorSet>>& fds)
15 : fEventFD_{WaitForIOReady_Support::mkEventFD ()}
16 , fPollable2Wakeup_{fEventFD_->GetWaitInfo ()}
17 , fData_{fds}
18 {
19 }
20 template <typename T, typename TRAITS>
21 inline UpdatableWaitForIOReady<T, TRAITS>::UpdatableWaitForIOReady ()
22 : UpdatableWaitForIOReady{Traversal::Iterable<pair<T, TypeOfMonitorSet>>{}}
23 {
24 }
25 template <typename T, typename TRAITS>
26 UpdatableWaitForIOReady<T, TRAITS>::UpdatableWaitForIOReady (const Traversal::Iterable<T>& fds, const TypeOfMonitorSet& flags)
27 : UpdatableWaitForIOReady{
28 fds.template Map<Traversal::Iterable<pair<T, TypeOfMonitorSet>>> ([&] (const T& t) { return make_pair (t, flags); })}
29 {
30 }
31 template <typename T, typename TRAITS>
32 UpdatableWaitForIOReady<T, TRAITS>::UpdatableWaitForIOReady (const T& fd, const TypeOfMonitorSet& flags)
33 : UpdatableWaitForIOReady{Containers::Collection<pair<T, TypeOfMonitorSet>>{make_pair (fd, flags)}}
34 {
35 }
36 template <typename T, typename TRAITS>
38 {
39 fData_.rwget ().clear ();
40 fEventFD_->Set (); // force wakeup of any waits
41 }
42 template <typename T, typename TRAITS>
43 inline auto UpdatableWaitForIOReady<T, TRAITS>::GetDescriptors () const -> Containers::Collection<pair<T, TypeOfMonitorSet>>
44 {
45 return fData_.load ();
46 }
47 template <typename T, typename TRAITS>
48 inline void UpdatableWaitForIOReady<T, TRAITS>::AddAll (const Traversal::Iterable<T>& fds, const TypeOfMonitorSet& flags)
49 {
50 {
51 auto lk = fData_.rwget ();
52 for (const auto& i : fds) {
53 lk->Add (i, flags);
54 }
55 }
56 fEventFD_->Set (); // force wakeup of any waits
57 }
58 template <typename T, typename TRAITS>
59 inline void UpdatableWaitForIOReady<T, TRAITS>::AddAll (const Traversal::Iterable<pair<T, TypeOfMonitorSet>>& fds)
60 {
61 fData_.rwget ()->fData_.AddAll (fds);
62 fEventFD_->Set (); // force wakeup of any waits
63 }
64 template <typename T, typename TRAITS>
65 inline auto UpdatableWaitForIOReady<T, TRAITS>::Wait (Time::DurationSeconds waitFor) -> Containers::Set<T>
66 {
67 return WaitUntil (waitFor + Time::GetTickCount ());
68 }
69 template <typename T, typename TRAITS>
70 inline auto UpdatableWaitForIOReady<T, TRAITS>::Wait (const Time::Duration& waitFor) -> Containers::Set<T>
71 {
72 return WaitUntil (waitFor + Time::GetTickCount ());
73 }
74 template <typename T, typename TRAITS>
75 inline auto UpdatableWaitForIOReady<T, TRAITS>::WaitQuietly (Time::DurationSeconds waitFor) -> Containers::Set<T>
76 {
77 return WaitQuietlyUntil (waitFor + Time::GetTickCount ());
78 }
79 template <typename T, typename TRAITS>
80 inline auto UpdatableWaitForIOReady<T, TRAITS>::WaitQuietly (const Time::Duration& waitFor) -> Containers::Set<T>
81 {
82 return WaitQuietly (waitFor);
83 }
84 template <typename T, typename TRAITS>
85 void UpdatableWaitForIOReady<T, TRAITS>::Add (T fd, const TypeOfMonitorSet& flags)
86 {
87 fData_.rwget ()->Add (pair<T, TypeOfMonitorSet>{fd, flags});
88 fEventFD_->Set (); // force wakeup of any waits
89 }
90 template <typename T, typename TRAITS>
91 void UpdatableWaitForIOReady<T, TRAITS>::Remove ([[maybe_unused]] T fd)
92 {
93 if (fData_.rwget ()->RemoveIf ([&] (auto p) { return p.first == fd; })) {
94 fEventFD_->Set (); // force wakeup of any waits
95 }
96 }
97 template <typename T, typename TRAITS>
98 void UpdatableWaitForIOReady<T, TRAITS>::RemoveAll ([[maybe_unused]] const Traversal::Iterable<T>& fds)
99 {
100 Containers::Set<T> fdsSet{fds};
101 if (fData_.rwget ()->RemoveAll ([&] (auto p) { return fdsSet.Contains (p.first); }) != 0) {
102 fEventFD_->Set (); // force wakeup of any waits
103 }
104 }
105 template <typename T, typename TRAITS>
106 void UpdatableWaitForIOReady<T, TRAITS>::SetDescriptors (const Traversal::Iterable<pair<T, TypeOfMonitorSet>>& fds)
107 {
108 fData_.store (fds);
109 fEventFD_->Set (); // force wakeup of any waits
110 }
111 template <typename T, typename TRAITS>
112 void UpdatableWaitForIOReady<T, TRAITS>::SetDescriptors (const Traversal::Iterable<T>& fds, const TypeOfMonitorSet& flags)
113 {
114 SetDescriptors (fds.template Map<Traversal::Iterable<pair<T, TypeOfMonitorSet>>> ([&] (const T& t) { return make_pair (t, flags); }));
115 }
116 template <typename T, typename TRAITS>
118 {
119 Containers::Set<T> result = WaitQuietlyUntil (timeoutAt);
120 if (result.empty ()) {
121 Execution::ThrowTimeoutExceptionAfter (timeoutAt); // maybe returning 0 entries without timeout, because of fPollable2Wakeup_
122 }
123 return result;
124 }
125 template <typename T, typename TRAITS>
127 {
128 // At some point, we need to clear the flags on the eventFD objects. We could do this before
129 // or after starting the wait. If we do it before calling mkWaiter_ (), there is a window after the clear and before the mkWaiter
130 // where if events happen, this will just return immediately (not a bug - good behavior).
131 // If we do it afterwards, not buggy exactly either, but its much more likely we'll return too soon.
132 fEventFD_->Clear ();
133 return mkWaiter_ ().WaitQuietlyUntil (timeoutAt);
134 }
135 template <typename T, typename TRAITS>
136 inline WaitForIOReady<T, TRAITS> UpdatableWaitForIOReady<T, TRAITS>::mkWaiter_ ()
137 {
138#if 1
139 // https://stroika.atlassian.net/browse/STK-1021
141 auto dataLock = fData_.rwget (); // not 100% understood yet, but it appears you need to hold lock longer - to make tsan happy
142 Iterable<pair<T, TypeOfMonitorSet>> r{dataLock.cref ()};
143 return WaitForIOReady<T, TRAITS>{r, fPollable2Wakeup_};
144#else
145 return WaitForIOReady<T, TRAITS>{fData_.load (), fPollable2Wakeup_};
146#endif
147 }
148
149}
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
Definition Realtime.h:82
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
Simple wrapper on WaitForIOReady (POSIX select/poll/etc API) - except it allows for the list if polle...
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
nonvirtual bool empty() const
Returns true iff size() == 0.
Definition Iterable.inl:306