join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
reactor.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_REACTOR_HPP
26#define JOIN_CORE_REACTOR_HPP
27
28// libjoin.
29#include <join/function.hpp>
30#include <join/thread.hpp>
31#include <join/queue.hpp>
32#include <join/utils.hpp>
33
34// C++.
35#include <unordered_map>
36#include <unordered_set>
37#include <atomic>
38
39// C.
40#include <sys/epoll.h>
41
42namespace join
43{
48 {
49 public:
53 EventHandler () = default;
54
59 EventHandler (const EventHandler& other) = default;
60
66 EventHandler& operator= (const EventHandler& other) = default;
67
72 EventHandler (EventHandler&& other) = default;
73
80
84 virtual ~EventHandler () = default;
85
86 protected:
92 virtual void onEvent (int fd, uint32_t revents)
93 {
94 if (JOIN_UNLIKELY (revents & EPOLLERR))
95 {
96 onError (fd);
97 }
98 else if (JOIN_UNLIKELY (revents & (EPOLLRDHUP | EPOLLHUP)))
99 {
100 onClose (fd);
101 }
102 else if (JOIN_LIKELY (revents & EPOLLIN))
103 {
104 onReadable (fd);
105 }
106 else if (revents & EPOLLOUT)
107 {
108 onWriteable (fd);
109 }
110 }
111
116 virtual void onReadable ([[maybe_unused]] int fd)
117 {
118 // do nothing.
119 }
120
125 virtual void onWriteable ([[maybe_unused]] int fd)
126 {
127 // do nothing.
128 }
129
134 virtual void onClose ([[maybe_unused]] int fd)
135 {
136 // do nothing.
137 }
138
143 virtual void onError ([[maybe_unused]] int fd)
144 {
145 // do nothing.
146 }
147
149 friend class Reactor;
150 };
151
156 {
157 public:
159 using InvokeHandler = Function<void (), 64>;
160
164 Reactor ();
165
170 Reactor (const Reactor& other) = delete;
171
177 Reactor& operator= (const Reactor& other) = delete;
178
183 Reactor (Reactor&& other) = delete;
184
190 Reactor& operator= (Reactor&& other) = delete;
191
195 ~Reactor () noexcept;
196
206 int addHandler (int fd, EventHandler* handler, bool wantRead = true, bool wantWrite = false,
207 bool sync = true) noexcept;
208
215 int delHandler (int fd, bool sync = true) noexcept;
216
223 int invoke (InvokeHandler* fn, bool sync = true) noexcept;
224
228 void run ();
229
234 void stop (bool sync = true) noexcept;
235
239 void waitStopped () const noexcept;
240
241#ifdef JOIN_HAS_NUMA
247 int mbind (int numa) const noexcept;
248#endif
249
254 int mlock () const noexcept;
255
260 bool isRunning () const noexcept;
261
266 bool isReactorThread () const noexcept;
267
268 private:
270 static constexpr size_t _deletedReserve = 64;
271
273 static constexpr size_t _queueSize = 1024;
274
276 static constexpr size_t _maxEvents = 1024;
277
281 enum class CommandType
282 {
283 Add,
284 Del,
285 Invoke,
286 Stop
287 };
288
292 struct alignas (64) Command
293 {
294 CommandType type;
295 int fd;
296 uint32_t events;
297 EventHandler* handler;
298 std::atomic<bool>* done;
299 std::error_code* errc;
300 InvokeHandler* fn;
301 };
302
310 int registerHandler (int fd, EventHandler* handler, uint32_t events) noexcept;
311
317 int unregisterHandler (int fd) noexcept;
318
324 int invokeFunction (InvokeHandler* fn) noexcept;
325
331 int writeCommand (const Command& cmd) noexcept;
332
337 void processCommand (const Command& cmd) noexcept;
338
342 void readCommands () noexcept;
343
348 void dispatchEvent (const epoll_event& event);
349
353 void eventLoop ();
354
360 bool isActive (int fd) const noexcept;
361
363 int _wakeup = -1;
364
366 int _epoll = -1;
367
369 alignas (64) std::atomic<bool> _notified{false};
370
373
375 std::unordered_map<int, EventHandler*> _handlers;
376
378 std::unordered_set<int> _deleted;
379
381 std::atomic<bool> _running{false};
382
384 static constexpr pthread_t _invalidThreadId = static_cast<pthread_t> (-1);
385
387 std::atomic<pthread_t> _threadId{_invalidThreadId};
388 };
389
394 {
395 public:
400 static Reactor& reactor ();
401
407 static int affinity (int core);
408
413 static int affinity ();
414
420 static int priority (int prio);
421
426 static int priority ();
427
432 static pthread_t handle ();
433
434#ifdef JOIN_HAS_NUMA
440 static int mbind (int numa);
441#endif
442
447 static int mlock ();
448
449 private:
454 static ReactorThread& instance ();
455
459 ReactorThread ();
460
465 ReactorThread (const ReactorThread& other) = delete;
466
472 ReactorThread& operator= (const ReactorThread& other) = delete;
473
478 ReactorThread (ReactorThread&& other) noexcept = delete;
479
485 ReactorThread& operator= (ReactorThread&& other) noexcept = delete;
486
491
493 Reactor _reactor;
494
496 Thread _dispatcher;
497 };
498}
499
500#endif
Event handler interface class.
Definition reactor.hpp:48
EventHandler(const EventHandler &other)=default
copy constructor.
virtual void onClose(int fd)
method called when handle was closed by the peer.
Definition reactor.hpp:134
virtual ~EventHandler()=default
destroy instance.
virtual void onError(int fd)
method called when an error occurred on handle.
Definition reactor.hpp:143
EventHandler()=default
create instance.
virtual void onReadable(int fd)
method called when data are ready to be read on handle.
Definition reactor.hpp:116
virtual void onEvent(int fd, uint32_t revents)
method called when events are reported on handle.
Definition reactor.hpp:92
EventHandler & operator=(const EventHandler &other)=default
copy assignment operator.
EventHandler(EventHandler &&other)=default
move constructor.
virtual void onWriteable(int fd)
method called when data are ready to be written on handle.
Definition reactor.hpp:125
fixed-capacity move-only allocation-free alternative to std::function.
Definition function.hpp:44
Convenience class that owns a Reactor running on a dedicated background thread.
Definition reactor.hpp:394
static int affinity()
get reactor thread affinity.
Definition reactor.cpp:602
static int priority()
get reactor thread priority.
Definition reactor.cpp:620
static pthread_t handle()
get the handle of the reactor thread.
Definition reactor.cpp:629
static Reactor & reactor()
get the global Reactor instance.
Definition reactor.cpp:584
static int mlock()
lock command queue memory in RAM.
Definition reactor.cpp:649
Reactor class.
Definition reactor.hpp:156
bool isRunning() const noexcept
check if the event loop is running.
Definition reactor.cpp:314
Reactor(Reactor &&other)=delete
move constructor.
Reactor()
default constructor.
Definition reactor.cpp:46
Function< void(), 64 > InvokeHandler
function invoked on the reactor thread.
Definition reactor.hpp:159
void waitStopped() const noexcept
wait for the event loop thread to terminate.
Definition reactor.cpp:280
bool isReactorThread() const noexcept
check if the calling thread is the reactor thread.
Definition reactor.cpp:323
int mlock() const noexcept
lock command queue memory in RAM.
Definition reactor.cpp:305
int delHandler(int fd, bool sync=true) noexcept
delete handler from reactor.
Definition reactor.cpp:155
Reactor & operator=(const Reactor &other)=delete
copy assignment operator.
void run()
run the event loop (blocking).
Definition reactor.cpp:241
Reactor(const Reactor &other)=delete
copy constructor.
~Reactor() noexcept
destroy instance.
Definition reactor.cpp:88
void stop(bool sync=true) noexcept
stop the event loop, ignored if no event loop is running.
Definition reactor.cpp:255
int addHandler(int fd, EventHandler *handler, bool wantRead=true, bool wantWrite=false, bool sync=true) noexcept
add handler to reactor.
Definition reactor.cpp:100
int invoke(InvokeHandler *fn, bool sync=true) noexcept
invoke a function from the reactor thread.
Definition reactor.cpp:198
thread class.
Definition thread.hpp:147
Definition acceptor.hpp:32
Definition error.hpp:144
BasicQueue< Type, Backend, SyncPolicy< Type, Backend > > Queue
queue type alias combining backend and policy.
Definition queue.hpp:1054
#define JOIN_LIKELY(x)
Definition utils.hpp:45
#define JOIN_UNLIKELY(x)
Definition utils.hpp:46