examples/ex_thread_pool_discard.c
destroy_threaded_pool() does not drop queued jobs silently. More...
Functions
| Name | |
|---|---|
| void * | slow_job(void * p) A job that takes 300 ms and releases its own param. |
| int | run(unsigned int delay) Queue four slow jobs on a one thread pool and destroy it. |
| int | main(void ) |
| void | discard_job(void * p) Discard function: releases a param that will never be run. |
Attributes
| Name | |
|---|---|
| int | ran Jobs that ran, and params the discard function released. |
| int | discarded |
| pthread_mutex_t | count_lock Guards the two counters. |
Detailed Description
destroy_threaded_pool() does not drop queued jobs silently.
Author: Castagnier Mickael
Version: 1.0
Date: 22/09/2026
One thread, one slow job running and three queued behind it. With a retry budget shorter than the running job, destroy gives up waiting, joins the thread - which still waits for the running job - and discards the three queued ones without running them. Their params used to go with them, unreleased and unmentioned; under a leak checker that was three leaks and nowhere else was it visible.
Now each discarded param is handed to the pool's discard function. This checks that exactly the three queued jobs are discarded, that the running one completes, and that a budget long enough to drain the queue runs all four and discards none. Run under ASan, a param that nobody releases fails the run.
Functions Documentation
function slow_job
static void * slow_job(
void * p
)
A job that takes 300 ms and releases its own param.
Parameters:
- p A malloc'd int.
Return: NULL
function run
static int run(
unsigned int delay
)
Queue four slow jobs on a one thread pool and destroy it.
Parameters:
- delay destroy_threaded_pool()'s retry delay, in microseconds.
Return: 0 when every job was set up, 1 otherwise.
function main
int main(
void
)
function discard_job
static void discard_job(
void * p
)
Discard function: releases a param that will never be run.
Parameters:
- p A malloc'd int.
Attributes Documentation
variable ran
static int ran = 0;
Jobs that ran, and params the discard function released.
variable discarded
static int discarded = 0;
variable count_lock
static pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
Guards the two counters.
Source code
/*
* Nilorea Library
* Copyright (C) 2005-2026 Castagnier Mickael
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "nilorea/n_common.h"
#include "nilorea/n_log.h"
#include "nilorea/n_thread_pool.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int ran = 0, discarded = 0;
static pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;
static void* slow_job(void* p) {
usleep(300000);
pthread_mutex_lock(&count_lock);
ran++;
pthread_mutex_unlock(&count_lock);
free(p);
return NULL;
}
static void discard_job(void* p) {
pthread_mutex_lock(&count_lock);
discarded++;
pthread_mutex_unlock(&count_lock);
free(p);
}
static int run(unsigned int delay) {
THREAD_POOL* pool = new_thread_pool(1, 0);
int i = 0;
if (!pool) return 1;
set_thread_pool_discard(pool, discard_job);
ran = discarded = 0;
for (i = 0; i < 4; i++) {
int* p = malloc(sizeof(int));
if (!p) return 1;
*p = i;
if (add_threaded_process(pool, slow_job, p, NORMAL_PROC) != TRUE) {
free(p);
return 1;
}
}
usleep(20000); /* let the first one start */
destroy_threaded_pool(&pool, delay);
return 0;
}
int main(void) {
int failures = 0;
/* The error line destroy logs for the short budget is the expected
outcome here, so it is not shown. */
set_log_level(LOG_NULL);
/* 1000 retries of 100 us is 0.1 s, shorter than the running job. */
if (run(100) != 0) failures++;
if (ran != 1 || discarded != 3) {
fprintf(stderr, "short budget: %d ran and %d discarded, wanted 1 and 3\n", ran, discarded);
failures++;
}
/* 1000 retries of 1 ms is a second: the queue drains inside it. */
if (run(1000) != 0) failures++;
if (ran != 4 || discarded != 0) {
fprintf(stderr, "long budget: %d ran and %d discarded, wanted 4 and 0\n", ran, discarded);
failures++;
}
if (failures) {
fprintf(stderr, "ex_thread_pool_discard: %d failure(s)\n", failures);
return 1;
}
printf("ex_thread_pool_discard: all checks passed\n");
return 0;
}
Modules
- AABB3D
- ACCEPT_POOL
- ALLEGRO4
- ALLEGRO5
- ANIM_LIB
- ASTAR
- ATLAS_LIB
- AVRO
- CLOCK_SYNC
- COMMONS
- CONFIGFILE
- CYPHER_BASE64
- CYPHER_VIGENERE
- DEAD_RECKONING
- ENUMS
- EXCEPTIONS
- GAME_ENV
- GIT
- GUI
- HASH_TABLE
- ISOMETRIC_ENGINE
- LIST
- LOG
- LOGNODUP
- LZ4
- NETWORKING
- NETWORK_MSG
- N_COOKIES
- N_DIFF
- N_DIGEST
- N_DISK_CACHE
- N_DNS
- N_ECC
- N_ENTROPY
- N_FILES
- N_FLUIDS
- N_GUI_COLOR
- N_GUI_COLORWHEEL
- N_GUI_CURVE
- N_GUI_GRID
- N_GUI_POPUP
- N_HEX
- N_HTTP3
- N_HTTP_COOKIE
- N_HTTP_FORM
- N_HTTP_MIME
- N_HTTP_REQ
- N_HTTP_RESP
- N_HTTP_ROUTER
- N_HTTP_SERVER
- N_ICC
- N_JSON
- N_KAFKA
- N_LINALG
- N_MODULE
- N_OPENSSL_COMPAT
- N_PRETTY
- N_PTH
- N_QUERY
- N_RANDOM
- N_SHA256
- N_STR
- N_TIFF
- N_TIME
- N_USER
- N_X509
- N_ZIP
- PARTICLES
- PCRE
- PHYSICS
- SIGNALS
- STACK
- THREADS
- TRAJECTORY
- TREE
- ZLIB