Zth (libzth)
Loading...
Searching...
No Matches
async.h
Go to the documentation of this file.
1#ifndef ZTH_ASYNC_H
2#define ZTH_ASYNC_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#include <libzth/fiber.h>
12
13#ifdef __cplusplus
14
15# include <libzth/allocator.h>
16# include <libzth/config.h>
17# include <libzth/exception.h>
18# include <libzth/sync.h>
19# include <libzth/util.h>
20# include <libzth/worker.h>
21
22# if __cplusplus >= 201103L
23# include <initializer_list>
24# include <tuple>
25# include <type_traits>
26# endif
27
28# if __cplusplus < 201103L
29# undef ZTH_TYPEDFIBER98
30// Always use C++98-compatible TypedFiber implementation.
31# define ZTH_TYPEDFIBER98 1
32# elif !defined(ZTH_TYPEDFIBER98)
33// By default only use C++11 TypedFiber implementation, but this can be
34// overridden for testing purposes.
35# define ZTH_TYPEDFIBER98 0
36# endif
37
38namespace zth {
39
40
41
43// Typed fiber base class and manipulators
44//
45
55template <typename R>
56class TypedFiber : public Fiber {
58public:
59 typedef R Return;
61
62 constexpr TypedFiber()
63 : Fiber(&entry, this)
64 {}
65
66 virtual ~TypedFiber() noexcept override is_default
67
69 {
70 m_future.reset(future);
71 zth_dbg(sync, "[%s] Registered to %s", future->id_str(), id_str());
72
73 if(state() == Fiber::Dead) {
74 // Fiber already dead, set the future now.
75# ifdef ZTH_FUTURE_EXCEPTION
76 setFuture(std::make_exception_ptr(fiber_already_dead()));
77# else
78 setFuture();
79# endif
80 }
81 }
82
84 {
85 return m_future;
86 }
87
89 {
90 if(!m_future.get()) {
93 ? new Future_type()
94 : new Future_type(
95 format("Future of %s", this->name().c_str())
96 .c_str()));
97 }
98
99 return m_future;
100 }
101
103 {
104 return withFuture();
105 }
106
108 {
109 return withFuture();
110 }
111
112protected:
113 static void entry(void* that)
114 {
115 if(unlikely(!that))
116 return;
117
118 TypedFiber& f = *static_cast<TypedFiber*>(that);
119
120# ifdef ZTH_FUTURE_EXCEPTION
121 try {
122# endif // ZTH_FUTURE_EXCEPTION
123 f.entry_();
124# ifdef ZTH_FUTURE_EXCEPTION
125 } catch(...) {
126 f.setFuture(std::current_exception());
127 }
128# endif // ZTH_FUTURE_EXCEPTION
129 }
130
131 virtual void entry_() = 0;
132
133 template <typename T>
134 void setFuture(T const& r)
135 {
136 if(m_future.get())
137 m_future->set(r);
138 }
139
141 {
142 if(m_future.get())
143 m_future->set();
144 }
145
146# ifdef ZTH_FUTURE_EXCEPTION
147 void setFuture(std::exception_ptr exception)
148 {
149 if(m_future.get())
150 m_future->set(std::move(exception));
151 }
152# endif // ZTH_FUTURE_EXCEPTION
153private:
154 SharedPointer<Future_type> m_future;
155};
156
158
177 size_t stack;
178
179 constexpr explicit setStackSize(size_t s) noexcept
180 : stack(s)
181 {}
182};
183
184template <typename R>
185TypedFiber<R>& operator<<(TypedFiber<R>& fiber, setStackSize const& m)
186{
187 if(m.stack) {
188 int res = fiber.setStackSize(m.stack);
189 if(res)
190 zth_throw(errno_exception(res));
191 }
192
193 return fiber;
194}
195
202struct setName : public FiberManipulator {
203# if __cplusplus >= 201103L
204 explicit setName(char const* n)
205 : name(n ? std::string{n} : std::string{})
206 {}
207
208 explicit setName(string const& n)
209 : name(n)
210 {}
211 explicit setName(string&& n)
212 : name(std::move(n))
213 {}
214# else // Pre C++11
215 explicit setName(char const* n)
216 : name(n)
217 {}
218
219 explicit setName(string const& n)
220 : name(n.c_str())
221 {}
222# endif // Pre C++11
223
224# if __cplusplus >= 201103L
225 string name;
226# else
227 char const* name;
228# endif
229};
230
231template <typename R>
233{
234 fiber.setName(m.name);
235 return fiber;
236}
237
238# if __cplusplus >= 201103L
239template <typename R>
240TypedFiber<R>& operator<<(TypedFiber<R>& fiber, setName&& m)
241{
242 fiber.setName(std::move(m.name));
243 return fiber;
244}
245# endif // C++11
246
268public:
269 constexpr explicit passOnExit(Gate& g) noexcept
270 : gate(g)
271 {}
272
273 static void atExit(Fiber& UNUSED_PAR(f), void* g) noexcept
274 {
275 static_cast<Gate*>(g)->pass();
276 }
277
279};
280
281static inline Fiber& operator<<(Fiber& fiber, passOnExit const& m)
282{
283 fiber.atExit(&passOnExit::atExit, static_cast<void*>(&m.gate));
284 return fiber;
285}
286
287template <typename R>
288TypedFiber<R>& operator<<(TypedFiber<R>& fiber, passOnExit const& m)
289{
290 static_cast<Fiber&>(fiber) << m;
291 return fiber;
292}
293
311struct asFuture : public FiberManipulator {};
312
313template <typename R>
315operator<<(TypedFiber<R>& fiber, asFuture const&)
316{
317 return fiber.withFuture();
318}
319
320
321
323// Actual TypedFiber implementations
324//
325// The TypedFiberX classes hold the actual entry point and arguments for the fiber. For Pre-C++11,
326// up to 3 arguments are supported. For C++11 and later, arbitrary arguments are supported.
327//
328
329# if ZTH_TYPEDFIBER98
330template <typename R>
331class TypedFiber0 final : public TypedFiber<R> {
332 ZTH_CLASS_NEW_DELETE(TypedFiber0)
333public:
334 typedef TypedFiber<R> base;
335 typedef R (*Function)();
336
337 explicit TypedFiber0(Function function)
338 : m_function(function)
339 {}
340
341 virtual ~TypedFiber0() final is_default
342
343protected:
344 virtual void entry_() final
345 {
346 this->setFuture(m_function());
347 }
348
349private:
350 Function m_function;
351};
352
353template <>
354class TypedFiber0<void> final : public TypedFiber<void> {
355 ZTH_CLASS_NEW_DELETE(TypedFiber0)
356public:
357 typedef TypedFiber<void> base;
358 typedef void (*Function)();
359
360 explicit TypedFiber0(Function func)
361 : m_function(func)
362 {}
363
364 virtual ~TypedFiber0() noexcept final is_default
365
366protected:
367 virtual void entry_() final
368 {
369 m_function();
370 this->setFuture();
371 }
372
373private:
374 Function m_function;
375};
376
377template <typename R, typename A1>
378class TypedFiber1 final : public TypedFiber<R> {
379 ZTH_CLASS_NEW_DELETE(TypedFiber1)
380public:
381 typedef TypedFiber<R> base;
382 typedef R (*Function)(A1);
383
384 TypedFiber1(Function func, A1 a1)
385 : m_function(func)
386 , m_a1(a1)
387 {}
388
389 virtual ~TypedFiber1() noexcept final is_default
390
391protected:
392 virtual void entry_() final
393 {
394 this->setFuture(m_function(m_a1));
395 }
396
397private:
398 Function m_function;
399 A1 m_a1;
400};
401
402template <typename A1>
403class TypedFiber1<void, A1> final : public TypedFiber<void> {
404 ZTH_CLASS_NEW_DELETE(TypedFiber1)
405public:
406 typedef TypedFiber<void> base;
407 typedef void (*Function)(A1);
408
409 // cppcheck-suppress uninitMemberVar
410 TypedFiber1(Function func, A1 a1)
411 : m_function(func)
412 , m_a1(a1)
413 {}
414
415 virtual ~TypedFiber1() noexcept final is_default
416
417protected:
418 virtual void entry_() final
419 {
420 m_function(m_a1);
421 this->setFuture();
422 }
423
424private:
425 Function m_function;
426 A1 m_a1;
427};
428
429template <typename R, typename A1, typename A2>
430class TypedFiber2 final : public TypedFiber<R> {
431 ZTH_CLASS_NEW_DELETE(TypedFiber2)
432public:
433 typedef TypedFiber<R> base;
434 typedef R (*Function)(A1, A2);
435
436 TypedFiber2(Function func, A1 a1, A2 a2)
437 : m_function(func)
438 , m_a1(a1)
439 , m_a2(a2)
440 {}
441
442 virtual ~TypedFiber2() noexcept final is_default
443
444protected:
445 virtual void entry_() final
446 {
447 this->setFuture(m_function(m_a1, m_a2));
448 }
449
450private:
451 Function m_function;
452 A1 m_a1;
453 A2 m_a2;
454};
455
456template <typename A1, typename A2>
457class TypedFiber2<void, A1, A2> final : public TypedFiber<void> {
458 ZTH_CLASS_NEW_DELETE(TypedFiber2)
459public:
460 typedef TypedFiber<void> base;
461 typedef void (*Function)(A1, A2);
462
463 // cppcheck-suppress uninitMemberVar
464 TypedFiber2(Function func, A1 a1, A2 a2)
465 : m_function(func)
466 , m_a1(a1)
467 , m_a2(a2)
468 {}
469
470 virtual ~TypedFiber2() noexcept final is_default
471
472protected:
473 virtual void entry_() final
474 {
475 m_function(m_a1, m_a2);
476 this->setFuture();
477 }
478
479private:
480 Function m_function;
481 A1 m_a1;
482 A2 m_a2;
483};
484
485template <typename R, typename A1, typename A2, typename A3>
486class TypedFiber3 final : public TypedFiber<R> {
487 ZTH_CLASS_NEW_DELETE(TypedFiber3)
488public:
489 typedef TypedFiber<R> base;
490 typedef R (*Function)(A1, A2, A3);
491
492 TypedFiber3(Function func, A1 a1, A2 a2, A3 a3)
493 : m_function(func)
494 , m_a1(a1)
495 , m_a2(a2)
496 , m_a3(a3)
497 {}
498
499 virtual ~TypedFiber3() noexcept final is_default
500
501protected:
502 virtual void entry_() final
503 {
504 this->setFuture(m_function(m_a1, m_a2, m_a3));
505 }
506
507private:
508 Function m_function;
509 A1 m_a1;
510 A2 m_a2;
511 A3 m_a3;
512};
513
514template <typename A1, typename A2, typename A3>
515class TypedFiber3<void, A1, A2, A3> final : public TypedFiber<void> {
516 ZTH_CLASS_NEW_DELETE(TypedFiber3)
517public:
518 typedef TypedFiber<void> base;
519 typedef void (*Function)(A1, A2, A3);
520
521 // cppcheck-suppress uninitMemberVar
522 TypedFiber3(Function func, A1 a1, A2 a2, A3 a3)
523 : m_function(func)
524 , m_a1(a1)
525 , m_a2(a2)
526 , m_a3(a3)
527 {}
528
529 virtual ~TypedFiber3() noexcept final is_default
530
531protected:
532 virtual void entry_() final
533 {
534 m_function(m_a1, m_a2, m_a3);
535 this->setFuture();
536 }
537
538private:
539 Function m_function;
540 A1 m_a1;
541 A2 m_a2;
542 A3 m_a3;
543};
544# endif // ZTH_TYPEDFIBER98
545
546# if __cplusplus >= 201103L
547// Always try to move the argument, unless it's an lvalue reference.
548template <typename T, typename std::enable_if<!std::is_lvalue_reference<T>::value, int>::type = 0>
549static constexpr T&& move_or_ref(T& t) noexcept
550{
551 return std::move(t);
552}
553
554template <typename T, typename std::enable_if<std::is_lvalue_reference<T>::value, int>::type = 0>
555static constexpr T move_or_ref(T t) noexcept
556{
557 return t;
558}
559
566template <typename F, typename R, typename Args>
567class TypedFiberN final : public TypedFiber<R> {
569public:
571 using Function = F;
572
573 template <typename F_, typename... Args_>
574 TypedFiberN(F_&& func, Args_&&... args)
575 : m_function{std::forward<F_>(func)}
576 , m_args{std::forward<Args_>(args)...}
577 {}
578
579 virtual ~TypedFiberN() final = default;
580
581protected:
582 virtual void entry_() final
583 {
584 entry__(typename SequenceGenerator<std::tuple_size<Args>::value>::type());
585 }
586
587private:
588 template <size_t... S>
589 void entry__(Sequence<S...>)
590 {
591 this->setFuture(m_function(
592 move_or_ref<typename std::tuple_element<S, Args>::type>(
593 std::get<S>(m_args))...));
594 }
595
596private:
597 Function m_function;
598 Args m_args;
599};
600
601template <typename F, typename Args>
602class TypedFiberN<F, void, Args> final : public TypedFiber<void> {
604public:
606 using Function = F;
607
608 template <typename F_, typename... Args_>
609 TypedFiberN(F_&& func, Args_&&... args)
610 : m_function{std::forward<F_>(func)}
611 , m_args{std::forward<Args_>(args)...}
612 {}
613
614 virtual ~TypedFiberN() final = default;
615
616protected:
617 virtual void entry_() final
618 {
619 entry__(typename SequenceGenerator<std::tuple_size<Args>::value>::type());
620 }
621
622private:
623 template <size_t... S>
624 void entry__(Sequence<S...>)
625 {
626 m_function(
627 move_or_ref<typename std::tuple_element<S, Args>::type>(
628 std::get<S>(m_args))...);
629 this->setFuture();
630 }
631
632private:
633 Function m_function;
634 Args m_args;
635};
636# endif // C++11
637
638
639
641// Define TypedFiberType to extract function type information to pick the right TypedFiberX class.
642//
643
644template <typename F>
646 typedef F type;
647};
648
649# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_(P, PArgs, suffix, ...) \
650 template <typename R, ##__VA_ARGS__> \
651 struct remove_function_cvref<R P PArgs suffix> { \
652 typedef R(type) PArgs; \
653 };
654
655# if ZTH_TYPEDFIBER98
656# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A0(P, suffix) \
657 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_(P, (), suffix)
658# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A1(P, suffix) \
659 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_(P, (A1), suffix, typename A1)
660# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A2(P, suffix) \
661 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_(P, (A1, A2), suffix, typename A1, typename A2)
662# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A3(P, suffix) \
663 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_( \
664 P, (A1, A2, A3), suffix, typename A1, typename A2, typename A3)
665
666# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A(P, suffix) \
667 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A0(P, suffix) \
668 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A1(P, suffix) \
669 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A2(P, suffix) \
670 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A3(P, suffix)
671# else
672# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A(P, suffix)
673# endif // ZTH_TYPEDFIBER98
674
675# if __cplusplus >= 201103L
676# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS(P, suffix) \
677 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A(P, suffix) \
678 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_(P, (Args...), suffix, typename... Args)
679# else
680# define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS(P, suffix) \
681 REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A(P, suffix)
682# endif // C++11
683
688
689# if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
694# endif // __cpp_noexcept_function_type
695
696# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_
697# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A0
698# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A1
699# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A2
700# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A3
701# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS_A
702# undef REMOVE_FUNCTION_CVREF_SPECIALIZATIONS
703
704# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_(PArgs, cvref, ...) \
705 template <typename R, typename C, ##__VA_ARGS__> \
706 struct remove_function_cvref<R(C::*) PArgs cvref> { \
707 typedef R(type) PArgs; \
708 };
709
710# if ZTH_TYPEDFIBER98
711# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A0(cvref) \
712 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_((), cvref)
713# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A1(cvref) \
714 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_((A1), cvref, typename A1)
715# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A2(cvref) \
716 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_((A1, A2), cvref, typename A1, typename A2)
717# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A3(cvref) \
718 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_( \
719 (A1, A2, A3), cvref, typename A1, typename A2, typename A3)
720# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A(cvref) \
721 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A0(cvref) \
722 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A1(cvref) \
723 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A2(cvref) \
724 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A3(cvref)
725# else
726# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A(cvref)
727# endif // ZTH_TYPEDFIBER98
728
729# if __cplusplus >= 201103L
730# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(cvref) \
731 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A(cvref) \
732 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_((Args...), cvref, typename... Args)
733# else
734# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(cvref) \
735 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A(cvref)
736# endif // C++11
737
738# define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_CV(...) \
739 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(__VA_ARGS__) \
740 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(const __VA_ARGS__) \
741 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(volatile __VA_ARGS__) \
742 REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS(const volatile __VA_ARGS__)
743
745# if __cplusplus >= 201103L
748
749# if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510
753# endif // __cpp_noexcept_function_type
754# endif // C++11
755
756# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_
757# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A0
758# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A1
759# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A2
760# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A3
761# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_A
762# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS
763# undef REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_CV
764
765# if __cplusplus >= 201103L
766template <typename T>
768
769template <typename R, typename... Args>
770struct functor_operator_type<R(Args...)> {
771 using return_type = R;
772 using args_type = std::tuple<Args...>;
773};
774
775// Extract function type from functor's operator().
776template <typename F>
778 using functor_type = typename std::decay<F>::type;
779
780private:
782 typename remove_function_cvref<decltype(&functor_type::operator())>::type>;
783
784public:
785 using return_type = typename functor_operator_type_::return_type;
786 using args_type = typename functor_operator_type_::args_type;
787};
788
789// Extract function type from function pointer.
790template <typename R, typename... Args>
791struct functor_traits<R (*)(Args...)> {
792public:
793 using functor_type = R (*)(Args...);
794 using return_type = R;
795 using args_type = std::tuple<Args...>;
796};
797
798template <typename R, typename... Args>
799struct functor_traits<R (*&)(Args...)> {
800public:
801 using functor_type = R (*)(Args...);
802 using return_type = R;
803 using args_type = std::tuple<Args...>;
804};
805
806// Extract function type from function reference.
807template <typename R, typename... Args>
808struct functor_traits<R (&)(Args...)> {
809public:
810 using functor_type = R (&)(Args...);
811 using return_type = R;
812 using args_type = std::tuple<Args...>;
813};
814
815// Extract function type from function type.
816template <typename R, typename... Args>
817struct functor_traits<R(Args...)> {
818public:
819 using functor_type = R (*)(Args...);
820 using return_type = R;
821 using args_type = std::tuple<Args...>;
822};
823
824// Extract fiber function type information.
825template <typename F>
837# else // Pre C++11
838template <typename F>
839struct TypedFiberType {};
840# endif // Pre C++11
841
842# if ZTH_TYPEDFIBER98
843# define ZTH_TYPEDFIBERTYPE_SPECIALIZATION(P) \
844 template <typename R> \
845 struct TypedFiberType<R P()> { \
846 struct NoArg {}; \
847 typedef R returnType; \
848 typedef TypedFiber0<R> fiberType; \
849 typedef NoArg a1Type; \
850 typedef NoArg a2Type; \
851 typedef NoArg a3Type; \
852 }; \
853 \
854 template <typename R, typename A1> \
855 struct TypedFiberType<R P(A1)> { \
856 struct NoArg {}; \
857 typedef R returnType; \
858 typedef TypedFiber1<R, A1> fiberType; \
859 typedef A1 a1Type; \
860 typedef NoArg a2Type; \
861 typedef NoArg a3Type; \
862 }; \
863 \
864 template <typename R, typename A1, typename A2> \
865 struct TypedFiberType<R P(A1, A2)> { \
866 struct NoArg {}; \
867 typedef R returnType; \
868 typedef TypedFiber2<R, A1, A2> fiberType; \
869 typedef A1 a1Type; \
870 typedef A2 a2Type; \
871 typedef NoArg a3Type; \
872 }; \
873 \
874 template <typename R, typename A1, typename A2, typename A3> \
875 struct TypedFiberType<R P(A1, A2, A3)> { \
876 struct NoArg {}; \
877 typedef R returnType; \
878 typedef TypedFiber3<R, A1, A2, A3> fiberType; \
879 typedef A1 a1Type; \
880 typedef A2 a2Type; \
881 typedef A3 a3Type; \
882 };
883
884ZTH_TYPEDFIBERTYPE_SPECIALIZATION()
885ZTH_TYPEDFIBERTYPE_SPECIALIZATION((*))
886ZTH_TYPEDFIBERTYPE_SPECIALIZATION((*&))
887ZTH_TYPEDFIBERTYPE_SPECIALIZATION((&))
888
889# undef ZTH_TYPEDFIBERTYPE_SPECIALIZATION
890# endif // ZTH_TYPEDFIBER98
891
892
893
895// Define a TypedFiberFactory. It holds the entry function and creates fibers when the arguments are
896// passed. The entry function and name are stored in the factory, the arguments are passed directly
897// to the new fiber (managed by TypedFiberX).
898//
899
900template <typename F>
902 typedef F type;
903};
904
905# if ZTH_TYPEDFIBER98
906# define FUNCTION_TYPE_HELPER_SPECIALIZATION(P) \
907 template <typename R> \
908 struct function_type_helper<R P()> { \
909 typedef R (*type)(); \
910 }; \
911 \
912 template <typename R, typename A1> \
913 struct function_type_helper<R P(A1)> { \
914 typedef R (*type)(A1); \
915 }; \
916 \
917 template <typename R, typename A1, typename A2> \
918 struct function_type_helper<R P(A1, A2)> { \
919 typedef R (*type)(A1, A2); \
920 }; \
921 \
922 template <typename R, typename A1, typename A2, typename A3> \
923 struct function_type_helper<R P(A1, A2, A3)> { \
924 typedef R (*type)(A1, A2, A3); \
925 };
926
927FUNCTION_TYPE_HELPER_SPECIALIZATION()
928FUNCTION_TYPE_HELPER_SPECIALIZATION((*))
929FUNCTION_TYPE_HELPER_SPECIALIZATION((*&))
930FUNCTION_TYPE_HELPER_SPECIALIZATION((&))
931
932# undef FUNCTION_TYPE_HELPER_SPECIALIZATION
933# endif // ZTH_TYPEDFIBER98
934
935# if __cplusplus >= 201103L
936template <typename R, typename... Args>
937struct function_type_helper<R(Args...)> {
938 using type = R (*)(Args...);
939};
940
941template <typename R, typename... Args>
942struct function_type_helper<R (*)(Args...)> {
943 using type = R (*)(Args...);
944};
945
946template <typename R, typename... Args>
947struct function_type_helper<R (*&)(Args...)> {
948 using type = R (*)(Args...);
949};
950
951template <typename R, typename... Args>
952struct function_type_helper<R (&)(Args...)> {
953 using type = R (*)(Args...);
954};
955# endif // C++11
956
957template <typename F>
958struct fiber_type;
959
960template <typename F>
962public:
967
968 constexpr TypedFiberFactory(Function function, char const* name) noexcept
969 : m_function(function)
970 , m_name(name)
971 {}
972
973# if __cplusplus >= 201103L
974 template <typename F_>
975 constexpr TypedFiberFactory(F_&& function, char const* name) noexcept
976 : m_function{std::forward<F_>(function)}
977 , m_name{name}
978 {}
979# endif // C++11
980
981# if ZTH_TYPEDFIBER98
982 typedef typename TypedFiberType<Function>::a1Type A1;
983 typedef typename TypedFiberType<Function>::a2Type A2;
984 typedef typename TypedFiberType<Function>::a3Type A3;
985
986 fiber_type<Function> operator()() const
987 {
988 return polish(*new TypedFiber_type(m_function));
989 }
990
991 fiber_type<Function> operator()(A1 a1) const
992 {
993 return polish(*new TypedFiber_type(m_function, a1));
994 }
995
996 fiber_type<Function> operator()(A1 a1, A2 a2) const
997 {
998 return polish(*new TypedFiber_type(m_function, a1, a2));
999 }
1000
1001 fiber_type<Function> operator()(A1 a1, A2 a2, A3 a3) const
1002 {
1003 return polish(*new TypedFiber_type(m_function, a1, a2, a3));
1004 }
1005# endif // ZTH_TYPEDFIBER98
1006
1007# if __cplusplus >= 201103L
1008 template <typename... Args>
1009 fiber_type<Function> operator()(Args&&... args) const
1010 {
1011 return polish(*new TypedFiber_type{m_function, std::forward<Args>(args)...});
1012 }
1013# endif // C++11
1014
1015protected:
1017 {
1018 if(unlikely(m_name))
1019 fiber.setName(m_name);
1020
1022 return fiber;
1023 }
1024
1025private:
1026 Function m_function;
1027 char const* m_name;
1028};
1029
1030
1031
1033// Provide a zth::fiber_type<F> API to get fiber information.
1034//
1035
1036template <typename F>
1039 typedef typename factory::Function function;
1040 typedef typename factory::Future future;
1042
1045
1046 // cppcheck-suppress noExplicitConstructor
1048 : _fiber(&f)
1049 {}
1050
1052 {
1053 future f = _fiber->withFuture();
1054 f.get().wait();
1055 return *f;
1056 }
1057
1059 {
1060 future f = _fiber->withFuture();
1061 f.get().wait();
1062 return *f;
1063 }
1064
1065 TypedFiber_type& getFiber() const noexcept
1066 {
1067 return *_fiber;
1068 }
1069
1070 operator TypedFiber_type&() const noexcept
1071 {
1072 return getFiber();
1073 }
1074
1075 operator Fiber&() const noexcept
1076 {
1077 return getFiber();
1078 }
1079
1080 future getFuture() const noexcept
1081 {
1082 return _fiber->withFuture();
1083 }
1084
1085 operator future() const noexcept
1086 {
1087 return getFuture();
1088 }
1089
1090 zth_fiber_t handle() const noexcept
1091 {
1092 return getFiber().handle();
1093 }
1094
1095 void kill() noexcept
1096 {
1097 _fiber->kill();
1098 }
1099
1100 void cancel()
1101 {
1102 _fiber->cancel();
1103 }
1104
1105 template <typename Manipulator>
1106 fiber& operator<<(Manipulator const& m) LREF_QUALIFIED
1107 {
1108 *_fiber << m;
1109 return *this;
1110 }
1111
1112 template <typename Manipulator>
1113 fiber const& operator<<(Manipulator const& m) const
1114 {
1115 *_fiber << m;
1116 return *this;
1117 }
1118
1119# if __cplusplus >= 201103L
1120 template <typename Manipulator>
1121 fiber&& operator<<(Manipulator const& m) &&
1122 {
1123 *_fiber << m;
1124 return std::move(*this);
1125 }
1126# endif // C++11
1127
1129 {
1130 return *_fiber << asFuture();
1131 }
1132};
1133
1134
1135
1137// zth::factory() and zth::fiber() functions
1138//
1139
1140namespace impl {
1141static inline char const* fiber_name(char const* name)
1142{
1143 return (zth_config(EnableDebugPrint) || Config::EnablePerfEvent
1145 ? name
1146 : nullptr;
1147}
1148} // namespace impl
1149
1150# if __cplusplus >= 201103L
1159template <typename F>
1160typename fiber_type<F>::factory factory(F&& f, char const* name = nullptr)
1161{
1162 return typename fiber_type<F>::factory(std::forward<F>(f), impl::fiber_name(name));
1163}
1164
1165template <typename F>
1166typename fiber_type<F>::factory factory(F const& f, char const* name = nullptr)
1167{
1168 return typename fiber_type<F>::factory(f, impl::fiber_name(name));
1169}
1170# else // Pre-C++11
1171template <typename F>
1172typename fiber_type<F>::factory factory(F f, char const* name = nullptr)
1173{
1174 return typename fiber_type<F>::factory(f, impl::fiber_name(name));
1175}
1176# endif // Pre-C++11
1177
1178# if ZTH_TYPEDFIBER98
1179template <typename F>
1180typename fiber_type<F>::fiber fiber(F f)
1181{
1182 return factory<F>(f)();
1183}
1184
1185template <typename F>
1186typename fiber_type<F>::fiber fiber(F f, typename fiber_type<F>::factory::A1 a1)
1187{
1188 return factory<F>(f)(a1);
1189}
1190
1191template <typename F>
1192typename fiber_type<F>::fiber
1193fiber(F f, typename fiber_type<F>::factory::A1 a1, typename fiber_type<F>::factory::A2 a2)
1194{
1195 return factory<F>(f)(a1, a2);
1196}
1197
1198template <typename F>
1199typename fiber_type<F>::fiber
1200fiber(F f, typename fiber_type<F>::factory::A1 a1, typename fiber_type<F>::factory::A2 a2,
1201 typename fiber_type<F>::factory::A3 a3)
1202{
1203 return factory<F>(f)(a1, a2, a3);
1204}
1205# endif // ZTH_TYPEDFIBER98
1206
1207# if __cplusplus >= 201103L
1220template <typename F, typename... Args>
1221typename fiber_type<F>::fiber fiber(F&& f, Args&&... args)
1222{
1223 return factory<F>(std::forward<F>(f))(std::forward<Args>(args)...);
1224}
1225# endif // C++11
1226
1227
1228
1230// Simplify fiber future type access
1231//
1232
1233namespace impl {
1234template <typename F>
1236 enum { value = 0 };
1237};
1238
1239# if ZTH_TYPEDFIBER98
1240template <typename R>
1241struct is_function_<R()> {
1242 enum { value = 1 };
1243};
1244template <typename R, typename A1>
1245struct is_function_<R(A1)> {
1246 enum { value = 1 };
1247};
1248template <typename R, typename A1, typename A2>
1249struct is_function_<R(A1, A2)> {
1250 enum { value = 1 };
1251};
1252template <typename R, typename A1, typename A2, typename A3>
1253struct is_function_<R(A1, A2, A3)> {
1254 enum { value = 1 };
1255};
1256# endif // ZTH_TYPEDFIBER98
1257
1258# if __cplusplus >= 201103L
1259template <typename T, typename... Args>
1260struct is_function_<T(Args...)> {
1261 enum { value = 1 };
1262};
1263# endif // C++11
1264} // namespace impl
1265
1266template <typename T>
1270
1271template <typename T>
1273 typedef char yes;
1274 typedef long no;
1275
1276 template <typename C>
1277 static yes test(decltype(&C::operator())*);
1278
1279 template <typename>
1280 static no test(...);
1281
1282 enum { value = sizeof(test<T>(nullptr)) == sizeof(yes) };
1283};
1284
1285template <typename T>
1289
1290namespace impl {
1291
1292template <
1293 typename T, bool =
1294# if __cplusplus >= 201103L
1296# else
1298# endif // C++11
1299 >
1301 typedef typename fiber_type<T>::future type;
1302};
1303
1304template <typename T>
1305struct fiber_future_helper<T, false> {
1307};
1308
1309} // namespace impl
1310
1320template <typename T = void>
1321struct fiber_future : public impl::fiber_future_helper<T>::type {
1325
1326 template <typename F>
1327 // cppcheck-suppress noExplicitConstructor
1328 fiber_future(F& f) noexcept
1329 : base(static_cast<future_type const&>(f))
1330 {}
1331
1332 template <typename F>
1333 // cppcheck-suppress noExplicitConstructor
1334 fiber_future(F const& f) noexcept
1335 : base(static_cast<future_type const&>(f))
1336 {}
1337};
1338
1339# if __cplusplus >= 201703L
1340// Deduction guides for fiber_future.
1341template <typename F>
1343
1344template <typename F>
1346# endif // C++17
1347
1348
1349
1351// Simple join
1352//
1353
1354// cppcheck-suppress constParameterReference
1355static inline void joinable(Fiber& f, Gate& g, Hook<Gate&>& UNUSED_PAR(join)) noexcept
1356{
1357 f << passOnExit(g);
1358}
1359
1360template <typename F>
1361static inline void
1362joinable(typename fiber_type<F>::fiber const& f, Gate& g, Hook<Gate&>& UNUSED_PAR(join)) noexcept
1363{
1364 f << passOnExit(g);
1365}
1366
1367template <typename T>
1368static inline void joinable(Future<T>& f, Gate& UNUSED_PAR(g), Hook<Gate&>& join) noexcept
1369{
1370 struct impl {
1371 static void cb(Gate& g_, void* f_) noexcept
1372 {
1373 Future<T>* f = static_cast<Future<T>*>(f_);
1374 f->wait();
1375 f->unused();
1376 g_.pass();
1377 }
1378 };
1379
1380 f.used();
1381 join.add(&impl::cb, static_cast<void*>(&f));
1382}
1383
1384template <typename T>
1385static inline void
1386joinable(SharedReference<Future<T> > const& f, Gate& g, Hook<Gate&>& join) noexcept
1387{
1388 joinable(f.get(), g, join);
1389}
1390
1405class joiner {
1407public:
1408 joiner() noexcept
1409 : m_gate(1)
1410 {}
1411
1412# if ZTH_TYPEDFIBER98
1413 template <typename J0>
1414 explicit joiner(J0& j0)
1415 : m_gate(2)
1416 {
1417 joinable(j0, m_gate, m_join);
1418 }
1419
1420 template <typename J0>
1421 explicit joiner(J0 const& j0)
1422 : m_gate(2)
1423 {
1424 joinable(j0, m_gate, m_join);
1425 }
1426
1427 template <typename J0, typename J1>
1428 explicit joiner(J0& j0, J1& j1)
1429 : m_gate(3)
1430 {
1431 joinable(j0, m_gate, m_join);
1432 joinable(j1, m_gate, m_join);
1433 }
1434
1435 template <typename J0, typename J1>
1436 explicit joiner(J0 const& j0, J1 const& j1)
1437 : m_gate(3)
1438 {
1439 joinable(j0, m_gate, m_join);
1440 joinable(j1, m_gate, m_join);
1441 }
1442
1443 template <typename J0, typename J1, typename J2>
1444 explicit joiner(J0& j0, J1& j1, J2& j2)
1445 : m_gate(4)
1446 {
1447 joinable(j0, m_gate, m_join);
1448 joinable(j1, m_gate, m_join);
1449 joinable(j2, m_gate, m_join);
1450 }
1451
1452 template <typename J0, typename J1, typename J2>
1453 explicit joiner(J0 const& j0, J1 const& j1, J2 const& j2)
1454 : m_gate(4)
1455 {
1456 joinable(j0, m_gate, m_join);
1457 joinable(j1, m_gate, m_join);
1458 joinable(j2, m_gate, m_join);
1459 }
1460
1461 template <typename J0, typename J1, typename J2, typename J3>
1462 explicit joiner(J0& j0, J1& j1, J2& j2, J3& j3)
1463 : m_gate(5)
1464 {
1465 joinable(j0, m_gate, m_join);
1466 joinable(j1, m_gate, m_join);
1467 joinable(j2, m_gate, m_join);
1468 joinable(j3, m_gate, m_join);
1469 }
1470
1471 template <typename J0, typename J1, typename J2, typename J3>
1472 explicit joiner(J0 const& j0, J1 const& j1, J2 const& j2, J3 const& j3)
1473 : m_gate(5)
1474 {
1475 joinable(j0, m_gate, m_join);
1476 joinable(j1, m_gate, m_join);
1477 joinable(j2, m_gate, m_join);
1478 joinable(j3, m_gate, m_join);
1479 }
1480
1481 template <typename J0, typename J1, typename J2, typename J3, typename J4>
1482 explicit joiner(J0& j0, J1& j1, J2& j2, J3& j3, J4& j4)
1483 : m_gate(6)
1484 {
1485 joinable(j0, m_gate, m_join);
1486 joinable(j1, m_gate, m_join);
1487 joinable(j2, m_gate, m_join);
1488 joinable(j3, m_gate, m_join);
1489 joinable(j4, m_gate, m_join);
1490 }
1491
1492 template <typename J0, typename J1, typename J2, typename J3, typename J4>
1493 explicit joiner(J0 const& j0, J1 const& j1, J2 const& j2, J3 const& j3, J4 const& j4)
1494 : m_gate(6)
1495 {
1496 joinable(j0, m_gate, m_join);
1497 joinable(j1, m_gate, m_join);
1498 joinable(j2, m_gate, m_join);
1499 joinable(j3, m_gate, m_join);
1500 joinable(j4, m_gate, m_join);
1501 }
1502# endif // ZTH_TYPEDFIBER98
1503
1504# if __cplusplus >= 201103L
1505 template <typename... J>
1506 explicit joiner(J&&... j)
1507 : m_gate{sizeof...(j) + 1U}
1508 {
1509 using dummy = int[];
1510 (void)dummy{0, (joinable(std::forward<J>(j), m_gate, m_join), 0)...};
1511 }
1512# endif // C++11
1513
1515 {
1516 m_join.once(m_gate);
1517 m_gate.wait();
1518 }
1519
1520private:
1521 Gate m_gate;
1522 Hook<Gate&> m_join;
1523};
1524
1525# if ZTH_TYPEDFIBER98
1526template <typename J0>
1527static inline void join(J0& j0)
1528{
1529 joiner jn(j0);
1530}
1531
1532template <typename J0, typename J1>
1533static inline void join(J0& j0, J1& j1)
1534{
1535 joiner jn(j0, j1);
1536}
1537
1538template <typename J0, typename J1, typename J2>
1539static inline void join(J0& j0, J1& j1, J2& j2)
1540{
1541 joiner jn(j0, j1, j2);
1542}
1543
1544template <typename J0, typename J1, typename J2, typename J3>
1545static inline void join(J0& j0, J1& j1, J2& j2, J3& j3)
1546{
1547 joiner jn(j0, j1, j2, j3);
1548}
1549
1550template <typename J0, typename J1, typename J2, typename J3, typename J4>
1551static inline void join(J0& j0, J1& j1, J2& j2, J3& j3, J4& j4)
1552{
1553 joiner jn(j0, j1, j2, j3, j4);
1554}
1555# endif
1556
1557# if __cplusplus >= 201103L
1562template <typename... J>
1563static inline void join(J&&... j)
1564{
1565 joiner jn{std::forward<J>(j)...};
1566}
1567# endif
1568
1569
1570
1572// zth_async macros
1573//
1574
1575namespace fibered {}
1576
1577} // namespace zth
1578
1579# define zth_fiber_declare_1(f) \
1580 namespace zth { \
1581 namespace fibered { \
1582 extern ::zth::fiber_type<decltype(&::f)>::factory const f; \
1583 } \
1584 }
1585
1590# define zth_fiber_declare(...) FOREACH(zth_fiber_declare_1, ##__VA_ARGS__)
1591
1592# define zth_fiber_define_1(storage, f) \
1593 namespace zth { \
1594 namespace fibered { \
1595 ZTH_DEPRECATED("Use zth::fiber(f, args...) instead") \
1596 storage ::zth::fiber_type<decltype(&::f)>::factory const \
1597 f(&::f, ::zth::Config::SupportDebugPrint || ::zth::Config::EnablePerfEvent \
1598 ? ZTH_STRINGIFY(f) "()" \
1599 : nullptr); /* NOLINT */ \
1600 } \
1601 } \
1602 typedef ::zth::fiber_type<decltype(&::f)>::future f##_future;
1603# define zth_fiber_define_extern_1(f) zth_fiber_define_1(extern, f)
1604# define zth_fiber_define_static_1(f) zth_fiber_define_1(static constexpr, f)
1605
1610# define zth_fiber_define(...) FOREACH(zth_fiber_define_extern_1, ##__VA_ARGS__)
1611
1616# define zth_fiber(...) FOREACH(zth_fiber_define_static_1, ##__VA_ARGS__)
1617
1637# define zth_async ::zth::fibered::
1638
1639
1640
1642// C API
1643//
1644
1649EXTERN_C ZTH_EXPORT ZTH_INLINE int zth_fiber_create(
1650 zth_fiber_t* h, void (*f)(void*), void* arg = nullptr, size_t stack = 0,
1651 char const* name = nullptr) noexcept
1652{
1653 if(h)
1654 h->p = nullptr;
1655
1656 try {
1657 zth::fiber_type<void(void*)>::fiber fib = zth::factory(f, name)(arg);
1658 fib << zth::setStackSize(stack);
1659 if(h)
1660 *h = fib.handle();
1661 } catch(std::bad_alloc const&) {
1662 return ENOMEM;
1663 } catch(zth::errno_exception const& e) {
1664# ifdef __cpp_exceptions
1665 return e.code;
1666# endif
1667 } catch(...) {
1668 return EAGAIN;
1669 }
1670
1671 return 0;
1672}
1673#else // !__cplusplus
1674
1675# include <stddef.h>
1676
1677ZTH_EXPORT int
1678zth_fiber_create(zth_fiber_t* h, void (*f)(void*), void* arg, size_t stack, char const* name);
1679
1680#endif // !__cplusplus
1681#endif // ZTH_ASYNC_H
#define REMOVE_FUNCTION_CVREF_SPECIALIZATIONS(P, suffix)
Definition async.h:676
#define REMOVE_FUNCTION_CVREF_MEMBER_SPECIALIZATIONS_CV(...)
Definition async.h:738
The fiber.
Definition fiber.h:62
State state() const noexcept
Definition fiber.h:163
zth_fiber_t handle() const noexcept
Definition fiber.h:127
Fiber-aware future.
Definition sync.h:1068
Fiber-aware barrier/gate.
Definition sync.h:1487
void wait()
Definition sync.h:1518
virtual char const * id_str() const noexcept override
Definition util.h:787
void setName(string const &name)
Definition util.h:766
string const & name() const noexcept
Definition util.h:761
SharedPointer_type::type type
Definition sync.h:200
constexpr T & get() const noexcept
Definition sync.h:163
TypedFiberType< Function >::fiberType TypedFiber_type
Definition async.h:965
TypedFiberType< Function >::returnType Return
Definition async.h:964
function_type_helper< F >::type Function
Definition async.h:963
fiber_type< Function > operator()(Args &&... args) const
Definition async.h:1009
SharedReference< typename TypedFiber_type::Future_type > Future
Definition async.h:966
constexpr TypedFiberFactory(F_ &&function, char const *name) noexcept
Definition async.h:975
constexpr TypedFiberFactory(Function function, char const *name) noexcept
Definition async.h:968
TypedFiber_type & polish(TypedFiber_type &fiber) const
Definition async.h:1016
Typed fiber class.
Definition async.h:56
virtual ~TypedFiber() noexcept override=default
void setFuture()
Definition async.h:140
SharedPointer< Future_type > const & withFuture()
Definition async.h:88
Future_type * future() const
Definition async.h:83
virtual void entry_()=0
Future< Return > Future_type
Definition async.h:60
constexpr TypedFiber()
Definition async.h:62
void setFuture(T const &r)
Definition async.h:134
void registerFuture(Future_type *future)
Definition async.h:68
static void entry(void *that)
Definition async.h:113
TypedFiberN(F_ &&func, Args_ &&... args)
Definition async.h:609
virtual ~TypedFiberN() final=default
Actual fiber implementation for arbitrary function types and arguments.
Definition async.h:567
virtual void entry_() final
Definition async.h:582
virtual ~TypedFiberN() final=default
TypedFiberN(F_ &&func, Args_ &&... args)
Definition async.h:574
void hatch(Fiber &fiber) noexcept
Definition worker.h:132
RAII class to join fibers and futures on destruction.
Definition async.h:1405
joiner(J &&... j)
Definition async.h:1506
joiner() noexcept
Definition async.h:1408
int zth_fiber_create(zth_fiber_t *h, 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:1649
#define zth_config(name)
Checks if the given zth::Config field is enabled.
Definition config.h:46
Worker & currentWorker() noexcept
Return the (thread-local) singleton Worker instance.
Definition worker.h:417
fiber_type< F >::factory factory(F &&f, char const *name=nullptr)
Create a new fiber.
Definition async.h:1160
fiber_type< F >::fiber fiber(F &&f, Args &&... args)
Create and start a new fiber.
Definition async.h:1221
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
Definition util.h:194
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
Definition util.h:330
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition allocator.h:160
#define zth_throw(...)
Definition macros.h:376
#define is_default
Definition macros.h:223
#define LREF_QUALIFIED
Definition macros.h:226
#define ZTH_INLINE
Definition macros.h:139
#define UNUSED_PAR(name)
Definition macros.h:79
STL namespace.
::std::future< zth::type< T > > future
Definition future.h:40
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
Definition util.h:498
TypedFiber< R > & operator<<(TypedFiber< R > &fiber, setStackSize const &m)
Definition async.h:185
static bool const EnablePerfEvent
Enable (but not necessarily record) perf.
Definition config.h:265
static bool const EnableStackWaterMark
When true, enable stack watermark to detect maximum stack usage.
Definition config.h:187
static bool const NamedSynchronizer
Save names for all zth::Synchronizer instances.
Definition config.h:236
typename traitsType::return_type returnType
Definition async.h:828
Forces the fiber to have a future that outlives the fiber.
Definition async.h:311
Wrapper for an errno.
Definition exception.h:41
Base exception class for Zth exceptions.
Definition exception.h:16
Exception thrown when an operation cannot be performed, as the fiber is already dead.
Definition exception.h:26
The future returned by a fiber.
Definition async.h:1321
future_type::type return_type
Definition async.h:1324
fiber_future(F const &f) noexcept
Definition async.h:1334
impl::fiber_future_helper< T >::type future_type
Definition async.h:1322
fiber_future(F &f) noexcept
Definition async.h:1328
future_type base
Definition async.h:1323
fiber_type< function > fiber
Definition async.h:1041
future getFuture() const noexcept
Definition async.h:1080
SharedPointer< TypedFiber_type > _fiber
Definition async.h:1044
TypedFiberFactory< typename function_type_helper< F >::type > factory
Definition async.h:1038
future operator<<(asFuture const &)
Definition async.h:1128
void kill() noexcept
Definition async.h:1095
TypedFiber_type & getFiber() const noexcept
Definition async.h:1065
fiber_type(TypedFiber_type &f) noexcept
Definition async.h:1047
TypedFiber_type::Return operator->()
Definition async.h:1058
factory::Function function
Definition async.h:1039
fiber const & operator<<(Manipulator const &m) const
Definition async.h:1113
factory::Future future
Definition async.h:1040
zth_fiber_t handle() const noexcept
Definition async.h:1090
fiber & operator<<(Manipulator const &m) &
Definition async.h:1106
factory::TypedFiber_type TypedFiber_type
Definition async.h:1043
fiber && operator<<(Manipulator const &m) &&
Definition async.h:1121
void cancel()
Definition async.h:1100
TypedFiber_type::Return operator*()
Definition async.h:1051
std::tuple< Args... > args_type
Definition async.h:772
std::tuple< Args... > args_type
Definition async.h:795
std::tuple< Args... > args_type
Definition async.h:803
std::tuple< Args... > args_type
Definition async.h:812
std::tuple< Args... > args_type
Definition async.h:821
typename std::decay< F >::type functor_type
Definition async.h:778
typename functor_operator_type_::args_type args_type
Definition async.h:786
typename functor_operator_type_::return_type return_type
Definition async.h:785
static yes test(decltype(&C::operator()) *)
static no test(...)
SharedReference< Future< T > > type
Definition async.h:1306
fiber_type< T >::future type
Definition async.h:1301
Makes the fiber pass the given gate upon exit.
Definition async.h:267
static void atExit(Fiber &f, void *g) noexcept
Definition async.h:273
constexpr passOnExit(Gate &g) noexcept
Definition async.h:269
Gate & gate
Definition async.h:278
Change the name of a fiber returned by zth_async.
Definition async.h:202
setName(string const &n)
Definition async.h:208
string name
Definition async.h:225
setName(char const *n)
Definition async.h:204
setName(string &&n)
Definition async.h:211
Change the stack size of a fiber returned by zth_async.
Definition async.h:176
constexpr setStackSize(size_t s) noexcept
Definition async.h:179
Opaque fiber handle type.
Definition fiber.h:24
void * p
Definition fiber.h:25
#define ZTH_CLASS_NOCOPY(Class)
Definition util.h:234
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:60