CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
unix_net_kqueue.cxh
1#include <cx/net/queue.cxh>
2#include <cx/platform/unix.h>
3
4// FreeBSD-only completion emulation over kqueue, the counterpart to NetQueueEpoll on Linux and IOCP
5// on Windows. Structurally identical to NetQueueEpoll -- one ingest thread feeds the base class's
6// dispatch pool -- but kevent() registers read and write interest as two independent filters per fd
7// rather than one combined interest struct, and there is no recvmmsg equivalent on FreeBSD, so the
8// datagram ingest path is the same unbatched per-packet loop NetQueueSelect uses.
9class NetQueueKqueue extends NetQueue
10{
11 int kq; ///< kqueue instance, created with kqueue()
12
13 /// @brief Handle -> socket, each entry holding a strong reference
14 ///
15 /// Same role as NetQueueEpoll's fdmap: maintained incrementally by addSocket/removeSocket
16 /// alongside the kevent() calls that keep the kernel's interest list in sync, and consulted at
17 /// dispatch time rather than trusting a kevent's udata directly, so a stale event referencing an
18 /// fd that has since been closed and reused resolves to nothing instead of the wrong socket. Not
19 /// rebuilt wholesale per pass (unlike NetQueueSelect's), so it can be mutated from an application
20 /// thread (removeSocket, via netsocketClose) at the same time the ingest thread is reading it --
21 /// every access goes through fdmapLock rather than relying on the queue's own socket-table lock.
22 hashtable[uint64,object] fdmap;
23
24 /// @brief Guards fdmap against the ingest thread and an application/worker thread racing on it
25 Mutex fdmapLock;
26
27 /// @brief Dedicated kevent-wait loop thread in threaded mode (NULL in polled mode)
28 ///
29 /// Same split as NetQueueEpoll/NetQueueSelect: this thread only ingests, filling the runqueue
30 /// via netqueue_submit; the base class's N dispatch workers drain it. In polled mode this stays
31 /// NULL and tick() runs kevent() on the caller's thread.
32 object[Thread] ingest;
33
34 /// @brief Self-pipe read/write ends, used to interrupt a blocked kevent()
35 ///
36 /// Registered on kq once at creation with EVFILT_READ and never removed. addSocket/shutdown
37 /// write a byte to wake a parked ingest thread the same way NetSelectSet's wake pipe does.
38 int wakeRead;
39 int wakeWrite;
40
41 factory create(NetQueueConfig *conf);
42
43 /// kevent() EV_ADD the new socket's interest immediately; no rebuild to wake for.
44 override addSocket;
45
46 /// kevent() EV_DELETE the socket's interest immediately.
47 override removeSocket;
48
49 /// Stop the ingest thread before the base tears the queue down.
50 override shutdown;
51
52 destroy();
53}