![]() |
Nilorea Library
C utilities for networking, threading, graphics
|
Data Structures | |
| struct | NETW_ACCEPT_POOL |
| Structure of a parallel accept pool. More... | |
| struct | NETW_ACCEPT_POOL_STATS |
| Statistics for the accept pool. More... | |
Macros | |
| #define | netw_accept_pool_atomic_read_state(pool) __atomic_load_n(&(pool)->state, __ATOMIC_ACQUIRE) |
| Lock-free atomic read of the accept pool state. | |
| #define | netw_accept_pool_atomic_write_state(pool, val) __atomic_store_n(&(pool)->state, (val), __ATOMIC_RELEASE) |
| Lock-free atomic write of the accept pool state. | |
| #define | NETW_ACCEPT_POOL_IDLE 0 |
| accept pool state: idle, not yet started | |
| #define | NETW_ACCEPT_POOL_RUNNING 1 |
| accept pool state: running and accepting connections | |
| #define | NETW_ACCEPT_POOL_STOPPED 3 |
| accept pool state: fully stopped | |
| #define | NETW_ACCEPT_POOL_STOPPING 2 |
| accept pool state: stop requested | |
Typedefs | |
| typedef void(* | netw_accept_callback_t) (NETWORK *accepted, void *user_data) |
| callback type for accepted connections. | |
Functions | |
| NETW_ACCEPT_POOL * | netw_accept_pool_create (NETWORK *server, size_t nb_threads, int accept_timeout, netw_accept_callback_t callback, void *user_data) |
| Create a new accept pool. | |
| int | netw_accept_pool_destroy (NETW_ACCEPT_POOL **pool) |
| Destroy an accept pool. | |
| int | netw_accept_pool_get_stats (NETW_ACCEPT_POOL *pool, NETW_ACCEPT_POOL_STATS *stats) |
| Get a snapshot of pool statistics (thread-safe copy) | |
| int | netw_accept_pool_start (NETW_ACCEPT_POOL *pool) |
| Start the accept pool (launches accept threads) | |
| int | netw_accept_pool_stop (NETW_ACCEPT_POOL *pool) |
| Request the accept pool to stop. | |
| int | netw_accept_pool_wait (NETW_ACCEPT_POOL *pool, int timeout_sec) |
| Wait for all accept threads to finish after a stop request. | |
The accept pool provides nginx-style parallel connection acceptance: multiple threads call accept() on the same listening socket, each invoking a user callback for every accepted connection.
There are three common ways to structure a server's accept + handling logic. Each has different performance characteristics depending on the workload:
One thread does accept() and handles the client inline before accepting the next connection. Both accept and handling are fully serialized.
One thread calls accept() and dispatches each connection to a worker thread pool for handling. Accept is serialized but handling is parallelized.
Multiple threads call accept() on the same listening socket (nginx-style), each dispatching to a worker thread pool. Both accept and handling are parallelized.
On localhost (loopback), accept() is near-instant (nanoseconds). A single accept thread can drain the kernel queue faster than clients can fill it. Adding more accept threads introduces kernel socket lock contention and context switches without benefit — single-pool will often outperform pooled mode in this case.
The pooled accept advantage appears when:
The example programs (ex_accept_pool_server, ex_accept_pool_client, test_accept_pool.sh) demonstrate all three modes with configurable parameters for benchmarking.
| struct NETW_ACCEPT_POOL |
Structure of a parallel accept pool.
Definition at line 135 of file n_network_accept_pool.h.
Collaboration diagram for NETW_ACCEPT_POOL:| Data Fields | ||
|---|---|---|
| pthread_t * | accept_threads | array of pthread ids |
| int | accept_timeout |
accept timeout in milliseconds (passed to netw_accept_from_ex blocking param). 0 = blocking, -1 = non-blocking, >0 = timeout in msec |
| netw_accept_callback_t | callback | user callback invoked on each accepted connection |
| size_t | nb_accept_threads | number of accept threads |
| NETWORK * | server | listening socket (not owned, caller must keep alive) |
| uint32_t | state | atomic pool state |
| NETW_ACCEPT_POOL_STATS | stats | pool statistics |
| pthread_mutex_t | stats_lock | mutex protecting stats |
| void * | user_data | opaque user data passed to callback |
| struct NETW_ACCEPT_POOL_STATS |
Statistics for the accept pool.
Definition at line 121 of file n_network_accept_pool.h.
Collaboration diagram for NETW_ACCEPT_POOL_STATS:| #define netw_accept_pool_atomic_read_state | ( | pool | ) | __atomic_load_n(&(pool)->state, __ATOMIC_ACQUIRE) |
Lock-free atomic read of the accept pool state.
Definition at line 158 of file n_network_accept_pool.h.
| #define netw_accept_pool_atomic_write_state | ( | pool, | |
| val | |||
| ) | __atomic_store_n(&(pool)->state, (val), __ATOMIC_RELEASE) |
Lock-free atomic write of the accept pool state.
Definition at line 161 of file n_network_accept_pool.h.
| #define NETW_ACCEPT_POOL_IDLE 0 |
accept pool state: idle, not yet started
Definition at line 106 of file n_network_accept_pool.h.
| #define NETW_ACCEPT_POOL_RUNNING 1 |
accept pool state: running and accepting connections
Definition at line 108 of file n_network_accept_pool.h.
| #define NETW_ACCEPT_POOL_STOPPED 3 |
accept pool state: fully stopped
Definition at line 112 of file n_network_accept_pool.h.
| #define NETW_ACCEPT_POOL_STOPPING 2 |
accept pool state: stop requested
Definition at line 110 of file n_network_accept_pool.h.
| typedef void(* netw_accept_callback_t) (NETWORK *accepted, void *user_data) |
callback type for accepted connections.
| accepted | the newly accepted NETWORK connection (caller takes ownership) |
| user_data | opaque pointer passed at pool creation |
Definition at line 118 of file n_network_accept_pool.h.
| NETW_ACCEPT_POOL * netw_accept_pool_create | ( | NETWORK * | server, |
| size_t | nb_threads, | ||
| int | accept_timeout, | ||
| netw_accept_callback_t | callback, | ||
| void * | user_data | ||
| ) |
Create a new accept pool.
| server | listening NETWORK (must already be listening) |
| nb_threads | number of accept threads |
| accept_timeout | timeout in msec for accept (0=blocking, -1=nonblocking, >0=timeout ms) |
| callback | function called for each accepted connection |
| user_data | opaque pointer passed to callback |
Definition at line 110 of file n_network_accept_pool.c.
References __n_assert, Free, LOG_ERR, Malloc, n_log, netw_accept_pool_atomic_write_state, NETW_ACCEPT_POOL_IDLE, pool, and server.
Referenced by main().
Here is the caller graph for this function:| int netw_accept_pool_destroy | ( | NETW_ACCEPT_POOL ** | pool | ) |
Destroy an accept pool.
Pool must be stopped first.
Pool must be stopped first.
| pool | pointer to the accept pool pointer (set to NULL) |
Definition at line 267 of file n_network_accept_pool.c.
References __n_assert, Free, LOG_WARNING, n_log, netw_accept_pool_atomic_read_state, NETW_ACCEPT_POOL_RUNNING, netw_accept_pool_stop(), NETW_ACCEPT_POOL_STOPPING, netw_accept_pool_wait(), and pool.
Referenced by main().
Here is the call graph for this function:
Here is the caller graph for this function:| int netw_accept_pool_get_stats | ( | NETW_ACCEPT_POOL * | pool, |
| NETW_ACCEPT_POOL_STATS * | stats | ||
| ) |
Get a snapshot of pool statistics (thread-safe copy)
Get a snapshot of pool statistics (thread-safe copy)
| pool | the accept pool |
| stats | output structure to fill |
Definition at line 251 of file n_network_accept_pool.c.
References __n_assert, and pool.
Referenced by main().
Here is the caller graph for this function:| int netw_accept_pool_start | ( | NETW_ACCEPT_POOL * | pool | ) |
Start the accept pool (launches accept threads)
| pool | the accept pool to start |
Definition at line 155 of file n_network_accept_pool.c.
References __n_assert, LOG_ERR, LOG_NOTICE, n_log, netw_accept_pool_atomic_read_state, netw_accept_pool_atomic_write_state, NETW_ACCEPT_POOL_IDLE, NETW_ACCEPT_POOL_RUNNING, NETW_ACCEPT_POOL_STOPPED, NETW_ACCEPT_POOL_STOPPING, netw_accept_pool_thread_func(), and pool.
Referenced by main().
Here is the call graph for this function:
Here is the caller graph for this function:| int netw_accept_pool_stop | ( | NETW_ACCEPT_POOL * | pool | ) |
Request the accept pool to stop.
Non-blocking, threads will finish current accept and exit.
| pool | the accept pool to stop |
Definition at line 195 of file n_network_accept_pool.c.
References __n_assert, LOG_NOTICE, LOG_WARNING, n_log, netw_accept_pool_atomic_read_state, netw_accept_pool_atomic_write_state, NETW_ACCEPT_POOL_RUNNING, NETW_ACCEPT_POOL_STOPPING, and pool.
Referenced by main(), netw_accept_pool_destroy(), and netw_accept_pool_wait().
Here is the caller graph for this function:| int netw_accept_pool_wait | ( | NETW_ACCEPT_POOL * | pool, |
| int | timeout_sec | ||
| ) |
Wait for all accept threads to finish after a stop request.
| pool | the accept pool to wait on |
| timeout_sec | maximum seconds to wait (0 = wait forever) |
Definition at line 221 of file n_network_accept_pool.c.
References __n_assert, LOG_NOTICE, LOG_WARNING, n_log, netw_accept_pool_atomic_read_state, netw_accept_pool_atomic_write_state, NETW_ACCEPT_POOL_IDLE, NETW_ACCEPT_POOL_RUNNING, netw_accept_pool_stop(), NETW_ACCEPT_POOL_STOPPED, and pool.
Referenced by main(), and netw_accept_pool_destroy().
Here is the call graph for this function:
Here is the caller graph for this function: