Zth (libzth)
async.h
Go to the documentation of this file.
1 #ifndef ZTH_ASYNC_H
2 #define ZTH_ASYNC_H
3 /*
4  * Zth (libzth), a cooperative userspace multitasking library.
5  * Copyright (C) 2019-2022 Jochem Rutgers
6  *
7  * This Source Code Form is subject to the terms of the Mozilla Public
8  * License, v. 2.0. If a copy of the MPL was not distributed with this
9  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
10  */
11 
12 #include <libzth/macros.h>
13 
14 #ifdef __cplusplus
15 
16 # include <libzth/allocator.h>
17 # include <libzth/config.h>
18 # include <libzth/fiber.h>
19 # include <libzth/sync.h>
20 # include <libzth/util.h>
21 # include <libzth/worker.h>
22 
23 # if __cplusplus >= 201103L
24 # include <tuple>
25 # endif
26 
27 # if __cplusplus < 201103L
28 # undef ZTH_TYPEDFIBER98
29 // Always use C++98-compatible TypedFiber implementation.
30 # define ZTH_TYPEDFIBER98 1
31 # elif !defined(ZTH_TYPEDFIBER98)
32 // By default only use C++11 TypedFiber implementation, but this can be
33 // overridden for testing purposes.
34 # define ZTH_TYPEDFIBER98 0
35 # endif
36 
37 namespace zth {
38 
39 template <typename R, typename F>
40 class TypedFiber : public Fiber {
42 public:
43  typedef R Return;
44  typedef F Function;
46 
47  explicit TypedFiber(Function function)
48  : Fiber(&entry, this)
49  , m_function(function)
50  {}
51 
52  virtual ~TypedFiber() override is_default
53 
55  {
56  m_future.reset(future);
57  zth_dbg(sync, "[%s] Registered to %s", future->id_str(), id_str());
58  }
59 
61  {
62  return m_future;
63  }
64 
66  {
67  if(!m_future.get()) {
70  ? new Future_type()
71  : new Future_type(
72  format("Future of %s", this->name().c_str())
73  .c_str()));
74  }
75 
76  return m_future;
77  }
78 
79 protected:
80  static void entry(void* that)
81  {
82  if(likely(that))
83  static_cast<TypedFiber*>(that)->entry_();
84  }
85 
86  virtual void entry_() = 0;
87 
88  template <typename T>
89  void setFuture(T const& r)
90  {
91  if(m_future.get())
92  m_future->set(r);
93  }
94 
95  void setFuture()
96  {
97  if(m_future.get())
98  m_future->set();
99  }
100 
101  Function function() const noexcept
102  {
103  return m_function;
104  }
105 
106 private:
107  Function m_function;
109 };
110 
112 protected:
113  constexpr FiberManipulator() noexcept is_default
115  virtual void apply(Fiber& fiber) const = 0;
116 
117  template <typename R, typename F>
118  friend TypedFiber<R, F>& operator<<(TypedFiber<R, F>& f, FiberManipulator const& m);
119 };
120 
121 template <typename R, typename F>
122 TypedFiber<R, F>& operator<<(TypedFiber<R, F>& f, FiberManipulator const& m)
123 {
124  m.apply(f);
125  return f;
126 }
127 
146 public:
147  constexpr explicit setStackSize(size_t stack) noexcept
148  : m_stack(stack)
149  {}
150  virtual ~setStackSize() override is_default
151 protected:
152  virtual void apply(Fiber& fiber) const override
153  {
154  fiber.setStackSize(m_stack);
155  }
156 
157 private:
158  size_t m_stack;
159 };
160 
167 class setName : public FiberManipulator {
168 public:
169 # if __cplusplus >= 201103L
170  explicit setName(char const* name)
171  : m_name(name ? std::string{name} : std::string{})
172  {}
173 
174  explicit setName(string const& name)
175  : m_name(name)
176  {}
177  explicit setName(string&& name)
178  : m_name(std::move(name))
179  {}
180 # else
181  explicit setName(char const* name)
182  : m_name(name)
183  {}
184 
185  explicit setName(string const& name)
186  : m_name(name.c_str())
187  {}
188 # endif
189 
190  virtual ~setName() override is_default
191 protected:
192  virtual void apply(Fiber& fiber) const override
193  {
194 # if __cplusplus >= 201103L
195  fiber.setName(std::move(m_name));
196 # else
197  fiber.setName(m_name);
198 # endif
199  }
200 
201 private:
202 # if __cplusplus >= 201103L
203  string m_name;
204 # else
205  char const* m_name;
206 # endif
207 };
208 
229 class passOnExit : public FiberManipulator {
230 public:
231  constexpr explicit passOnExit(Gate& gate) noexcept
232  : m_gate(&gate)
233  {}
234 
235  virtual ~passOnExit() override is_default
236 
237 protected:
238  static void cleanup(Fiber& UNUSED_PAR(f), void* gate)
239  {
240  reinterpret_cast<Gate*>(gate)->pass();
241  }
242 
243  virtual void apply(Fiber& fiber) const override
244  {
245  fiber.addCleanup(&cleanup, (void*)m_gate);
246  }
247 
248 private:
249  Gate* m_gate;
250 };
251 
252 template <typename T>
253 class AutoFuture : public SharedPointer<Future<T> > {
255 public:
258 
259  virtual ~AutoFuture() override is_default
260 
262  : base()
263  {}
264 
265  constexpr14 AutoFuture(AutoFuture const& af) noexcept
266  : base(af)
267  {}
268 
269  // cppcheck-suppress noExplicitConstructor
270  constexpr14 AutoFuture(base const& p) noexcept
271  : base(p)
272  {}
273 
274  template <typename F>
275  // cppcheck-suppress noExplicitConstructor
277  {
278  *this = fiber;
279  }
280 
281  template <typename F>
283  {
284  this->reset(fiber.withFuture().get());
285  return *this;
286  }
287 
289  {
290  this->reset(af.get());
291  return *this;
292  }
293 };
294 
295 # if ZTH_TYPEDFIBER98
296 template <typename R>
297 class TypedFiber0 final : public TypedFiber<R, R (*)()> {
298  ZTH_CLASS_NEW_DELETE(TypedFiber0)
299 public:
300  typedef TypedFiber<R, R (*)()> base;
301 
302  explicit TypedFiber0(typename base::Function function)
303  : base(function)
304  {}
305 
306  virtual ~TypedFiber0() final is_default
307 
308 protected:
309  virtual void entry_() final
310  {
311  this->setFuture(this->function()());
312  }
313 };
314 
315 template <>
316 class TypedFiber0<void> final : public TypedFiber<void, void (*)()> {
317  ZTH_CLASS_NEW_DELETE(TypedFiber0)
318 public:
319  typedef TypedFiber<void, void (*)()> base;
320 
321  explicit TypedFiber0(typename base::Function function)
322  : base(function)
323  {}
324 
325  virtual ~TypedFiber0() final is_default
326 
327 protected:
328  virtual void entry_() final
329  {
330  this->function()();
331  this->setFuture();
332  }
333 };
334 
335 template <typename R, typename A1>
336 class TypedFiber1 final : public TypedFiber<R, R (*)(A1)> {
337  ZTH_CLASS_NEW_DELETE(TypedFiber1)
338 public:
339  typedef TypedFiber<R, R (*)(A1)> base;
340 
341  TypedFiber1(typename base::Function function, A1 a1)
342  : base(function)
343  , m_a1(a1)
344  {}
345 
346  virtual ~TypedFiber1() final is_default
347 
348 protected:
349  virtual void entry_() final
350  {
351  this->setFuture(this->function()(m_a1));
352  }
353 
354 private:
355  A1 m_a1;
356 };
357 
358 template <typename A1>
359 class TypedFiber1<void, A1> final : public TypedFiber<void, void (*)(A1)> {
360  ZTH_CLASS_NEW_DELETE(TypedFiber1)
361 public:
362  typedef TypedFiber<void, void (*)(A1)> base;
363 
364  TypedFiber1(typename base::Function function, A1 a1)
365  : base(function)
366  , m_a1(a1)
367  {}
368 
369  virtual ~TypedFiber1() final is_default
370 
371 protected:
372  virtual void entry_() final
373  {
374  this->function()(m_a1);
375  this->setFuture();
376  }
377 
378 private:
379  A1 m_a1;
380 };
381 
382 template <typename R, typename A1, typename A2>
383 class TypedFiber2 final : public TypedFiber<R, R (*)(A1, A2)> {
384  ZTH_CLASS_NEW_DELETE(TypedFiber2)
385 public:
386  typedef TypedFiber<R, R (*)(A1, A2)> base;
387 
388  TypedFiber2(typename base::Function function, A1 a1, A2 a2)
389  : base(function)
390  , m_a1(a1)
391  , m_a2(a2)
392  {}
393 
394  virtual ~TypedFiber2() final is_default
395 
396 protected:
397  virtual void entry_() final
398  {
399  this->setFuture(this->function()(m_a1, m_a2));
400  }
401 
402 private:
403  A1 m_a1;
404  A2 m_a2;
405 };
406 
407 template <typename A1, typename A2>
408 class TypedFiber2<void, A1, A2> final : public TypedFiber<void, void (*)(A1, A2)> {
409  ZTH_CLASS_NEW_DELETE(TypedFiber2)
410 public:
411  typedef TypedFiber<void, void (*)(A1, A2)> base;
412 
413  TypedFiber2(typename base::Function function, A1 a1, A2 a2)
414  : base(function)
415  , m_a1(a1)
416  , m_a2(a2)
417  {}
418 
419  virtual ~TypedFiber2() final is_default
420 
421 protected:
422  virtual void entry_() final
423  {
424  this->function()(m_a1, m_a2);
425  this->setFuture();
426  }
427 
428 private:
429  A1 m_a1;
430  A2 m_a2;
431 };
432 
433 template <typename R, typename A1, typename A2, typename A3>
434 class TypedFiber3 final : public TypedFiber<R, R (*)(A1, A2, A3)> {
435  ZTH_CLASS_NEW_DELETE(TypedFiber3)
436 public:
437  typedef TypedFiber<R, R (*)(A1, A2, A3)> base;
438 
439  TypedFiber3(typename base::Function function, A1 a1, A2 a2, A3 a3)
440  : base(function)
441  , m_a1(a1)
442  , m_a2(a2)
443  , m_a3(a3)
444  {}
445 
446  virtual ~TypedFiber3() final is_default
447 
448 protected:
449  virtual void entry_() final
450  {
451  this->setFuture(this->function()(m_a1, m_a2, m_a3));
452  }
453 
454 private:
455  A1 m_a1;
456  A2 m_a2;
457  A3 m_a3;
458 };
459 
460 template <typename A1, typename A2, typename A3>
461 class TypedFiber3<void, A1, A2, A3> final : public TypedFiber<void, void (*)(A1, A2, A3)> {
462  ZTH_CLASS_NEW_DELETE(TypedFiber3)
463 public:
464  typedef TypedFiber<void, void (*)(A1, A2, A3)> base;
465 
466  TypedFiber3(typename base::Function function, A1 a1, A2 a2, A3 a3)
467  : base(function)
468  , m_a1(a1)
469  , m_a2(a2)
470  , m_a3(a3)
471  {}
472 
473  virtual ~TypedFiber3() final is_default
474 
475 protected:
476  virtual void entry_() final
477  {
478  this->function()(m_a1, m_a2, m_a3);
479  this->setFuture();
480  }
481 
482 private:
483  A1 m_a1;
484  A2 m_a2;
485  A3 m_a3;
486 };
487 # endif // ZTH_TYPEDFIBER98
488 
489 # if __cplusplus >= 201103L
490 template <typename R, typename... Args>
491 class TypedFiberN final : public TypedFiber<R, R (*)(Args...)> {
493 public:
494  typedef TypedFiber<R, R (*)(Args...)> base;
495 
496  template <typename... Args_>
497  // cppcheck-suppress passedByValue
498  TypedFiberN(typename base::Function function, Args_&&... args)
499  : base(function)
500  , m_args(std::forward<Args_>(args)...)
501  {}
502 
503  virtual ~TypedFiberN() final = default;
504 
505 protected:
506  virtual void entry_() final
507  {
508  entry__(typename SequenceGenerator<sizeof...(Args)>::type());
509  }
510 
511 private:
512  template <size_t... S>
513  void entry__(Sequence<S...>)
514  {
515  this->setFuture(this->function()(std::get<S>(m_args)...));
516  }
517 
518 private:
519  std::tuple<Args...> m_args;
520 };
521 
522 template <typename... Args>
523 class TypedFiberN<void, Args...> final : public TypedFiber<void, void (*)(Args...)> {
525 public:
526  typedef TypedFiber<void, void (*)(Args...)> base;
527 
528  template <typename... Args_>
529  // cppcheck-suppress passedByValue
530  TypedFiberN(typename base::Function function, Args_&&... args)
531  : base(function)
532  , m_args(std::forward<Args_>(args)...)
533  {}
534 
535  virtual ~TypedFiberN() final = default;
536 
537 protected:
538  virtual void entry_() final
539  {
540  entry__(typename SequenceGenerator<sizeof...(Args)>::type());
541  }
542 
543 private:
544  template <size_t... S>
545  void entry__(Sequence<S...>)
546  {
547  this->function()(std::get<S>(m_args)...);
548  this->setFuture();
549  }
550 
551 private:
552  std::tuple<Args...> m_args;
553 };
554 # endif // C++11
555 
556 template <typename F>
557 struct TypedFiberType {};
558 
559 # if ZTH_TYPEDFIBER98
560 template <typename R>
561 struct TypedFiberType<R (*)()> {
562  struct NoArg {};
563  typedef R returnType;
564  typedef TypedFiber0<R> fiberType;
565  typedef NoArg a1Type;
566  typedef NoArg a2Type;
567  typedef NoArg a3Type;
568 };
569 
570 template <typename R, typename A1>
571 struct TypedFiberType<R (*)(A1)> {
572  struct NoArg {};
573  typedef R returnType;
574  typedef TypedFiber1<R, A1> fiberType;
575  typedef A1 a1Type;
576  typedef NoArg a2Type;
577  typedef NoArg a3Type;
578 };
579 
580 template <typename R, typename A1, typename A2>
581 struct TypedFiberType<R (*)(A1, A2)> {
582  struct NoArg {};
583  typedef R returnType;
584  typedef TypedFiber2<R, A1, A2> fiberType;
585  typedef A1 a1Type;
586  typedef A2 a2Type;
587  typedef NoArg a3Type;
588 };
589 
590 template <typename R, typename A1, typename A2, typename A3>
591 struct TypedFiberType<R (*)(A1, A2, A3)> {
592  struct NoArg {};
593  typedef R returnType;
594  typedef TypedFiber3<R, A1, A2, A3> fiberType;
595  typedef A1 a1Type;
596  typedef A2 a2Type;
597  typedef A3 a3Type;
598 };
599 # endif // ZTH_TYPEDFIBER98
600 
601 # if __cplusplus >= 201103L
602 template <typename R, typename... Args>
603 struct TypedFiberType<R (*)(Args...)> {
604  struct NoArg {};
605  typedef R returnType;
606  typedef TypedFiberN<R, Args...> fiberType;
607  // The following types are only here for compatibility with the other TypedFiberTypes.
608  typedef NoArg a1Type;
609  typedef NoArg a2Type;
610  typedef NoArg a3Type;
611 };
612 # endif // C++11
613 
614 template <typename F>
616 public:
617  typedef F Function;
624 
625  constexpr TypedFiberFactory(Function function, char const* name) noexcept
626  : m_function(function)
627  , m_name(name)
628  {}
629 
630 # if ZTH_TYPEDFIBER98
631  TypedFiber_type& operator()() const
632  {
633  return polish(*new TypedFiber_type(m_function));
634  }
635 
636  TypedFiber_type& operator()(A1 a1) const
637  {
638  return polish(*new TypedFiber_type(m_function, a1));
639  }
640 
641  TypedFiber_type& operator()(A1 a1, A2 a2) const
642  {
643  return polish(*new TypedFiber_type(m_function, a1, a2));
644  }
645 
646  TypedFiber_type& operator()(A1 a1, A2 a2, A3 a3) const
647  {
648  return polish(*new TypedFiber_type(m_function, a1, a2, a3));
649  }
650 # endif // ZTH_TYPEDFIBER98
651 
652 # if __cplusplus >= 201103L
653  template <typename... Args>
654  TypedFiber_type& operator()(Args&&... args) const
655  {
656  return polish(*new TypedFiber_type(m_function, std::forward<Args>(args)...));
657  }
658 # endif // C++11
659 
660 protected:
662  {
663  if(unlikely(m_name))
664  fiber.setName(m_name);
665 
666  currentWorker().add(&fiber);
667  return fiber;
668  }
669 
670 private:
671  Function m_function;
672  char const* m_name;
673 };
674 
675 template <typename F>
678  typedef typename factory::TypedFiber_type& fiber;
680 };
681 
682 template <typename F>
683 struct fiber_type {};
684 
685 # if ZTH_TYPEDFIBER98
686 template <typename R>
687 struct fiber_type<R (*)()> : public fiber_type_impl<R (*)()> {};
688 
689 template <typename R, typename A1>
690 struct fiber_type<R (*)(A1)> : public fiber_type_impl<R (*)(A1)> {};
691 
692 template <typename R, typename A1, typename A2>
693 struct fiber_type<R (*)(A1, A2)> : public fiber_type_impl<R (*)(A1, A2)> {};
694 
695 template <typename R, typename A1, typename A2, typename A3>
696 struct fiber_type<R (*)(A1, A2, A3)> : public fiber_type_impl<R (*)(A1, A2, A3)> {};
697 # endif
698 
699 # if __cplusplus >= 201103L
700 template <typename R, typename... Args>
701 struct fiber_type<R (*)(Args...)> : public fiber_type_impl<R (*)(Args...)> {};
702 # endif
703 
712 template <typename F>
713 typename fiber_type<F>::factory fiber(F f, char const* name = nullptr)
714 {
715  return typename fiber_type<F>::factory(
716  f,
718  ? name
719  : nullptr);
720 }
721 
722 namespace fibered {}
723 
724 } // namespace zth
725 
726 # define zth_fiber_declare_1(f) \
727  namespace zth { \
728  namespace fibered { \
729  extern ::zth::TypedFiberFactory<decltype(&::f)> const f; \
730  } \
731  }
732 
738 # define zth_fiber_declare(...) FOREACH(zth_fiber_declare_1, ##__VA_ARGS__)
739 
740 # define zth_fiber_define_1(storage, f) \
741  namespace zth { \
742  namespace fibered { \
743  storage ::zth::TypedFiberFactory<decltype(&::f)> const \
744  f(&::f, ::zth::Config::EnableDebugPrint || ::zth::Config::EnablePerfEvent \
745  ? ZTH_STRINGIFY(f) "()" \
746  : nullptr); /* NOLINT */ \
747  } \
748  } \
749  typedef ::zth::TypedFiberFactory<decltype(&::f)>::AutoFuture_type f##_future;
750 # define zth_fiber_define_extern_1(f) zth_fiber_define_1(extern, f)
751 # define zth_fiber_define_static_1(f) zth_fiber_define_1(static constexpr, f)
752 
758 # define zth_fiber_define(...) FOREACH(zth_fiber_define_extern_1, ##__VA_ARGS__)
759 
765 # define zth_fiber(...) FOREACH(zth_fiber_define_static_1, ##__VA_ARGS__)
766 
787 # define zth_async ::zth::fibered::
788 # ifndef ZTH_NO_ASYNC_KEYWORD
789 # define async zth_async
790 # endif
791 
796 EXTERN_C ZTH_EXPORT ZTH_INLINE int zth_fiber_create(
797  void (*f)(void*), void* arg = nullptr, size_t stack = 0,
798  char const* name = nullptr) noexcept
799 {
800  int res = 0;
801  zth::Fiber* fib = nullptr;
802 
803  try {
804  fib = new zth::Fiber(f, arg);
805  } catch(std::bad_alloc const&) {
806  return ENOMEM;
807  } catch(...) {
808  return EAGAIN;
809  }
810 
811  if(unlikely(stack))
812  if((res = fib->setStackSize(stack))) {
813  delete fib;
814  return res;
815  }
816 
817  if(unlikely(name))
818  fib->setName(name);
819 
820  zth::currentWorker().add(fib);
821  return res;
822 }
823 #else // !__cplusplus
824 
825 # include <stddef.h>
826 
827 ZTH_EXPORT int zth_fiber_create(void (*f)(void*), void* arg, size_t stack, char const* name);
828 
829 #endif // !__cplusplus
830 #endif // ZTH_ASYNC_H
AutoFuture & operator=(AutoFuture const &af)
Definition: async.h:288
AutoFuture & operator=(TypedFiber< T, F > &fiber)
Definition: async.h:282
constexpr AutoFuture(AutoFuture const &af) noexcept
Definition: async.h:265
constexpr AutoFuture(base const &p) noexcept
Definition: async.h:270
SharedPointer< Future< T > > base
Definition: async.h:256
AutoFuture(TypedFiber< T, F > &fiber)
Definition: async.h:276
virtual ~AutoFuture() override=default
Future< T > Future_type
Definition: async.h:257
The fiber.
Definition: fiber.h:52
int setStackSize(size_t size) noexcept
Definition: fiber.h:119
constexpr FiberManipulator() noexcept=default
virtual void apply(Fiber &fiber) const =0
Fiber-aware future.
Definition: sync.h:542
Fiber-aware barrier/gate.
Definition: sync.h:757
constexpr T * get() const noexcept
Definition: sync.h:120
TypedFiberType< Function >::fiberType TypedFiber_type
Definition: async.h:619
TypedFiberType< Function >::a1Type A1
Definition: async.h:620
TypedFiberType< Function >::returnType Return
Definition: async.h:618
TypedFiberType< Function >::a2Type A2
Definition: async.h:621
TypedFiber_type & polish(TypedFiber_type &fiber) const
Definition: async.h:661
TypedFiberType< Function >::a3Type A3
Definition: async.h:622
AutoFuture< Return > AutoFuture_type
Definition: async.h:623
TypedFiber_type & operator()(Args &&... args) const
Definition: async.h:654
constexpr TypedFiberFactory(Function function, char const *name) noexcept
Definition: async.h:625
Future< Return > Future_type
Definition: async.h:45
TypedFiber(Function function)
Definition: async.h:47
virtual void entry_()=0
void setFuture(T const &r)
Definition: async.h:89
void registerFuture(Future_type *future)
Definition: async.h:54
static void entry(void *that)
Definition: async.h:80
SharedPointer< Future_type > withFuture()
Definition: async.h:65
virtual ~TypedFiber() override=default
void setFuture()
Definition: async.h:95
Function function() const noexcept
Definition: async.h:101
Future_type * future() const
Definition: async.h:60
TypedFiberN(typename base::Function function, Args_ &&... args)
Definition: async.h:530
virtual ~TypedFiberN() final=default
TypedFiber< void, void(*)(Args...)> base
Definition: async.h:526
virtual ~TypedFiberN() final=default
TypedFiber< R, R(*)(Args...)> base
Definition: async.h:494
TypedFiberN(typename base::Function function, Args_ &&... args)
Definition: async.h:498
virtual char const * id_str() const override
Definition: util.h:751
string const & name() const noexcept
Definition: util.h:725
void setName(string const &name)
Definition: util.h:730
void add(Fiber *fiber) noexcept
Definition: worker.h:106
Makes the fiber pass the given gate upon exit.
Definition: async.h:229
virtual void apply(Fiber &fiber) const override
Definition: async.h:243
virtual ~passOnExit() override=default
constexpr passOnExit(Gate &gate) noexcept
Definition: async.h:231
Change the name of a fiber returned by async.
Definition: async.h:167
setName(string const &name)
Definition: async.h:174
setName(char const *name)
Definition: async.h:170
setName(string &&name)
Definition: async.h:177
virtual ~setName() override=default
Change the stack size of a fiber returned by async.
Definition: async.h:145
virtual ~setStackSize() override=default
constexpr setStackSize(size_t stack) noexcept
Definition: async.h:147
int zth_fiber_create(void(*f)(void *), void *arg=nullptr, size_t stack=0, char const *name=nullptr) noexcept
Run a function as a new fiber.
Definition: async.h:796
Worker & currentWorker() noexcept
Return the (thread-local) singleton Worker instance.
Definition: worker.h:388
fiber_type< F >::factory fiber(F f, char const *name=nullptr)
Create a new fiber.
Definition: async.h:713
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
Definition: util.h:210
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
Definition: util.h:335
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition: allocator.h:114
#define constexpr14
Definition: macros.h:201
#define is_default
Definition: macros.h:205
#define ZTH_INLINE
Definition: macros.h:130
#define UNUSED_PAR(name)
Definition: macros.h:79
Definition: allocator.h:23
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
Definition: util.h:503
static bool const EnablePerfEvent
Enable (but not necessarily record) perf.
Definition: config.h:163
static bool const EnableDebugPrint
Actually do print the debug output.
Definition: config.h:91
static bool const EnableStackWaterMark
When true, enable stack watermark to detect maximum stack usage.
Definition: config.h:137
static bool const NamedSynchronizer
Save names for all zth::Synchronizer instances.
Definition: config.h:151
TypedFiberN< R, Args... > fiberType
Definition: async.h:606
TypedFiberFactory< F > factory
Definition: async.h:677
factory::AutoFuture_type future
Definition: async.h:679
factory::TypedFiber_type & fiber
Definition: async.h:678
#define likely(expr)
Marks the given expression to likely be evaluated to true.
Definition: util.h:42
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition: util.h:56