Skip to content

Thread Pool

Sudheer edited this page Mar 11, 2023 · 12 revisions

Description

Implementation of a minimalist thread pool in C.

Uses ev_queue a lock-free queue, for the purpose of enqueueing tasks to the thread pool.
The worker threads use mutexes to coordinate. Prototype implementation without mutex/lock performs poorly in terms of CPU usage due to busy wait. Since the tasks can come at any instance spread over time, it is more efficient to use the lock based implementation as against a lock free one.

#include <thread_pool.h>

Inclusion of thread_pool.h exposes the following typedefs

typedef struct thread_pool_s thread_pool_s_type;
typedef struct thread_pool_s *thread_pool_type;
typedef void * task_argument_type;

Taks to the thread pool are submitted in the form of a function pointer to a function that performs the desired operation and a function pointer that performs the management of task complete notification.

typedef void (*task_func_type)(task_argument_type);
typedef void* (*task_func_with_return_t)(task_argument_type);
typedef void (*notify_task_completion_t)(void*, void*);

Thread pool management functions

thread_pool_type create_thread_pool(int num_threads);

Creates a thread pool with num_threads, with this all the worker threads will be in the state
of waiting to perform a task

Parameters:
    num_threads: int
Return:
    thread_pool: thread_pool_type 

ERROR:
    upon error, return value is NULL and the global variable errno is set
    EINVAL: invalid value of num_threads.

    In case of being unable to create threads, the function aborts printing error to
    standard ouput.

int destroy_thread_pool(thread_pool_type);

Shuts down the thread_pool and frees up allocated memory. All the worker threads are stopped
at the end of this operation.

Parameters:
	thread_pool: thread_pool_type
Return:
    ret : int, 0 is returned upon success and -1 in case of any error

ERROR:
    if ret is -1 the global variable errno is set to
    EINVAL: In case the passed thread pool is not valid
	EBUSY: In case shutdown process has already been initiated.

Task management functions

Two types of tasks can be submitted to thread pool

  1. Functions that take an argument and dont have a return, the caller should separately arrange to get results once the task is complete
  2. Functions that take an argument (task_argument_type) and have a return (task_argument_type), a notification function gets called upon completion and the caller can implement any return data handling in the notification function.

void enqueue_task(thread_pool_type, task_func_type, task_argument_type);

Pushes a type1 task to the thread_pool queue.

Parameters:
    thread_pool: thread_pool_type
    task_func: task_func_type
    arg: task_argument_type
Return:
    void

ERROR:
    TBD: Backlog

void enqueue_task_function(thread_pool_type, task_func_with_return_t,
task_argument_type, void * ref_data, notify_task_completion_t);

Pushes a type2 task to the queue. The task function will return upon completion and the notification function
will be invoked with return value of the task function and ref_data as arguments.

Parameters:
    threa_pool: thread_pool_type
    task_func: task_func_with_return_t
    arg: task_argument_type
    ref_data: void*
    notification_func: notify_task_completion_t
Return:
    none

ERROR:
    TBD: Backlog