CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
unix_net_epoll.cxh
1#include <cx/net/queue.cxh>
2#include <cx/platform/unix.h>
3
4// Linux-only completion emulation over epoll, with recvmmsg batching on the datagram ingest path.
5// This is the Unix performance target, the counterpart to IOCP on Windows -- structurally it is
6// NetQueueSelect's readiness-to-completion loop (ingest thread feeds the base class's dispatch
7// pool) with a different wait call and a different, edge-count-free way of tracking which sockets
8// to watch: epoll_ctl mutates the kernel's interest list directly instead of rebuilding a whole set
9// every pass, so addSocket/removeSocket act immediately rather than waking a loop to rebuild.
10class NetQueueEpoll extends NetQueue
11{
12 int epfd; ///< epoll instance, created with epoll_create1()
13
14 /// @brief Handle -> socket, each entry holding a strong reference
15 ///
16 /// Unlike NetQueueSelect's fdmap (rebuilt every tick from q->sockets, and so only ever touched
17 /// by the single thread doing that rebuild), this map is maintained incrementally by
18 /// addSocket/removeSocket alongside the epoll_ctl calls that keep the kernel's interest list in
19 /// sync, since there is no per-pass rebuild step to refresh it from -- which means it can be
20 /// mutated from an application thread (removeSocket, via netsocketClose) at the same time the
21 /// ingest thread is reading it, so every access goes through fdmapLock rather than relying on
22 /// the queue's own socket-table lock.
23 hashtable[uint64,object] fdmap;
24
25 /// @brief Guards fdmap against the ingest thread and an application/worker thread racing on it
26 Mutex fdmapLock;
27
28 /// @brief Dedicated epoll_wait loop thread in threaded mode (NULL in polled mode)
29 ///
30 /// Same split as NetQueueSelect: this thread only ingests, filling the runqueue via
31 /// netqueue_submit; the base class's N dispatch workers drain it. In polled mode this stays
32 /// NULL and tick() runs epoll_wait on the caller's thread.
33 object[Thread] ingest;
34
35 /// @brief Self-pipe read/write ends, used to interrupt a blocked epoll_wait()
36 ///
37 /// Registered on epfd once at creation with EPOLLIN and never removed. addSocket/shutdown write
38 /// a byte to wake a parked ingest thread the same way NetSelectSet's wake pipe does.
39 int wakeRead;
40 int wakeWrite;
41
42 factory create(NetQueueConfig *conf);
43
44 /// epoll_ctl ADD/MOD the new socket immediately; no rebuild to wake for.
45 override addSocket;
46
47 /// epoll_ctl DEL the socket immediately.
48 override removeSocket;
49
50 /// Stop the ingest thread before the base tears the queue down.
51 override shutdown;
52
53 destroy();
54}