join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
proactor.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_PROACTOR_HPP
26#define JOIN_CORE_PROACTOR_HPP
27
28// libjoin.
30#include <join/io_operation.hpp>
31#include <join/function.hpp>
32#ifdef JOIN_HAS_IO_URING
33#include <join/io_policy.hpp>
34#include <join/wheel.hpp>
35#else
36#include <join/reactor.hpp>
37#endif
38#include <join/backoff.hpp>
39#include <join/thread.hpp>
40#include <join/memory.hpp>
41#include <join/queue.hpp>
42
43// C++.
44#include <unordered_map>
45#include <utility>
46#include <vector>
47
48// C.
49#include <sys/eventfd.h>
50#include <sys/prctl.h>
51#include <cerrno>
52
53namespace join
54{
55 class CompletionHandler;
56#ifdef JOIN_HAS_IO_URING
57 template <typename IoPolicy>
58 class BasicProactor;
59 template <typename IoPolicy>
60 class BasicProactorThread;
61
62 using Proactor = BasicProactor<IoDefaultPolicy>;
63 using HybridProactor = BasicProactor<IoHybridPolicy>;
64 using SqpollProactor = BasicProactor<IoSqpollPolicy>;
65 using ProactorThread = BasicProactorThread<IoDefaultPolicy>;
66 using HybridProactorThread = BasicProactorThread<IoHybridPolicy>;
67 using SqpollProactorThread = BasicProactorThread<IoSqpollPolicy>;
68#else
69 class BasicProactor;
70 class BasicProactorThread;
71
74#endif
75}
76
81{
83#ifdef JOIN_HAS_IO_URING
84 template <typename IoPolicy>
85 friend class join::BasicProactor;
86#else
87 friend class join::BasicProactor;
88#endif
89
90public:
94 CompletionHandler () = default;
95
100 CompletionHandler (const CompletionHandler& other) = default;
101
108
114
121
125 virtual ~CompletionHandler () = default;
126
127protected:
133 virtual void onComplete ([[maybe_unused]] IoOperation& op, [[maybe_unused]] int result)
134 {
135 // do nothing.
136 }
137
143 virtual void onCancel ([[maybe_unused]] IoOperation& op, [[maybe_unused]] int result)
144 {
145 // do nothing.
146 }
147};
148
152#ifdef JOIN_HAS_IO_URING
153template <typename IoPolicy = join::IoDefaultPolicy>
155#else
157#endif
158{
159private:
161 static constexpr size_t _queueSize = 1024;
162
163#ifdef JOIN_HAS_IO_URING
167 class WheelPolicy
168 {
169 public:
174 explicit WheelPolicy (BasicProactor& proactor) noexcept
175 : _proactor (proactor)
176 {
177 }
178
185 template <class Wheel>
186 int start ([[maybe_unused]] Wheel& wheel, [[maybe_unused]] std::chrono::nanoseconds period) noexcept
187 {
188 // do nothing, the event loop advances the wheel.
189 return 0;
190 }
191
195 void stop () noexcept
196 {
197 // do nothing, the event loop advances the wheel.
198 }
199
204 bool isRunnerThread () const noexcept
205 {
206 return _proactor.isProactorThread ();
207 }
208
214 template <class Wheel>
215 int flush ([[maybe_unused]] Wheel& wheel) noexcept
216 {
217 if (JOIN_UNLIKELY (!_proactor.isRunning ()))
218 {
219 return -1;
220 }
221
222 return _proactor.wakeup ();
223 }
224
225 private:
231 template <class Wheel>
232 static uint64_t advance (Wheel& wheel) noexcept
233 {
234 return wheel.advance ();
235 }
236
243 template <class Wheel>
244 static __kernel_timespec* timeout (const Wheel& wheel, __kernel_timespec& ts) noexcept
245 {
246 const std::chrono::nanoseconds next = wheel.next ();
247
248 if (next == std::chrono::nanoseconds::max ())
249 {
250 return nullptr;
251 }
252
253 ts.tv_sec = next.count () / 1'000'000'000;
254 ts.tv_nsec = next.count () % 1'000'000'000;
255
256 return &ts;
257 }
258
260 BasicProactor& _proactor;
261
263 friend class BasicProactor;
264 };
265#endif
266
267public:
269 using InvokeHandler = Function<void (), 64>;
270
271#ifdef JOIN_HAS_IO_URING
273 "tick must not be finer than the backoff sleep");
274
277#else
280#endif
281
285 explicit BasicProactor ();
286
291 BasicProactor (const BasicProactor& other) = delete;
292
298 BasicProactor& operator= (const BasicProactor& other) = delete;
299
304 BasicProactor (BasicProactor&& other) = delete;
305
312
316 ~BasicProactor () noexcept;
317
325 int submit (IoOperation& op, bool flush = false, bool sync = false) noexcept;
326
334 int cancel (IoOperation& op, bool flush = false, bool sync = false) noexcept;
335
342 int invoke (InvokeHandler* fn, bool sync = true) noexcept;
343
344#ifdef JOIN_HAS_IO_URING
350 int flush (bool sync = false) noexcept;
351#endif
352
357 void suspend (IoOperation& op) noexcept;
358
364 void resume (IoOperation& op, CompletionHandler& handler) noexcept;
365
369 void run ();
370
375 void stop (bool sync = true) noexcept;
376
380 void waitStopped () const noexcept;
381
382#ifdef JOIN_HAS_IO_URING
388 template <size_t Count, size_t... Sizes>
389 int registerFixedBuffers (LocalMem::SlabAllocator<Count, Sizes...>& arena) noexcept;
390
395 int unregisterFixedBuffers () noexcept;
396#endif
397
405 template <size_t Count, size_t Size>
406 int registerBufferRing (uint16_t group, LocalMem::SlabAllocator<Count, Size>& arena);
407
414 template <size_t Count, size_t Size>
416
422 int unregisterBufferRing (uint16_t group);
423
424#ifdef JOIN_HAS_NUMA
430 int mbind (int numa) const noexcept;
431#endif
432
437 int mlock () const noexcept;
438
443 bool isRunning () const noexcept;
444
449 bool isProactorThread () const noexcept;
450
455 Wheel& wheel () noexcept;
456
457private:
461 enum class WakeupState
462 {
463 Sleeping,
464 Waking,
465 Spinning,
466 };
467
471 enum class CommandType
472 {
473 Submit,
474 Cancel,
475 Invoke,
476 Stop,
477#ifdef JOIN_HAS_IO_URING
478 Flush,
479#endif
480 };
481
485 struct alignas (64) Command
486 {
487 CommandType type;
488 IoOperation* op;
489 bool flush;
490 std::atomic<bool>* done;
491 std::error_code* errc;
492 InvokeHandler* fn;
493 };
494
500 int writeCommand (const Command& cmd) noexcept;
501
502#ifdef JOIN_HAS_IO_URING
507 int wakeup () noexcept;
508#endif
509
513 void readCommands () noexcept;
514
519 void processCommand (const Command& cmd) noexcept;
520
527 int submitOperation (IoOperation& op, bool flush) noexcept;
528
535 int cancelOperation (IoOperation& op, bool flush) noexcept;
536
540 void cancelAllOperations () noexcept;
541
547 int invokeFunction (InvokeHandler* fn) noexcept;
548
555 void notifyOperation (IoOperation& op, int result, bool cancelled) noexcept;
556
563 void dispatchOperation (IoOperation& op, int result, bool cancelled) noexcept;
564
571 void endOperation (IoOperation& op, int result, bool cancelled = false) noexcept;
572
577 void resetOperation (IoOperation& op) noexcept;
578
579#ifdef JOIN_HAS_IO_URING
586 template <size_t Count, size_t... Sizes, size_t... Is>
587 int registerFixedBuffers (LocalMem::SlabAllocator<Count, Sizes...>& arena, std::index_sequence<Is...>) noexcept;
588
593 io_uring_sqe* getSqe () noexcept;
594
600 void prepareSqe (io_uring_sqe* sqe, IoOperation& op) noexcept;
601
606 void dispatchCqe (io_uring_cqe* cqe) noexcept;
607
611 void eventLoop () noexcept;
612
616 void eventLoop (std::false_type, std::false_type) noexcept;
617
621 void eventLoop (std::true_type, std::false_type) noexcept;
622
626 void eventLoop (std::true_type, std::true_type) noexcept;
627#else
633 void onEvent (int fd, uint32_t revents) noexcept override;
634
642 void drainQueue (IoOperation& tail, int result, uint32_t revents, bool cancelled) noexcept;
643
650 void processQueue (int fd, bool write, uint32_t revents) noexcept;
651
657 void processOperation (IoOperation& op, uint32_t revents) noexcept;
658
665 static int executeOperation (IoOperation& op, uint32_t revents) noexcept;
666
672 bool unqueueOperation (IoOperation& op) noexcept;
673
679 static bool isWriteOperation (const IoOperation& op) noexcept;
680#endif
681
682#ifdef JOIN_HAS_IO_URING
684 Wheel _wheel{*this};
685#endif
686
689
691#ifdef JOIN_HAS_IO_URING
692 alignas (64) std::atomic<WakeupState> _wakeupState{WakeupState::Spinning};
693#else
694 alignas (64) std::atomic<WakeupState> _wakeupState{WakeupState::Sleeping};
695#endif
696
698 int _wakeup = -1;
699
700#ifdef JOIN_HAS_IO_URING
702 alignas (64) uint64_t _wakeupBuf = 0;
703
705 IoOperation _wakeupOp = {};
706
708 io_uring _ring = {};
709
711 std::vector<IoOperation*> _pendingOps;
712
714 std::atomic<pid_t> _threadId{Thread::invalidId};
715
717 std::atomic<bool> _running{false};
718#else
720 std::vector<IoOperation*> _readOps;
721
723 std::vector<IoOperation*> _writeOps;
724
726 Reactor _reactor;
727#endif
728
730 std::unordered_map<uint16_t, IoRingBuffer> _bufferRings;
731};
732
733// =========================================================================
734// CLASS : BasicProactor
735// METHOD : submit
736// =========================================================================
737#ifdef JOIN_HAS_IO_URING
738template <typename IoPolicy>
739int join::BasicProactor<IoPolicy>::submit (IoOperation& op, bool flush, bool sync) noexcept
740#else
741inline int join::BasicProactor::submit (IoOperation& op, bool flush, bool sync) noexcept
742#endif
743{
744 if (isProactorThread ())
745 {
746 return submitOperation (op, flush);
747 }
748
749 std::atomic<bool> done{false}, *pdone = nullptr;
750 std::error_code errc, *perrc = nullptr;
751
752 if (JOIN_UNLIKELY (sync))
753 {
754 pdone = &done;
755 perrc = &errc;
756 }
757
758 if (JOIN_UNLIKELY (writeCommand ({CommandType::Submit, &op, flush, pdone, perrc, nullptr}) == -1))
759 {
760 return -1; // LCOV_EXCL_LINE
761 }
762
763 if (JOIN_UNLIKELY (sync))
764 {
765 Backoff backoff;
766 while (!done.load (std::memory_order_acquire))
767 {
768 backoff ();
769 }
770
771 if (JOIN_UNLIKELY (errc))
772 {
773 lastError = errc;
774 return -1;
775 }
776 }
777
778 return 0;
779}
780
781// =========================================================================
782// CLASS : BasicProactor
783// METHOD : cancel
784// =========================================================================
785#ifdef JOIN_HAS_IO_URING
786template <typename IoPolicy>
787int join::BasicProactor<IoPolicy>::cancel (IoOperation& op, bool flush, bool sync) noexcept
788#else
789inline int join::BasicProactor::cancel (IoOperation& op, bool flush, bool sync) noexcept
790#endif
791{
792 if (isProactorThread ())
793 {
794 return cancelOperation (op, flush);
795 }
796
797 std::atomic<bool> done{false}, *pdone = nullptr;
798 std::error_code errc, *perrc = nullptr;
799
800 if (JOIN_UNLIKELY (sync))
801 {
802 pdone = &done;
803 perrc = &errc;
804 }
805
806 if (JOIN_UNLIKELY (writeCommand ({CommandType::Cancel, &op, flush, pdone, perrc, nullptr}) == -1))
807 {
808 return -1; // LCOV_EXCL_LINE
809 }
810
811 if (JOIN_UNLIKELY (sync))
812 {
813 Backoff backoff;
814 while (!done.load (std::memory_order_acquire))
815 {
816 backoff ();
817 }
818
819 if (JOIN_UNLIKELY (errc))
820 {
821 lastError = errc;
822 return -1;
823 }
824 }
825
826 return 0;
827}
828
829// =========================================================================
830// CLASS : BasicProactor
831// METHOD : invoke
832// =========================================================================
833#ifdef JOIN_HAS_IO_URING
834template <typename IoPolicy>
835int join::BasicProactor<IoPolicy>::invoke (InvokeHandler* fn, bool sync) noexcept
836#else
837inline int join::BasicProactor::invoke (InvokeHandler* fn, bool sync) noexcept
838#endif
839{
840 if (isProactorThread ())
841 {
842 return invokeFunction (fn);
843 }
844
845 std::atomic<bool> done{false}, *pdone = nullptr;
846 std::error_code errc, *perrc = nullptr;
847
848 if (JOIN_LIKELY (sync))
849 {
850 pdone = &done;
851 perrc = &errc;
852 }
853
854 if (JOIN_UNLIKELY (writeCommand ({CommandType::Invoke, nullptr, false, pdone, perrc, fn}) == -1))
855 {
856 return -1; // LCOV_EXCL_LINE
857 }
858
859 if (JOIN_LIKELY (sync))
860 {
861 Backoff backoff;
862 while (!done.load (std::memory_order_acquire))
863 {
864 backoff ();
865 }
866
867 if (JOIN_UNLIKELY (errc))
868 {
869 lastError = errc;
870 return -1;
871 }
872 }
873
874 return 0;
875}
876
877// =========================================================================
878// CLASS : BasicProactor
879// METHOD : suspend
880// =========================================================================
881#ifdef JOIN_HAS_IO_URING
882template <typename IoPolicy>
884#else
886#endif
887{
888 Backoff backoff;
889 for (;;)
890 {
891 IoOperation::State expected = op.state.load (std::memory_order_acquire);
892 if ((expected == IoOperation::State::Idle) || (expected == IoOperation::State::Submitted))
893 {
894 if (op.state.compare_exchange_strong (expected, IoOperation::State::Suspended, std::memory_order_acquire,
895 std::memory_order_relaxed))
896 {
897 op.resume = expected;
898 return;
899 }
900 }
901 else if ((expected == IoOperation::State::Busy) && isProactorThread ())
902 {
903 return;
904 }
905
906 backoff ();
907 }
908}
909
910// =========================================================================
911// CLASS : BasicProactor
912// METHOD : resume
913// =========================================================================
914#ifdef JOIN_HAS_IO_URING
915template <typename IoPolicy>
917#else
919#endif
920{
921 op.handler = &handler;
922 IoOperation::State expected = IoOperation::State::Suspended;
923 op.state.compare_exchange_strong (expected, op.resume, std::memory_order_release, std::memory_order_relaxed);
924}
925
926// =========================================================================
927// CLASS : BasicProactor
928// METHOD : invokeFunction
929// =========================================================================
930#ifdef JOIN_HAS_IO_URING
931template <typename IoPolicy>
932int join::BasicProactor<IoPolicy>::invokeFunction (InvokeHandler* fn) noexcept
933#else
934inline int join::BasicProactor::invokeFunction (InvokeHandler* fn) noexcept
935#endif
936{
937 if (JOIN_UNLIKELY ((fn == nullptr) || !*fn))
938 {
939 lastError = make_error_code (Errc::InvalidParam);
940 return -1;
941 }
942
943 (*fn) ();
944
945 return 0;
946}
947
948// =========================================================================
949// CLASS : BasicProactor
950// METHOD : notifyOperation
951// =========================================================================
952#ifdef JOIN_HAS_IO_URING
953template <typename IoPolicy>
954void join::BasicProactor<IoPolicy>::notifyOperation (IoOperation& op, int result, bool cancelled) noexcept
955#else
956inline void join::BasicProactor::notifyOperation (IoOperation& op, int result, bool cancelled) noexcept
957#endif
958{
959 if (JOIN_LIKELY (op.handler))
960 {
961 if (cancelled)
962 {
963 op.handler->onCancel (op, result);
964 }
965 else
966 {
967 op.handler->onComplete (op, result);
968 }
969 }
970}
971
972// =========================================================================
973// CLASS : BasicProactor
974// METHOD : dispatchOperation
975// =========================================================================
976#ifdef JOIN_HAS_IO_URING
977template <typename IoPolicy>
978void join::BasicProactor<IoPolicy>::dispatchOperation (IoOperation& op, int result, bool cancelled) noexcept
979#else
980inline void join::BasicProactor::dispatchOperation (IoOperation& op, int result, bool cancelled) noexcept
981#endif
982{
983 Backoff backoff;
984 for (;;)
985 {
986 IoOperation::State expected = op.state.load (std::memory_order_relaxed);
987 if (expected != IoOperation::State::Suspended)
988 {
989 if (op.state.compare_exchange_strong (expected, IoOperation::State::Busy, std::memory_order_acquire,
990 std::memory_order_relaxed))
991 {
992 break;
993 }
994 }
995 backoff (); // LCOV_EXCL_LINE
996 }
997
998 if (op.ring != nullptr)
999 {
1000 op.ring->unbind ();
1001 op.ring = nullptr;
1002 }
1003
1004 op.more = false;
1005
1006 notifyOperation (op, result, cancelled);
1007}
1008
1009// =========================================================================
1010// CLASS : BasicProactor
1011// METHOD : resetOperation
1012// =========================================================================
1013#ifdef JOIN_HAS_IO_URING
1014template <typename IoPolicy>
1015void join::BasicProactor<IoPolicy>::resetOperation (IoOperation& op) noexcept
1016#else
1017inline void join::BasicProactor::resetOperation (IoOperation& op) noexcept
1018#endif
1019{
1020 IoOperation::State expected = IoOperation::State::Submitted;
1021 if (!op.state.compare_exchange_strong (expected, IoOperation::State::Idle, std::memory_order_release,
1022 std::memory_order_relaxed) &&
1023 (expected != IoOperation::State::Busy)) // LCOV_EXCL_LINE
1024 {
1025 op.resume = IoOperation::State::Idle; // LCOV_EXCL_LINE
1026 }
1027}
1028
1029#ifdef JOIN_HAS_IO_URING
1030#include "proactor_uring_impl.hpp"
1031#else
1032#include "proactor_epoll_impl.hpp"
1033#endif
1034
1038#ifdef JOIN_HAS_IO_URING
1039template <typename IoPolicy = join::IoDefaultPolicy>
1041#else
1043#endif
1044{
1045public:
1050#ifdef JOIN_HAS_IO_URING
1052#else
1054#endif
1055 {
1056 return instance ()._proactor;
1057 }
1058
1064 static int affinity (int core)
1065 {
1066 return instance ()._dispatcher.affinity (core);
1067 }
1068
1073 static int affinity () noexcept
1074 {
1075 return instance ()._dispatcher.affinity ();
1076 }
1077
1083 static int priority (int prio)
1084 {
1085 return instance ()._dispatcher.priority (prio);
1086 }
1087
1092 static int priority () noexcept
1093 {
1094 return instance ()._dispatcher.priority ();
1095 }
1096
1101 static pthread_t handle () noexcept
1102 {
1103 return instance ()._dispatcher.handle ();
1104 }
1105
1106#ifdef JOIN_HAS_NUMA
1112 static int mbind (int numa) noexcept
1113 {
1114 return instance ()._proactor.mbind (numa);
1115 }
1116#endif
1117
1122 static int mlock () noexcept
1123 {
1124 return instance ()._proactor.mlock ();
1125 }
1126
1127private:
1132 static BasicProactorThread& instance ()
1133 {
1134 static BasicProactorThread proactorThread;
1135 return proactorThread;
1136 }
1137
1141 BasicProactorThread ()
1142 {
1143 _dispatcher = Thread ([this] () {
1144 _proactor.run ();
1145 });
1146
1147 Backoff backoff;
1148 while (!_proactor.isRunning ())
1149 {
1150 backoff ();
1151 }
1152 }
1153
1158 BasicProactorThread (const BasicProactorThread&) = delete;
1159
1165 BasicProactorThread& operator= (const BasicProactorThread&) = delete;
1166
1171 BasicProactorThread (BasicProactorThread&&) = delete;
1172
1178 BasicProactorThread& operator= (BasicProactorThread&&) = delete;
1179
1183 ~BasicProactorThread ()
1184 {
1185 _proactor.stop ();
1186 _dispatcher.join ();
1187 }
1188
1189#ifdef JOIN_HAS_IO_URING
1191 BasicProactor<IoPolicy> _proactor;
1192#else
1194 BasicProactor _proactor;
1195#endif
1196
1198 Thread _dispatcher;
1199};
1200
1201#endif
adaptive backoff for busy-wait loops, requires Rdtsc::calibrate ().
Definition backoff.hpp:47
Convenience class that owns a Proactor running on a dedicated background thread.
Definition proactor.hpp:1044
static int affinity() noexcept
get proactor thread affinity.
Definition proactor.hpp:1073
static int priority(int prio)
set proactor thread scheduling priority.
Definition proactor.hpp:1083
static int mlock() noexcept
lock proactor command queue and timer wheel memory in RAM.
Definition proactor.hpp:1122
static int affinity(int core)
set proactor thread affinity.
Definition proactor.hpp:1064
static pthread_t handle() noexcept
get the native handle of the proactor thread.
Definition proactor.hpp:1101
static BasicProactor & proactor()
get the Proactor instance owned by the singleton ProactorThread.
Definition proactor.hpp:1053
static int priority() noexcept
get proactor thread scheduling priority.
Definition proactor.hpp:1092
basic proactor class.
Definition proactor.hpp:158
int mlock() const noexcept
lock proactor command queue and timer wheel memory in RAM.
Definition proactor_epoll_impl.hpp:288
int unregisterBufferRing(uint16_t group)
unregister a provided buffer ring.
Definition proactor_epoll_impl.hpp:213
bool isRunning() const noexcept
check if the event loop is running.
Definition proactor_epoll_impl.hpp:302
void run()
run the event loop (blocking).
Definition proactor_epoll_impl.hpp:61
BasicProactor(const BasicProactor &other)=delete
copy constructor.
BasicProactor(BasicProactor &&other)=delete
move constructor.
~BasicProactor() noexcept
destroy instance.
Definition proactor_epoll_impl.hpp:50
int invoke(InvokeHandler *fn, bool sync=true) noexcept
invoke a function from the proactor thread.
Definition proactor.hpp:837
int registerBufferRing(uint16_t group, LocalMem::SlabAllocator< Count, Size > &arena)
register a provided buffer ring.
Definition proactor_epoll_impl.hpp:107
Wheel & wheel() noexcept
get the timer wheel advanced by the event loop.
Definition proactor_epoll_impl.hpp:320
BasicProactor & operator=(const BasicProactor &other)=delete
copy assignment operator.
Function< void(), 64 > InvokeHandler
function invoked on the proactor thread.
Definition proactor.hpp:269
void stop(bool sync=true) noexcept
stop the event loop, ignored if no event loop is running.
Definition proactor_epoll_impl.hpp:71
int submit(IoOperation &op, bool flush=false, bool sync=false) noexcept
submit an asynchronous operation to the proactor.
Definition proactor.hpp:741
void resume(IoOperation &op, CompletionHandler &handler) noexcept
resume an I/O operation.
Definition proactor.hpp:918
bool isProactorThread() const noexcept
check if the calling thread is the proactor thread.
Definition proactor_epoll_impl.hpp:311
void waitStopped() const noexcept
wait for the event loop thread to terminate.
Definition proactor_epoll_impl.hpp:97
void suspend(IoOperation &op) noexcept
suspend an I/O operation.
Definition proactor.hpp:885
int cancel(IoOperation &op, bool flush=false, bool sync=false) noexcept
cancel an in-flight operation.
Definition proactor.hpp:789
BasicProactor()
initialize the proactor and its I/O backend.
Definition proactor_epoll_impl.hpp:32
slab allocator owning a backend and managing one or more pools.
Definition slab_allocator.hpp:339
timing wheel.
Definition wheel.hpp:58
completion handler interface class.
Definition proactor.hpp:81
virtual void onComplete(IoOperation &op, int result)
method called when an operation completes successfully.
Definition proactor.hpp:133
CompletionHandler()=default
create instance.
virtual ~CompletionHandler()=default
destroy instance.
CompletionHandler(CompletionHandler &&other)=default
move constructor.
CompletionHandler & operator=(const CompletionHandler &other)=default
copy assignment operator.
CompletionHandler(const CompletionHandler &other)=default
copy constructor.
virtual void onCancel(IoOperation &op, int result)
method called when an operation is cancelled.
Definition proactor.hpp:143
Event handler interface class.
Definition reactor.hpp:51
friend class Reactor
friendship with reactor.
Definition reactor.hpp:152
fixed-capacity move-only allocation-free alternative to std::function.
Definition function.hpp:44
BasicSlabAllocator< LocalMem, Count, Sizes... > SlabAllocator
Definition memory.hpp:327
BasicWheel< Monotonic, WheelPolicy, _queueSize, 1 '000 > Wheel
timer wheel, able to arm a timer for every queued command.
Definition reactor.hpp:276
void join() noexcept
block the current thread until the running thread finishes its execution.
Definition thread.cpp:292
static constexpr pid_t invalidId
invalid thread id.
Definition thread.hpp:183
int affinity(int core)
set thread affinity.
Definition thread.cpp:148
int priority(int prio)
set thread priority.
Definition thread.cpp:211
pthread_t handle() const noexcept
get the handle of the thread of execution.
Definition thread.cpp:350
Monotonic::Wheel< 64 > Wheel
Definition monotonic_wheel_test.cpp:41
Definition acceptor.hpp:32
BasicProactorThread ProactorThread
Definition proactor.hpp:73
constexpr uint64_t sleep_ns_v
Definition io_policy.hpp:100
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
constexpr uint64_t tick_ns_v
Definition io_policy.hpp:110
BasicProactor Proactor
Definition proactor.hpp:72
Definition error.hpp:144
Describes a single asynchronous operation submitted to the Proactor.
Definition io_operation.hpp:48
State
operation lifecycle state.
Definition io_operation.hpp:53
BasicQueue< Type, Backend, SyncPolicy< Type, Backend > > Queue
queue type alias combining backend and policy.
Definition queue.hpp:1040
#define JOIN_LIKELY(x)
Definition utils.hpp:50
#define JOIN_UNLIKELY(x)
Definition utils.hpp:51