CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
queue_select.cxh
1#include <cx/net/queue.cxh>
2
3// Portable readiness backend built on select().
4//
5// One shared class serves every platform. The differences between Windows and Unix select --
6// SOCKET vs int, WSAGetLastError vs errno, the fd_set representation, the wake mechanism -- are
7// all syscall-shim differences that live in the platform socket layer (netLastError(), the
8// netSock* shims) and the NetSelectSet primitive, not in the queue. What is shared is the part
9// that matters: the readiness-to-completion emulation, which is where the bugs would be, so it is
10// written exactly once.
11//
12// Correct everywhere including Wine, FD_SETSIZE-limited, and the reference the completion backends
13// are validated against. In polled mode it runs its loop inside tick() on the caller's thread; in
14// threaded mode a dedicated ingest thread runs the select() loop and feeds the base class's pool of
15// dispatch workers, which is the only genuinely select-specific piece of the threading model.
16
17class NetQueueSelect extends NetQueue
18{
19 // NetSelectSet* (opaque), created and destroyed by hand
20 //
21 // Held as void* so the private NetSelectSet declaration does not have to leak into this
22 // generated header. Cast back in the implementation.
23 void *selset;
24
25 // Handle -> socket for the current tick, each entry holding a strong reference
26 //
27 // Rebuilt every tick under the socket lock. Holding a reference means a socket removed by
28 // another thread mid-tick stays alive until the map is cleared at the top of the next tick,
29 // so ingest never touches freed memory. The object value type manages the references.
30 hashtable[uint64,object] fdmap;
31
32 // Dedicated select-loop thread in threaded mode (NULL in polled mode)
33 //
34 // select() cannot usefully be shared across threads -- one fd_set, one wait -- so threaded
35 // mode runs exactly one ingest thread here that fills the runqueue, plus the base class's N
36 // dispatch workers that drain it. In polled mode this stays NULL and tick() runs the loop on
37 // the caller's thread. Joined (via nselWake + thrWait) before it is released, in shutdown or as
38 // a destroy-time safety net.
39 object[Thread] ingest;
40
41 factory create(NetQueueConfig *conf);
42
43 // Wake the select loop so it rebuilds its watch set with the new socket.
44 override addSocket;
45
46 // Wake the select loop so it drops the removed socket from its watch set.
47 override removeSocket;
48
49 // Stop the ingest thread before the base tears the queue down.
50 override shutdown;
51
52 destroy();
53}