|
CX Framework
Cross-platform C utility framework
|
A single ordering domain: one connection, or one datagram peer. More...
#include <flow.h>
Public Member Functions | |
| Weak (NetSocket) *socket | |
| Socket that owns this flow. | |
| atomic (uint32) claimed | |
| A worker is currently draining this flow. | |
| atomic (uint32) queued | |
| Present on the queue's runqueue. | |
| atomic (uint32) dying | |
| atomic (ptr) inbox | |
| Pending messages for this flow, in an intrusive lock-free stack. | |
| atomic (uint32) lastActive | |
| Last time a packet was ingested for this flow, for approximate LRU. | |
| Weak (ObjInst) *handlerWeak | |
| Context passed to per-flow handlers, set by setHandlersObj() – NULL when handlerCtx is in use instead. | |
Data Fields | |
| NetPool * | pool |
| Pool every message on this flow was drawn from, held strongly. | |
| NetAddr | peer |
| uint64 | key |
| QUIC: the stream id this flow is keyed on. Zero on every other kind of flow. | |
| NetMessage * | ready |
| Consumer-private FIFO head, refilled from inbox. | |
| NetMessage * | readytail |
| sa_stvar | user |
| Application state for this peer, allocated lazily. | |
| NetHandlers * | handlers |
| Per-flow handler overrides, optional. | |
| void * | handlerCtx |
| RWLock | handlerLock |
| Guards handlers/handlerCtx/handlerWeak against a concurrent setHandlers()/setHandlersObj() | |
| sa_uint64 | timers |
| Ids of the timers currently armed on this flow, guarded by the queue's timerLock. | |
| sa_NetFlowFilter | filters |
| This flow's filter chain, ordered application -> wire, or empty for none. | |
| BufRing * | encIn |
| Stream: staging ring the encode chain consumes from, allocated with the chain. | |
| NetMsgQueue | encInMsgs |
| Datagram: staging queue the encode chain consumes from, the encIn of the message side. | |
| Mutex | filterLock |
| Serializes filter chain access for this flow. | |
| uint8 | closeReason |
| NetCloseReason once the flow is dying. | |
A single ordering domain: one connection, or one datagram peer.
| NetFlow::atomic | ( | ptr | ) |
Pending messages for this flow, in an intrusive lock-free stack.
Any ingest thread can push; only the worker holding the claim drains it.
| NetFlow::atomic | ( | uint32 | ) |
Marked for close; blocks further dispatch
| NetFlow::atomic | ( | uint32 | ) |
Last time a packet was ingested for this flow, for approximate LRU.
Reclaim scans for the oldest entries rather than keeping an ordered list, since updating a list on every packet would put a lock on the hottest path in the system. Stored as a coarse ~1 second tick rather than a precise timestamp, which keeps it small enough to update as a single atomic write.
| NetFlow::Weak | ( | NetSocket | ) |
Socket that owns this flow.
Weak, to break the socket/flow ownership cycle. Resolve to a strong reference once per dispatch batch, not once per packet.
| BufRing* NetFlow::encIn |
Stream: staging ring the encode chain consumes from, allocated with the chain.
netsocketSend() writes the application payload here and the chain's first stage reads it; whatever a stage declines to consume stays put and resumes on the next pass. NULL when the flow has no filters, and always NULL on a datagram flow, which stages whole messages in encInMsgs instead.
| NetMsgQueue NetFlow::encInMsgs |
Datagram: staging queue the encode chain consumes from, the encIn of the message side.
A stage still negotiating declines to consume application messages, and they wait here until it will take them, exactly as unconsumed bytes wait in a stream flow's encIn. Bounded by NET_FLOW_ENCQ_MAX messages, past which a send is refused rather than buffered without limit.
| Mutex NetFlow::filterLock |
Serializes filter chain access for this flow.
Decode always runs on the worker holding the flow's claim, but encode is driven by whatever thread called netsocketSend(), and both touch the same stage objects and boundary buffers. Held across an entire driver pass – but never across an application callback, which could re-enter through netsocketSend().
| sa_NetFlowFilter NetFlow::filters |
This flow's filter chain, ordered application -> wire, or empty for none.
Never installed by hand: the socket builds it when the flow is created (and when a filter is attached to a socket that already has flows) by walking its own NetFilter list and calling createFlow() on each, so the two run in lockstep. See Filters.
| void* NetFlow::handlerCtx |
| uint64 NetFlow::key |
| NetAddr NetFlow::peer |
| NetPool* NetFlow::pool |
Pool every message on this flow was drawn from, held strongly.
Strong where socket is weak, and for the opposite reason: a flow can still be holding messages – in its inbox, its ready list, or the datagram staging queue – at a moment when neither its socket nor the queue is reachable any more, and a pooled buffer destroyed instead of returned costs the whole queue that much of its ceiling for good. NULL only for a stream flow whose socket has not been added to a queue yet; netqueueAddSocket() fills it in.
| NetMessage* NetFlow::readytail |
| sa_stvar NetFlow::user |