47 pthread_mutex_lock(&
pool->stats_lock);
48 pool->stats.active_threads++;
49 pthread_mutex_unlock(&
pool->stats_lock);
64 pthread_mutex_lock(&
pool->stats_lock);
65 pool->stats.total_accepted++;
66 pthread_mutex_unlock(&
pool->stats_lock);
68 pool->callback(accepted,
pool->user_data);
70 if (retval == EINTR) {
74 if (retval == EAGAIN || retval == EWOULDBLOCK || retval == 0) {
76 pthread_mutex_lock(&
pool->stats_lock);
77 pool->stats.total_timeouts++;
78 pthread_mutex_unlock(&
pool->stats_lock);
80 if (
pool->accept_timeout == -1) {
85 pthread_mutex_lock(&
pool->stats_lock);
86 pool->stats.total_errors++;
87 pthread_mutex_unlock(&
pool->stats_lock);
88 n_log(
LOG_ERR,
"accept pool thread: accept error, retval=%d", retval);
93 pthread_mutex_lock(&
pool->stats_lock);
94 if (
pool->stats.active_threads > 0) {
95 pool->stats.active_threads--;
97 pthread_mutex_unlock(&
pool->stats_lock);
115 if (nb_threads == 0) {
116 n_log(
LOG_ERR,
"netw_accept_pool_create: nb_threads must be > 0");
125 pool->nb_accept_threads = nb_threads;
126 pool->accept_timeout = accept_timeout;
127 pool->callback = callback;
128 pool->user_data = user_data;
134 if (pthread_mutex_init(&
pool->stats_lock, NULL) != 0) {
135 n_log(
LOG_ERR,
"netw_accept_pool_create: failed to init stats mutex");
140 Malloc(
pool->accept_threads, pthread_t, nb_threads);
141 if (!
pool->accept_threads) {
142 n_log(
LOG_ERR,
"netw_accept_pool_create: failed to allocate thread array");
143 pthread_mutex_destroy(&
pool->stats_lock);
161 n_log(
LOG_ERR,
"netw_accept_pool_start: pool is not idle or stopped (state=%u)", current);
166 pthread_mutex_lock(&
pool->stats_lock);
168 clock_gettime(CLOCK_MONOTONIC, &
pool->stats.start_time);
169 pthread_mutex_unlock(&
pool->stats_lock);
173 for (
size_t i = 0; i <
pool->nb_accept_threads; i++) {
176 n_log(
LOG_ERR,
"netw_accept_pool_start: failed to create thread %zu: %s", i, strerror(err));
179 for (
size_t j = 0; j < i; j++) {
180 pthread_join(
pool->accept_threads[j], NULL);
201 n_log(
LOG_WARNING,
"netw_accept_pool_stop: pool is not running (state=%u)", current);
209 if (
pool->server &&
pool->server->link.sock != INVALID_SOCKET) {
210 shutdown(
pool->server->link.sock, SHUT_RDWR);
231 n_log(
LOG_WARNING,
"netw_accept_pool_wait: pool still running, calling stop first");
236 for (
size_t i = 0; i <
pool->nb_accept_threads; i++) {
237 pthread_join(
pool->accept_threads[i], NULL);
256 pthread_mutex_lock(&
pool->stats_lock);
258 pthread_mutex_unlock(&
pool->stats_lock);
274 n_log(
LOG_WARNING,
"netw_accept_pool_destroy: pool still active, stopping and waiting");
279 pthread_mutex_destroy(&(*pool)->stats_lock);
280 Free((*pool)->accept_threads);
static NETWORK_POOL * pool
#define NETW_ACCEPT_POOL_RUNNING
accept pool state: running and accepting connections
void(* netw_accept_callback_t)(NETWORK *accepted, void *user_data)
callback type for accepted connections.
#define NETW_ACCEPT_POOL_IDLE
accept pool state: idle, not yet started
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_get_stats(NETW_ACCEPT_POOL *pool, NETW_ACCEPT_POOL_STATS *stats)
Get a snapshot of pool statistics.
int netw_accept_pool_wait(NETW_ACCEPT_POOL *pool, int timeout_sec)
Wait for all accept threads to finish after a stop request.
#define netw_accept_pool_atomic_read_state(pool)
Lock-free atomic read of the accept pool state.
int netw_accept_pool_destroy(NETW_ACCEPT_POOL **pool)
Destroy an accept pool.
int netw_accept_pool_stop(NETW_ACCEPT_POOL *pool)
Request the accept pool to stop.
int netw_accept_pool_start(NETW_ACCEPT_POOL *pool)
Start the accept pool (launches accept threads)
#define netw_accept_pool_atomic_write_state(pool, val)
Lock-free atomic write of the accept pool state.
#define NETW_ACCEPT_POOL_STOPPING
accept pool state: stop requested
#define NETW_ACCEPT_POOL_STOPPED
accept pool state: fully stopped
Structure of a parallel accept pool.
Statistics for the accept pool.
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
#define __n_assert(__ptr, __ret)
macro to assert things
#define Free(__ptr)
Free Handler to get errors.
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_ERR
error conditions
#define LOG_NOTICE
normal but significant condition
#define LOG_WARNING
warning conditions
void u_sleep(unsigned int usec)
wrapper around usleep for API consistency
NETWORK * netw_accept_from_ex(NETWORK *from, size_t send_list_limit, size_t recv_list_limit, int blocking, int *retval)
make a normal 'accept' .
int netw_close(NETWORK **netw)
Closing a specified Network, destroy queues, free the structure.
static void * netw_accept_pool_thread_func(void *arg)
Thread function for accept pool workers.
Accept pool for parallel connection acceptance (nginx-style)