C-Thread-Pool/thpool.h

237 lines
7.1 KiB
C
Raw Normal View History

2011-11-05 16:35:31 +04:00
/**********************************
* @author Johan Hanssen Seferidis
* @date 12/08/2011
* Last update: 01/11/2011
* License: LGPL
*
**********************************/
/* Description: Library providing a threading pool where you can add work on the fly. The number
* of threads in the pool is adjustable when creating the pool. In most cases
* this should equal the number of threads supported by your cpu.
*
* For an example on how to use the threadpool, check the main.c file or just read
* the documentation.
*
* In this header file a detailed overview of the functions and the threadpool logical
* scheme is present in case tweaking of the pool is needed.
* */
/*
* Fast reminders:
*
* tp = threadpool
* thpool = threadpool
* thpool_t = threadpool type
* tp_p = threadpool pointer
* sem = semaphore
* xN = x can be any string. N stands for amount
*
* */
/* _______________________________________________________
* / \
* | JOB QUEUE | job1 | job2 | job3 | job4 | .. |
* | |
* | threadpool | thread1 | thread2 | .. |
* \_______________________________________________________/
*
* Description: Jobs are added to the job queue. Once a thread in the pool
* is idle, it is assigned with the first job from the queue(and
* erased from the queue). It's each thread's job to read from
* the queue serially(using lock) and executing each job
* until the queue is empty.
*
*
* Scheme:
*
* thpool______ jobqueue____ ______
* | | | | .----------->|_job0_| Newly added job
* | | | head------------' |_job1_|
* | jobqueue----------------->| | |_job2_|
* | | | tail------------. |__..__|
* |___________| |___________| '----------->|_jobn_| Job for thread to take
*
*
* job0________
* | |
* | function---->
* | |
* | arg------->
* | | job1________
* | next-------------->| |
* |___________| | |..
*/
#ifndef _THPOOL_
#define _THPOOL_
#include <pthread.h>
#include <semaphore.h>
/* ================================= STRUCTURES ================================================ */
/* Individual job */
2014-11-23 14:38:34 +03:00
typedef struct job_t{
void* (*function)(void* arg); /**< function pointer */
void* arg; /**< function's argument */
struct job_t* next; /**< pointer to next job */
struct job_t* prev; /**< pointer to previous job */
}job_t;
2011-11-05 16:35:31 +04:00
/* Job queue as doubly linked list */
typedef struct thpool_jobqueue{
2014-11-23 14:38:34 +03:00
job_t *head; /**< pointer to head of queue */
job_t *tail; /**< pointer to tail of queue */
2011-11-05 16:35:31 +04:00
}thpool_jobqueue;
/* The threadpool */
typedef struct thpool_t{
2014-11-23 14:38:34 +03:00
pthread_t* threads; /**< pointer to threads' ID */
int threadsN; /**< amount of threads */
thpool_jobqueue* jobqueue; /**< pointer to the job queue */
sem_t *queued_jobsN; /**< number of jobs in queue */
2011-11-05 16:35:31 +04:00
}thpool_t;
/* Container for all things that each thread is going to need */
typedef struct thread_data{
pthread_mutex_t *mutex_p;
thpool_t *tp_p;
}thread_data;
/* =========================== FUNCTIONS ================================================ */
/* ----------------------- Threadpool specific --------------------------- */
/**
* @brief Initialize threadpool
*
* Allocates memory for the threadpool, jobqueue, semaphore and fixes
* pointers in jobqueue.
*
* @param number of threads to be used
* @return threadpool struct on success,
* NULL on error
*/
thpool_t* thpool_init(int threadsN);
/**
* @brief What each thread is doing
*
* In principle this is an endless loop. The only time this loop gets interuppted is once
* thpool_destroy() is invoked.
*
* @param threadpool to use
* @return nothing
*/
void thpool_thread_do(thpool_t* tp_p);
/**
* @brief Add work to the job queue
*
* Takes an action and its argument and adds it to the threadpool's job queue.
* If you want to add to work a function with more than one arguments then
* a way to implement this is by passing a pointer to a structure.
*
* ATTENTION: You have to cast both the function and argument to not get warnings.
*
* @param threadpool to where the work will be added to
* @param function to add as work
* @param argument to the above function
* @return int
*/
int thpool_add_work(thpool_t* tp_p, void *(*function_p)(void*), void* arg_p);
/**
* @brief Destroy the threadpool
*
* This will 'kill' the threadpool and free up memory. If threads are active when this
* is called, they will finish what they are doing and then they will get destroyied.
*
* @param threadpool a pointer to the threadpool structure you want to destroy
*/
void thpool_destroy(thpool_t* tp_p);
/* ------------------------- Queue specific ------------------------------ */
/**
* @brief Initialize queue
* @param pointer to threadpool
* @return 0 on success,
* -1 on memory allocation error
*/
2014-11-23 14:38:34 +03:00
int jobqueue_init(thpool_t* tp_p);
2011-11-05 16:35:31 +04:00
/**
* @brief Add job to queue
*
* A new job will be added to the queue. The new job MUST be allocated
2014-11-23 14:38:34 +03:00
* before passed to this function or else other functions like jobqueue_empty()
2011-11-05 16:35:31 +04:00
* will be broken.
*
* @param pointer to threadpool
* @param pointer to the new job(MUST BE ALLOCATED)
* @return nothing
*/
2014-11-23 14:38:34 +03:00
void jobqueue_push(thpool_t* tp_p, job_t* newjob_p);
2011-11-05 16:35:31 +04:00
/**
2014-11-23 14:38:34 +03:00
* @brief Get first job from queue(removes it from queue)
2011-11-05 16:35:31 +04:00
*
* This does not free allocated memory so be sure to have peeked() \n
* before invoking this as else there will result lost memory pointers.
*
* @param pointer to threadpool
2014-11-23 14:38:34 +03:00
* @return point to job on success,
* NULL if there is no job in queue
2011-11-05 16:35:31 +04:00
*/
2014-11-23 14:38:34 +03:00
job_t* jobqueue_pull(thpool_t* tp_p);
2011-11-05 16:35:31 +04:00
/**
* @brief Get last job in queue (tail)
*
* Gets the last job that is inside the queue. This will work even if the queue
* is empty.
*
* @param pointer to threadpool structure
* @return job a pointer to the last job in queue,
* a pointer to NULL if the queue is empty
*/
2014-11-23 14:38:34 +03:00
job_t* thpool_jobqueue_peek(thpool_t* tp_p);
2011-11-05 16:35:31 +04:00
/**
* @brief Remove and deallocate all jobs in queue
*
* This function will deallocate all jobs in the queue and set the
* jobqueue to its initialization values, thus tail and head pointing
* to NULL and amount of jobs equal to 0.
*
* @param pointer to threadpool structure
* */
2014-11-23 14:38:34 +03:00
void jobqueue_empty(thpool_t* tp_p);
2011-11-05 16:35:31 +04:00
#endif