Mstdlib-1.24.0

Typedefs

typedef struct M_threadpool M_threadpool_t
 
typedef struct M_threadpool_parent M_threadpool_parent_t
 

Functions

M_threadpool_tM_threadpool_create (size_t min_threads, size_t max_threads, M_uint64 idle_time_ms, size_t queue_max_size)
 
void M_threadpool_destroy (M_threadpool_t *pool)
 
M_threadpool_parent_tM_threadpool_parent_create (M_threadpool_t *pool)
 
M_bool M_threadpool_parent_destroy (M_threadpool_parent_t *parent)
 
void M_threadpool_dispatch (M_threadpool_parent_t *parent, void(*task)(void *), void **task_args, size_t num_tasks)
 
void M_threadpool_dispatch_notify (M_threadpool_parent_t *parent, void(*task)(void *), void **task_args, size_t num_tasks, void(*finished)(void *))
 
size_t M_threadpool_available_slots (const M_threadpool_t *pool)
 
void M_threadpool_wait_available_thread (M_threadpool_parent_t *parent)
 
size_t M_threadpool_num_threads (const M_threadpool_t *pool)
 
void M_threadpool_parent_wait (M_threadpool_parent_t *parent)
 

Detailed Description

Implementation of a thread pool for having a limited the number of threads available to workers. Threads in the pool will only be destroyed when the pool is destroyed. A maximum number of threads will be created by the pool. Workers are assigned to parents which can be used to logically separate workers by tasks.

Example:

static M_uint32 count = 0;
static void pool_task(void *arg)
{
(void)arg;
}
int main(int argc, char **argv)
{
char args[32];
M_mem_set(args, 0, sizeof(args));
pool = M_threadpool_create(16, 16, 0, SIZE_MAX);
M_threadpool_dispatch(parent, pool_task, (void **)&args, sizeof(args));
M_printf("count='%u'\n", count);
return 0;
}
M_uint32 M_atomic_inc_u32(volatile M_uint32 *ptr)
ssize_t M_printf(const char *fmt,...)
void * M_mem_set(void *s, int c, size_t n)
void M_threadpool_dispatch(M_threadpool_parent_t *parent, void(*task)(void *), void **task_args, size_t num_tasks)
M_threadpool_t * M_threadpool_create(size_t min_threads, size_t max_threads, M_uint64 idle_time_ms, size_t queue_max_size)
M_bool M_threadpool_parent_destroy(M_threadpool_parent_t *parent)
struct M_threadpool_parent M_threadpool_parent_t
Definition: m_threadpool.h:86
struct M_threadpool M_threadpool_t
Definition: m_threadpool.h:83
M_threadpool_parent_t * M_threadpool_parent_create(M_threadpool_t *pool)
void M_threadpool_destroy(M_threadpool_t *pool)
void M_threadpool_parent_wait(M_threadpool_parent_t *parent)

Typedef Documentation

◆ M_threadpool_t

typedef struct M_threadpool M_threadpool_t

◆ M_threadpool_parent_t

typedef struct M_threadpool_parent M_threadpool_parent_t

Function Documentation

◆ M_threadpool_create()

M_threadpool_t * M_threadpool_create ( size_t  min_threads,
size_t  max_threads,
M_uint64  idle_time_ms,
size_t  queue_max_size 
)

Initializes a new threadpool and spawns the minimum number of threads requested.

Parameters
[in]min_threadsMinimum number of threads to spawn, 0 to not pre-spawn any.
[in]max_threadsMaximum number of threads to spawn, any number above the min_threads number will be spawned on demand, and idle threads will be shutdown after the specified idle time. Must be greater than 0.
[in]idle_time_msNumber of milliseconds a thread can be idle for before it is destroyed when the total thread count is above min_threads. If min_threads and max_threads are the same value, this parameter is ignored. Use M_UINT64_MAX to never terminate an idle thread, or use 0 to never allow idle threads.
[in]queue_max_sizeIf 0, will calculate a desirable queue size based on the maximum thread count. Otherwise, must be at least the size of the thread pool. It often makes sense to have the queue larger than the threadpool size to prevent the threads from sleeping. When inserting into the queue, if there are no available slots the M_threadpool_dispatch() function will block. If blocking is not desirable, use SIZE_MAX to allow an unbounded number of queue slots.
Returns
initialized threadpool or NULL on failure

◆ M_threadpool_destroy()

void M_threadpool_destroy ( M_threadpool_t pool)

Shuts down the thread pool, waits for all threads to exit.

Parameters
[in]poolinitialized threadpool.

◆ M_threadpool_parent_create()

M_threadpool_parent_t * M_threadpool_parent_create ( M_threadpool_t pool)

Creates a new parent/user/consumer of the threadpool.

This is the handle used to insert tasks and wait for task completion specific to the consumer.

It is safe to share this handle across multiple threads if convenient as long as it is guaranteed to not be destroyed until all consumers are done using it. If sharing across multiple threads, it probably would mean you would not be using M_threadpool_parent_wait() from multiple threads simultaneously.

Parameters
[in]poolInitialized thread pool.
Returns
initialized parent/user/consumer handle.

◆ M_threadpool_parent_destroy()

M_bool M_threadpool_parent_destroy ( M_threadpool_parent_t parent)

Frees the parent handle.

There must be no oustanding tasks prior to calling this. Call M_threadpool_parent_wait() first if unsure to wait on all tasks to complete.

Parameters
[in]parentInitialized parent handle.
Returns
M_FALSE if there are tasks remaining, M_TRUE if successfully cleaned up.

◆ M_threadpool_dispatch()

void M_threadpool_dispatch ( M_threadpool_parent_t parent,
void(*)(void *)  task,
void **  task_args,
size_t  num_tasks 
)

Dispatch a task or set of tasks to the threadpool. Identical to M_threadpool_dispatch_notify() if passed a NULL finished argument.

Requires a callback function to do the processing and an argument that is passed to the function. There is no way to retrieve a return value from the task, so the argument passed to the task should hold a result parameter if it is necessary to know the completion status. Multiple tasks may be queued simultaneously.

This may take a while to complete if there are no queue slots available.

Parameters
[in,out]parentInitialized parent handle.
[in]taskTask callback.
[in,out]task_argsArgument array to pass to each task (one per task).
[in]num_taskstotal number of tasks being enqueued.

◆ M_threadpool_dispatch_notify()

void M_threadpool_dispatch_notify ( M_threadpool_parent_t parent,
void(*)(void *)  task,
void **  task_args,
size_t  num_tasks,
void(*)(void *)  finished 
)

Dispatch a task or set of tasks to the threadpool and notify on task completion.

Requires a callback function to do the processing and an argument that is passed to the function. There is no way to retrieve a return value from the task, so the argument passed to the task should hold a result parameter if it is necessary to know the completion status. Multiple tasks may be queued simultaneously.

This may take a while to complete if there are no queue slots available.

Parameters
[in,out]parentInitialized parent handle.
[in]taskTask callback.
[in,out]task_argsArgument array to pass to each task (one per task).
[in]num_taskstotal number of tasks being enqueued.
[in]finishedOptional. Callback to call for each task completion. Will pass the callback the same argument passed to the task. Use NULL if no notification desired.

◆ M_threadpool_available_slots()

size_t M_threadpool_available_slots ( const M_threadpool_t pool)

Count the number of queue slots available to be enqueued for a threadpool.

Parameters
[in]poolinitialized threadpool.

◆ M_threadpool_wait_available_thread()

void M_threadpool_wait_available_thread ( M_threadpool_parent_t parent)

Wait for a thread to become available for processing tasks.

This explicitly waits for a THREAD and NOT an available queue slot which there could be available slots. This is meant as an optimization in some instances where you want to ensure you enqueue some things together, especially if you're trying to manage SQL locks for tasks being performed. Typically though, this function would never be used.

Parameters
[in]parentInitialized parent handle.

◆ M_threadpool_num_threads()

size_t M_threadpool_num_threads ( const M_threadpool_t pool)

Get the current count of the number of threads in the thread pool.

Parameters
[in]poolInitialized pool handle.
Returns
count of threads

◆ M_threadpool_parent_wait()

void M_threadpool_parent_wait ( M_threadpool_parent_t parent)

Wait for all queued tasks to complete then return.

This is a blocking function with no return value. It is not recommended to call this from mulitiple threads simultaneously.

Parameters
[in]parentthe initialized parent/user/consumer handle.