Zth (libzth)
Loading...
Searching...
No Matches
waiter.h
Go to the documentation of this file.
1#ifndef ZTH_WAITER_H
2#define ZTH_WAITER_H
3/*
4 * SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 */
8
9#include <libzth/macros.h>
10
11#ifdef __cplusplus
12
13# include <libzth/allocator.h>
14# include <libzth/fiber.h>
15# include <libzth/list.h>
16# include <libzth/time.h>
17# include <libzth/util.h>
18
19# if __cplusplus >= 201103L
20# include <type_traits>
21# endif
22
23namespace zth {
24class Worker;
25
26class Waitable {
28public:
29 Waitable() noexcept
30 : m_fiber()
31 {}
32
33 virtual ~Waitable() noexcept is_default
34
35 Fiber& fiber() const noexcept
36 {
38 return *m_fiber;
39 }
40
41 virtual bool poll(Timestamp const& now = Timestamp::now()) noexcept = 0;
42
43 virtual string str() const
44 {
45 return format("Waitable for %s", fiber().str().c_str());
46 }
47
48 void setFiber(Fiber& fiber) noexcept
49 {
50 m_fiber = &fiber;
51 }
52
53 void resetFiber() noexcept
54 {
55 m_fiber = nullptr;
56 }
57
58 bool hasFiber() const noexcept
59 {
60 return m_fiber;
61 }
62
63private:
64 Fiber* m_fiber;
65};
66
67class TimedWaitable : public Waitable, public Listable {
69public:
70 explicit TimedWaitable(Timestamp const& timeout = Timestamp()) noexcept
71 : m_timeout(timeout)
72 {}
73
74 virtual ~TimedWaitable() noexcept override is_default
75
76 Timestamp const& timeout() const noexcept
77 {
78 return m_timeout;
79 }
80
81 virtual bool poll(Timestamp const& now = Timestamp::now()) noexcept override
82 {
83 return timeout() <= now;
84 }
85
86 bool operator<(TimedWaitable const& rhs) const noexcept
87 {
88 return timeout() < rhs.timeout();
89 }
90
91 virtual string str() const override
92 {
93 if(hasFiber())
94 return format(
95 "Waitable with %s timeout for %s",
96 (timeout() - Timestamp::now()).str().c_str(),
97 fiber().str().c_str());
98 else
99 return format(
100 "Waitable with %s timeout",
101 (timeout() - Timestamp::now()).str().c_str());
102 }
103
104protected:
105 void setTimeout(Timestamp const& t) noexcept
106 {
107 m_timeout = t;
108 }
109
110private:
111 Timestamp m_timeout;
112};
113
114template <typename F>
117public:
118 explicit PolledWaiting(F const& f, TimeInterval const& interval = TimeInterval())
120 , m_f(f)
121 {
123 }
124
125 virtual ~PolledWaiting() noexcept override is_default
126
127 virtual bool poll(Timestamp const& now = Timestamp::now()) noexcept override
128 {
129 if(m_f())
130 return true;
131
132 Timestamp next_poll = timeout() + interval();
133 if(unlikely(next_poll < now))
134 next_poll = now + interval();
135
136 setTimeout(next_poll);
137 return false;
138 }
139
140 TimeInterval const& interval() const noexcept
141 {
142 return m_interval;
143 }
144
145 void
147 {
148 m_interval = interval;
149 setTimeout(now + interval);
150 }
151
152private:
153 F m_f;
154 TimeInterval m_interval;
155};
156
157template <typename C>
159 constexpr PolledMemberWaitingHelper(C& that_, bool (C::*f_)()) noexcept
160 : that(that_)
161 , f(f_)
162 {}
163
164 bool operator()() const
165 {
166 zth_assert(f != nullptr);
167 // cppcheck-suppress nullPointerRedundantCheck
168 return (that.*f)();
169 }
170
172 bool (C::*f)();
173};
174
175template <typename C>
176class PolledMemberWaiting : public PolledWaiting<PolledMemberWaitingHelper<C> > {
178public:
180
182 C& that, bool (C::*f)(), TimeInterval const& interval = TimeInterval()) noexcept
184 {}
185
186 virtual ~PolledMemberWaiting() noexcept override is_default
187};
188
189class PollerServerBase;
190
194class Waiter : public Runnable {
196public:
197 explicit Waiter(Worker& worker);
198 virtual ~Waiter() noexcept override;
199
200 void wait(TimedWaitable& w);
203 void wakeup(TimedWaitable& w);
204
205 PollerServerBase& poller();
206 void setPoller(PollerServerBase* p = nullptr);
207 void wakeup();
208
209protected:
210 bool polling() const;
211
212 virtual int fiberHook(Fiber& f) override
213 {
214 f.setName("zth::Waiter");
215 f.suspend();
216 return Runnable::fiberHook(f);
217 }
218
219 virtual void entry() override;
220
221private:
222 Worker& m_worker;
224 PollerServerBase* m_poller;
225 PollerServerBase* m_defaultPoller;
226};
227
232ZTH_EXPORT void waitUntil(TimedWaitable& w);
233
238# if __cplusplus >= 201103L
239template <
240 typename F,
241 typename std::enable_if<!std::is_base_of<TimedWaitable, F>::value, int>::type = 0>
242void waitUntil(F f, TimeInterval const& pollInterval = TimeInterval())
243{
244 PolledWaiting<F> w(f, pollInterval);
245 waitUntil(w);
246}
247# else
248ZTH_EXPORT inline void waitUntil(bool (*f)(), TimeInterval const& pollInterval = TimeInterval())
249{
250 PolledWaiting<bool (*)()> w(f, pollInterval);
251 waitUntil(w);
252}
253# endif
254
259template <typename C>
260void waitUntil(C& that, bool (C::*f)(), TimeInterval const& pollInterval = TimeInterval())
261{
262 PolledMemberWaiting<C> w(that, f, pollInterval);
263 waitUntil(w);
264}
265
266void scheduleTask(TimedWaitable& w);
267void unscheduleTask(TimedWaitable& w);
268void wakeup(TimedWaitable& w);
269
274ZTH_EXPORT inline void nap(Timestamp const& sleepUntil)
275{
276 TimedWaitable w(sleepUntil);
277 waitUntil(w);
278}
279
284ZTH_EXPORT inline void nap(TimeInterval const& sleepFor)
285{
286 if(!sleepFor.hasPassed())
287 nap(Timestamp::now() + sleepFor);
288}
289
294ZTH_EXPORT inline void mnap(long sleepFor_ms)
295{
296 nap(TimeInterval((time_t)(sleepFor_ms / 1000L), sleepFor_ms % 1000L * 1000000L));
297}
298
303ZTH_EXPORT inline void unap(long sleepFor_us)
304{
305 nap(TimeInterval((time_t)(sleepFor_us / 1000000L), sleepFor_us % 1000000L * 1000L));
306}
307
360public:
361 explicit PeriodicWakeUp(TimeInterval const& interval)
362 : m_interval(interval)
363 , m_t(Timestamp::now())
364 {}
365
366 Timestamp const& t() const noexcept
367 {
368 return m_t;
369 }
370
371 TimeInterval const& interval() const noexcept
372 {
373 return m_interval;
374 }
375
376 void setInterval(TimeInterval const& interval) noexcept
377 {
378 m_interval = interval;
379 }
380
381 PeriodicWakeUp& operator=(TimeInterval const& interval) noexcept
382 {
383 setInterval(interval);
384 return *this;
385 }
386
387 bool nap()
388 {
389 return nap(t());
390 }
391
392 bool nap(Timestamp const& reference, Timestamp const& now = Timestamp::now());
393
395 {
396 nap();
397 }
398
399private:
400 TimeInterval m_interval;
401 Timestamp m_t;
402};
403
404} // namespace zth
405
411EXTERN_C ZTH_EXPORT ZTH_INLINE void zth_nap(struct timespec const* ts)
412{
413 if(likely(ts))
415}
416
422EXTERN_C ZTH_EXPORT ZTH_INLINE void zth_mnap(long sleepFor_ms)
423{
424 zth::mnap(sleepFor_ms);
425}
426
432EXTERN_C ZTH_EXPORT ZTH_INLINE void zth_unap(long sleepFor_us)
433{
434 zth::unap(sleepFor_us);
435}
436
437#else // !__cplusplus
438
439# include <time.h>
440
441ZTH_EXPORT void zth_nap(struct timespec const* ts);
442ZTH_EXPORT void zth_mnap(long sleepFor_ms);
443ZTH_EXPORT void zth_unap(long sleepFor_us);
444
445#endif // __cplusplus
446#endif // ZTH_WAITER_H
The fiber.
Definition fiber.h:49
void suspend() noexcept
Definition fiber.h:345
void setName(string const &name)
Definition util.h:751
Periodic wakeup after fixed interval.
Definition waiter.h:358
PeriodicWakeUp(TimeInterval const &interval)
Definition waiter.h:361
TimeInterval const & interval() const noexcept
Definition waiter.h:371
Timestamp const & t() const noexcept
Definition waiter.h:366
void setInterval(TimeInterval const &interval) noexcept
Definition waiter.h:376
PeriodicWakeUp & operator=(TimeInterval const &interval) noexcept
Definition waiter.h:381
PolledWaiting< PolledMemberWaitingHelper< C > > base
Definition waiter.h:179
virtual ~PolledMemberWaiting() noexcept override=default
constexpr PolledMemberWaiting(C &that, bool(C::*f)(), TimeInterval const &interval=TimeInterval()) noexcept
Definition waiter.h:181
virtual bool poll(Timestamp const &now=Timestamp::now()) noexcept override
Definition waiter.h:127
void setInterval(TimeInterval const &interval, Timestamp const &now=Timestamp::now()) noexcept
Definition waiter.h:146
virtual ~PolledWaiting() noexcept override=default
PolledWaiting(F const &f, TimeInterval const &interval=TimeInterval())
Definition waiter.h:118
TimeInterval const & interval() const noexcept
Definition waiter.h:140
Abstract base class of a Poller server.
Definition poller.h:270
An abstract class, that can be started as a fiber.
Definition fiber.h:491
virtual int fiberHook(Fiber &f)
Definition fiber.h:524
Convenient wrapper around struct timespec that contains a time interval.
Definition time.h:55
constexpr bool hasPassed() const noexcept
Definition time.h:261
virtual bool poll(Timestamp const &now=Timestamp::now()) noexcept override
Definition waiter.h:81
bool operator<(TimedWaitable const &rhs) const noexcept
Definition waiter.h:86
void setTimeout(Timestamp const &t) noexcept
Definition waiter.h:105
Timestamp const & timeout() const noexcept
Definition waiter.h:76
TimedWaitable(Timestamp const &timeout=Timestamp()) noexcept
Definition waiter.h:70
virtual string str() const override
Definition waiter.h:91
virtual ~TimedWaitable() noexcept override=default
Convenient wrapper around struct timespec that contains an absolute timestamp.
Definition time.h:568
static Timestamp now()
Definition time.h:595
void setFiber(Fiber &fiber) noexcept
Definition waiter.h:48
Waitable() noexcept
Definition waiter.h:29
virtual string str() const
Definition waiter.h:43
void resetFiber() noexcept
Definition waiter.h:53
virtual ~Waitable() noexcept=default
bool hasFiber() const noexcept
Definition waiter.h:58
virtual bool poll(Timestamp const &now=Timestamp::now()) noexcept=0
Fiber & fiber() const noexcept
Definition waiter.h:35
A single fiber per Worker that manages sleeping and blocked fibers.
Definition waiter.h:194
virtual int fiberHook(Fiber &f) override
Definition waiter.h:212
The class that manages the fibers within this thread.
Definition worker.h:35
void zth_mnap(long sleepFor_ms)
Sleep for the given amount of milliseconds.
Definition waiter.h:422
void zth_unap(long sleepFor_us)
Sleep for the given amount of microseconds.
Definition waiter.h:432
void zth_nap(struct timespec const *ts)
Sleep for the given time interval.
Definition waiter.h:411
void nap(Timestamp const &sleepUntil)
Sleep until the given time stamp.
Definition waiter.h:274
void mnap(long sleepFor_ms)
Sleep for the given amount of milliseconds.
Definition waiter.h:294
void waitUntil(TimedWaitable &w)
Wait until the given Waitable has passed.
Definition waiter.cpp:25
void unap(long sleepFor_us)
Sleep for the given amount of microseconds.
Definition waiter.h:303
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition allocator.h:159
#define is_default
Definition macros.h:212
#define ZTH_INLINE
Definition macros.h:129
void unscheduleTask(TimedWaitable &w)
Definition waiter.cpp:66
void scheduleTask(TimedWaitable &w)
Definition waiter.cpp:54
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
Definition util.h:483
void wakeup(TimedWaitable &w)
Definition waiter.cpp:77
constexpr PolledMemberWaitingHelper(C &that_, bool(C::*f_)()) noexcept
Definition waiter.h:159
#define zth_assert(expr)
assert(), but better integrated in Zth.
Definition util.h:217
#define likely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:45
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:60