Simplicity
This commit is contained in:
parent
d42a436bfc
commit
1c20ad1cde
248
thpool.c
248
thpool.c
|
@ -14,7 +14,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <semaphore.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -24,55 +23,73 @@
|
||||||
#define POLLING_INTERVAL 1
|
#define POLLING_INTERVAL 1
|
||||||
|
|
||||||
static int threads_keepalive;
|
static int threads_keepalive;
|
||||||
static int threads_hold_flag;
|
static int threads_on_hold;
|
||||||
|
|
||||||
|
static int return_value;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================== THREADPOOL ============================ */
|
||||||
|
|
||||||
/* Initialise thread pool */
|
/* Initialise thread pool */
|
||||||
thpool_t* thpool_init(int threadsN){
|
thpool_t* thpool_init(int threadsN){
|
||||||
|
|
||||||
threads_hold_flag = 0;
|
threads_on_hold = 0;
|
||||||
threads_keepalive = 1;
|
threads_keepalive = 1;
|
||||||
|
|
||||||
if (threadsN < 0){
|
if ( threadsN < 0){
|
||||||
threadsN = 0;
|
threadsN = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Make new thread pool */
|
/* Make new thread pool */
|
||||||
thpool_t* thpool;
|
thpool_t* thpool;
|
||||||
thpool = (thpool_t*)malloc(sizeof(thpool_t));
|
thpool = (thpool_t*)malloc(sizeof(thpool_t));
|
||||||
if (thpool==NULL){
|
if (thpool==NULL){
|
||||||
fprintf(stderr, "thpool_init(): Could not allocate memory for thread pool\n");
|
fprintf(stderr, "thpool_init(): Could not allocate memory for thread pool\n");
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
thpool->threads_alive = 0;
|
||||||
|
|
||||||
/* Initialise the job queue */
|
/* Initialise the job queue */
|
||||||
if (jobqueue_init(thpool)==-1){
|
if (jobqueue_init(thpool)==-1){
|
||||||
fprintf(stderr, "thpool_init(): Could not allocate memory for job queue\n");
|
fprintf(stderr, "thpool_init(): Could not allocate memory for job queue\n");
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make threads in pool */
|
/* Make threads in pool */
|
||||||
thpool->threads = (thread_t*)malloc(threadsN*sizeof(thread_t));
|
thpool->threads = (thread_t**)malloc(threadsN * sizeof(thread_t));
|
||||||
if (thpool->threads==NULL){
|
if (thpool->threads==NULL){
|
||||||
fprintf(stderr, "thpool_init(): Could not allocate memory for threads\n");
|
fprintf(stderr, "thpool_init(): Could not allocate memory for threads\n");
|
||||||
return NULL;
|
exit(1);
|
||||||
}
|
}
|
||||||
thpool->threadsN=threadsN;
|
|
||||||
|
/* Thread init */
|
||||||
int n;
|
int n;
|
||||||
for (n=0; n<threadsN; n++){
|
for (n=0; n<threadsN; n++){
|
||||||
|
|
||||||
thread_t* th;
|
thread_init(thpool, thpool->threads[n], n);
|
||||||
th = &(thpool->threads[n]);
|
//thpool->threads[n]->thpool = thpool;
|
||||||
(*th).id = n;
|
/*puts("next");
|
||||||
args_t args;
|
thpool->threads[n] = thread_init(thpool);
|
||||||
args.arg1 = thpool;
|
(*thpool->threads[n]).id = n;
|
||||||
args.arg2 = th;
|
printf("Created thread %d in pool \n", n);*/
|
||||||
pthread_create(&((*th).pthread), NULL, (void *)thread_do, (args_t*)&args);
|
|
||||||
pthread_detach((*th).pthread);
|
|
||||||
printf("Created thread %d in pool \n", (*th).id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
//thpool->threads[n] = malloc(sizeof(thread_t));
|
||||||
|
// thpool->threads[n]->initialized = 0;
|
||||||
|
//thpool->threads[n]->thpool = thpool;
|
||||||
|
// pthread_create(&thpool->threads[n]->pthread, NULL, (void *)thread_do, thpool->threads[n]);
|
||||||
|
// pthread_detach(thpool->threads[n]->pthread);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for threads to initialize */
|
||||||
|
while (thpool->threads_alive != threadsN) {}
|
||||||
|
|
||||||
return thpool;
|
return thpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,21 +97,21 @@ thpool_t* thpool_init(int threadsN){
|
||||||
/* Add work to the thread pool */
|
/* Add work to the thread pool */
|
||||||
int thpool_add_work(thpool_t* thpool, void *(*function_p)(void*), void* arg_p){
|
int thpool_add_work(thpool_t* thpool, void *(*function_p)(void*), void* arg_p){
|
||||||
job_t* newjob;
|
job_t* newjob;
|
||||||
|
|
||||||
newjob=(job_t*)malloc(sizeof(job_t));
|
newjob=(job_t*)malloc(sizeof(job_t));
|
||||||
if (newjob==NULL){
|
if (newjob==NULL){
|
||||||
fprintf(stderr, "thpool_add_work(): Could not allocate memory for new job\n");
|
fprintf(stderr, "thpool_add_work(): Could not allocate memory for new job\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add function and argument */
|
/* add function and argument */
|
||||||
newjob->function=function_p;
|
newjob->function=function_p;
|
||||||
newjob->arg=arg_p;
|
newjob->arg=arg_p;
|
||||||
|
|
||||||
/* add job to queue */
|
/* add job to queue */
|
||||||
pthread_mutex_lock(&thpool->rwmutex);
|
pthread_mutex_lock(&thpool->jobqueue->rwmutex);
|
||||||
jobqueue_push(thpool, newjob);
|
jobqueue_push(thpool, newjob);
|
||||||
pthread_mutex_unlock(&thpool->rwmutex);
|
pthread_mutex_unlock(&thpool->jobqueue->rwmutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -113,31 +130,22 @@ void thpool_destroy(thpool_t* thpool){
|
||||||
|
|
||||||
/* End each thread 's infinite loop */
|
/* End each thread 's infinite loop */
|
||||||
threads_keepalive = 0;
|
threads_keepalive = 0;
|
||||||
|
|
||||||
int any_threads_idle(thpool_t* thpool){
|
/* Give one second to kill idle threads */
|
||||||
int n;
|
|
||||||
for (n=0; n < (thpool->threadsN); n++){
|
|
||||||
if (!thpool->threads[n].working){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kill idle threads */
|
|
||||||
double TIMEOUT = 1.0;
|
double TIMEOUT = 1.0;
|
||||||
time_t start, end;
|
time_t start, end;
|
||||||
double tpassed;
|
double tpassed;
|
||||||
time (&start);
|
time (&start);
|
||||||
while (any_threads_idle(thpool))
|
while (tpassed < TIMEOUT && thpool->threads_alive){
|
||||||
{
|
|
||||||
while (tpassed < TIMEOUT)
|
|
||||||
{
|
|
||||||
bsem_post(thpool->jobqueue->has_jobs);
|
|
||||||
time (&end);
|
|
||||||
tpassed = difftime(end,start);
|
|
||||||
}
|
|
||||||
bsem_post(thpool->jobqueue->has_jobs);
|
bsem_post(thpool->jobqueue->has_jobs);
|
||||||
|
time (&end);
|
||||||
|
tpassed = difftime(end,start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Poll remaining threads */
|
||||||
|
while (thpool->threads_alive){
|
||||||
|
bsem_post(thpool->jobqueue->has_jobs);
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Job queue cleanup */
|
/* Job queue cleanup */
|
||||||
|
@ -152,98 +160,81 @@ void thpool_destroy(thpool_t* thpool){
|
||||||
|
|
||||||
|
|
||||||
void thpool_pause(thpool_t* thpool) {
|
void thpool_pause(thpool_t* thpool) {
|
||||||
threads_hold();
|
int n;
|
||||||
|
for (n=0; n < thpool->threads_alive; n++){
|
||||||
|
//pthread_kill(thpool->threads[n]->pthread, SIGUSR1);
|
||||||
|
pthread_kill(thpool->threads[n]->pthread, SIGUSR1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void thpool_continue(thpool_t* thpool) {
|
void thpool_continue(thpool_t* thpool) {
|
||||||
threads_unhold();
|
threads_on_hold = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ====================== THREAD OPERATIONS ========================= */
|
/* ============================ THREAD ============================== */
|
||||||
|
|
||||||
|
thread_t* thread_init (thpool_t *thpool, thread_t *thread, int id){
|
||||||
|
//thread = malloc(sizeof(thread_t));
|
||||||
|
//thread->initialized = 0;
|
||||||
|
//thread->thpool = thpool;
|
||||||
|
//pthread_create(&thread->pthread, NULL, (void *)thread_do, thread);
|
||||||
|
//pthread_detach(thread->pthread);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
thread = malloc(sizeof(thread_t));
|
||||||
|
if (thread == NULL){
|
||||||
|
fprintf(stderr, "thpool_init(): Could not allocate memory for thread\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
static void threads_hold () {
|
thread->thpool = thpool;
|
||||||
threads_hold_flag = 1;
|
thread->id = id;
|
||||||
while (threads_hold_flag){
|
|
||||||
|
pthread_create(&thread->pthread, NULL, (void *)thread_do, thread);
|
||||||
|
pthread_detach(thread->pthread);
|
||||||
|
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void thread_hold () {
|
||||||
|
threads_on_hold = 1;
|
||||||
|
while (threads_on_hold){
|
||||||
sleep(1);
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void threads_unhold () {
|
static void* thread_do(thread_t* thread){
|
||||||
threads_hold_flag = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void thread_suicide() {
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void thread_kill(thread_t *th, int now) {
|
|
||||||
if (!now && (*th).working){
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
pthread_kill((*th).pthread, SIGTERM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void signal_handler (int signum) {
|
|
||||||
|
|
||||||
switch(signum){
|
|
||||||
|
|
||||||
case SIGUSR1:
|
|
||||||
threads_hold();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SIGUSR2:
|
|
||||||
threads_unhold();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SIGTERM:
|
|
||||||
thread_suicide();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init point for each thread
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
static void thread_do(args_t* args){
|
|
||||||
|
|
||||||
/* Assure all threads have been created before starting serving */
|
/* Assure all threads have been created before starting serving */
|
||||||
thpool_t* thpool;
|
thpool_t* thpool = thread->thpool;
|
||||||
thread_t* thread;
|
|
||||||
thpool = (*args).arg1;
|
|
||||||
thread = (*args).arg2;
|
|
||||||
(*thread).working = 0;
|
|
||||||
|
|
||||||
/* Register signal handler */
|
/* Register signal handler */
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
act.sa_handler = signal_handler;
|
act.sa_handler = thread_hold;
|
||||||
if (sigaction(SIGUSR1, &act, NULL) == -1) {
|
if (sigaction(SIGUSR1, &act, NULL) == -1) {
|
||||||
perror("Error: cannot handle SIGUSR1");
|
perror("Error: cannot handle SIGUSR1");
|
||||||
}
|
}
|
||||||
if (sigaction(SIGUSR2, &act, NULL) == -1) {
|
|
||||||
perror("Error: cannot handle SIGUSR2");
|
|
||||||
}
|
|
||||||
if (sigaction(SIGTERM, &act, NULL) == -1) {
|
|
||||||
perror("Error: cannot handle SIGTERM");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Mark thread as alive (initialized) */
|
||||||
|
pthread_mutex_lock(&thpool->thcount_lock);
|
||||||
|
thpool->threads_alive += 1;
|
||||||
|
pthread_mutex_unlock(&thpool->thcount_lock);
|
||||||
|
// puts("ts");
|
||||||
|
|
||||||
|
//printf("Thread (%u) initialized init?: %d\n", (int)pthread_self(), (*thread).initialized);
|
||||||
|
//printf("Thread (%u) init adr: %p\n", (int)pthread_self(), &(*thread).initialized);
|
||||||
|
//printf("Thread (%u) id: %d\n", (int)pthread_self(), (*thread).id);
|
||||||
|
|
||||||
while(threads_keepalive){
|
while(threads_keepalive){
|
||||||
|
|
||||||
bsem_wait(thpool->jobqueue->has_jobs);
|
bsem_wait(thpool->jobqueue->has_jobs);
|
||||||
(*thread).working = 1;
|
|
||||||
|
|
||||||
if (threads_keepalive){
|
if (threads_keepalive){
|
||||||
|
|
||||||
|
@ -251,30 +242,35 @@ static void thread_do(args_t* args){
|
||||||
void*(*func_buff)(void* arg);
|
void*(*func_buff)(void* arg);
|
||||||
void* arg_buff;
|
void* arg_buff;
|
||||||
job_t* job;
|
job_t* job;
|
||||||
pthread_mutex_lock(&thpool->rwmutex);
|
pthread_mutex_lock(&thpool->jobqueue->rwmutex);
|
||||||
job = jobqueue_pull(thpool);
|
job = jobqueue_pull(thpool);
|
||||||
pthread_mutex_unlock(&thpool->rwmutex);
|
pthread_mutex_unlock(&thpool->jobqueue->rwmutex);
|
||||||
if (job) {
|
if (job) {
|
||||||
func_buff = job->function;
|
func_buff = job->function;
|
||||||
arg_buff = job->arg;
|
arg_buff = job->arg;
|
||||||
func_buff(arg_buff);
|
func_buff(arg_buff);
|
||||||
free(job);
|
free(job);
|
||||||
}
|
}
|
||||||
(*thread).working = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&thpool->rwmutex);
|
pthread_mutex_lock(&thpool->thcount_lock);
|
||||||
thpool->threadsN --;
|
thpool->threads_alive --;
|
||||||
pthread_mutex_unlock(&thpool->rwmutex);
|
pthread_mutex_unlock(&thpool->thcount_lock);
|
||||||
printf("Thread %d exiting\n", (*thread).id);
|
printf("Thread %d exiting\n", (*thread).id);
|
||||||
thread_suicide();
|
pthread_exit(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void thread_destroy (thread_t* thread){
|
||||||
|
free(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ===================== JOB QUEUE OPERATIONS ======================= */
|
/* ============================ JOB QUEUE =========================== */
|
||||||
|
|
||||||
|
|
||||||
/* Initialise queue */
|
/* Initialise queue */
|
||||||
|
@ -284,6 +280,7 @@ static int jobqueue_init(thpool_t* thpool){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
thpool->jobqueue->has_jobs = (bsem_t*)malloc(sizeof(bsem_t));
|
thpool->jobqueue->has_jobs = (bsem_t*)malloc(sizeof(bsem_t));
|
||||||
|
bsem_init(thpool->jobqueue->has_jobs, 0);
|
||||||
jobqueue_clear(thpool);
|
jobqueue_clear(thpool);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -371,6 +368,18 @@ static void jobqueue_destroy(thpool_t* thpool){
|
||||||
/* ======================== SYNCHRONISATION ========================= */
|
/* ======================== SYNCHRONISATION ========================= */
|
||||||
|
|
||||||
|
|
||||||
|
/* Binary semaphore init */
|
||||||
|
static void bsem_init(bsem_t *bsem, int value) {
|
||||||
|
bsem->v = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Binary semaphore reset */
|
||||||
|
static void bsem_reset(bsem_t *bsem) {
|
||||||
|
bsem_init(bsem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Binary semaphore post */
|
/* Binary semaphore post */
|
||||||
static void bsem_post(bsem_t *bsem) {
|
static void bsem_post(bsem_t *bsem) {
|
||||||
pthread_mutex_lock(&bsem->mutex);
|
pthread_mutex_lock(&bsem->mutex);
|
||||||
|
@ -380,6 +389,15 @@ static void bsem_post(bsem_t *bsem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Binary semaphore post */
|
||||||
|
static void bsem_post_all(bsem_t *bsem) {
|
||||||
|
pthread_mutex_lock(&bsem->mutex);
|
||||||
|
bsem->v = 1;
|
||||||
|
pthread_cond_broadcast(&bsem->cond);
|
||||||
|
pthread_mutex_unlock(&bsem->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Binary semaphore wait */
|
/* Binary semaphore wait */
|
||||||
static void bsem_wait(bsem_t *bsem) {
|
static void bsem_wait(bsem_t *bsem) {
|
||||||
pthread_mutex_lock(&bsem->mutex);
|
pthread_mutex_lock(&bsem->mutex);
|
||||||
|
|
147
thpool.h
147
thpool.h
|
@ -69,13 +69,6 @@
|
||||||
/* ========================== STRUCTURES ============================ */
|
/* ========================== STRUCTURES ============================ */
|
||||||
|
|
||||||
|
|
||||||
/* Generic packed args */
|
|
||||||
typedef struct args_t {
|
|
||||||
void* arg1;
|
|
||||||
void* arg2;
|
|
||||||
} args_t;
|
|
||||||
|
|
||||||
|
|
||||||
/* Binary semaphore */
|
/* Binary semaphore */
|
||||||
typedef struct bsem_t {
|
typedef struct bsem_t {
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
@ -94,26 +87,28 @@ typedef struct job_t{
|
||||||
|
|
||||||
/* Job queue */
|
/* Job queue */
|
||||||
typedef struct jobqueue_t{
|
typedef struct jobqueue_t{
|
||||||
job_t *front; /* pointer to front of queue */
|
pthread_mutex_t rwmutex; /* used for queue r/w access */
|
||||||
job_t *rear; /* pointer to rear of queue */
|
job_t *front; /* pointer to front of queue */
|
||||||
bsem_t *has_jobs; /* flag as binary semaphore */
|
job_t *rear; /* pointer to rear of queue */
|
||||||
int len; /* number of jobs in queue */
|
bsem_t *has_jobs; /* flag as binary semaphore */
|
||||||
|
int len; /* number of jobs in queue */
|
||||||
} jobqueue_t;
|
} jobqueue_t;
|
||||||
|
|
||||||
|
|
||||||
/* Thread */
|
/* Thread */
|
||||||
typedef struct thread_t{
|
typedef struct thread_t{
|
||||||
int id; /* friendly id */
|
int id; /* friendly id */
|
||||||
int working; /* is thread idle or working? */
|
int initialized; /* binary to solve race conds */
|
||||||
pthread_t pthread; /* pointer to front of queue */
|
pthread_t pthread; /* pointer to actual thread */
|
||||||
|
struct thpool_t* thpool; /* access to thpool */
|
||||||
} thread_t;
|
} thread_t;
|
||||||
|
|
||||||
|
|
||||||
/* Threadpool */
|
/* Threadpool */
|
||||||
typedef struct thpool_t{
|
typedef struct thpool_t{
|
||||||
pthread_mutex_t rwmutex; /* used for queue w/r access */
|
thread_t** threads; /* pointer to threads */
|
||||||
thread_t* threads; /* pointer to threads */
|
int threads_alive; /* threads currently alive */
|
||||||
int threadsN; /* amount of threads */
|
pthread_mutex_t thcount_lock; /* used for thread count etc */
|
||||||
jobqueue_t* jobqueue; /* pointer to the job queue */
|
jobqueue_t* jobqueue; /* pointer to the job queue */
|
||||||
} thpool_t;
|
} thpool_t;
|
||||||
|
|
||||||
|
@ -139,18 +134,6 @@ typedef struct thpool_t{
|
||||||
thpool_t* thpool_init(int threadsN);
|
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
|
|
||||||
*/
|
|
||||||
static void thpool_thread_do(args_t* args);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add work to the job queue
|
* @brief Add work to the job queue
|
||||||
*
|
*
|
||||||
|
@ -179,6 +162,30 @@ int thpool_add_work(thpool_t* thpool, void *(*function_p)(void*), void* arg_p);
|
||||||
void thpool_wait(thpool_t* thpool);
|
void thpool_wait(thpool_t* thpool);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pauses all threads immediately
|
||||||
|
*
|
||||||
|
* The threads will be paused no matter if they are idle or working.
|
||||||
|
* The threads return to their previous states once thpool_continue
|
||||||
|
* is called.
|
||||||
|
*
|
||||||
|
* While the thread is being paused, new work can be added.
|
||||||
|
*
|
||||||
|
* @param threadpool where the threads should be paused
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
void thpool_pause(thpool_t* thpool);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unpauses all threads if they are paused
|
||||||
|
*
|
||||||
|
* @param threadpool where the threads should be unpaused
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
void thpool_continue(thpool_t* thpool);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy the threadpool
|
* @brief Destroy the threadpool
|
||||||
*
|
*
|
||||||
|
@ -192,6 +199,47 @@ void thpool_destroy(thpool_t* thpool);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------- Thread specific --------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a thread in the thread pool
|
||||||
|
*
|
||||||
|
* Will initialize a new thread for the given threadpool and give the
|
||||||
|
* the thread an ID
|
||||||
|
*
|
||||||
|
* Notice also that the thread's id is not populated automatically.
|
||||||
|
*
|
||||||
|
* @param threadpool threadpool to create thread
|
||||||
|
* @param thread pointer to the thread that will be created
|
||||||
|
* @param id id to be given to thread
|
||||||
|
*
|
||||||
|
* @return the initialized thread
|
||||||
|
*/
|
||||||
|
thread_t* thread_init(thpool_t* thpool, thread_t* thread, int id);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
static void* thread_do(thread_t* thread);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the calling thread on hold until threads_on_hold is set to 1
|
||||||
|
* @param nothing
|
||||||
|
* @return nothing
|
||||||
|
*/
|
||||||
|
static void thread_hold();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ----------------------- Queue specific --------------------------- */
|
/* ----------------------- Queue specific --------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
@ -219,6 +267,8 @@ static void jobqueue_clear(thpool_t* thpool);
|
||||||
* before passed to this function or else other functions like jobqueue_empty()
|
* before passed to this function or else other functions like jobqueue_empty()
|
||||||
* will be broken.
|
* will be broken.
|
||||||
*
|
*
|
||||||
|
* MUST HOLD MUTEX WHEN CALLING
|
||||||
|
*
|
||||||
* @param pointer to threadpool
|
* @param pointer to threadpool
|
||||||
* @param pointer to the new job(MUST BE ALLOCATED)
|
* @param pointer to the new job(MUST BE ALLOCATED)
|
||||||
* @return nothing
|
* @return nothing
|
||||||
|
@ -232,6 +282,8 @@ static void jobqueue_push(thpool_t* thpool, job_t* newjob);
|
||||||
* This does not free allocated memory so be sure to have peeked() \n
|
* This does not free allocated memory so be sure to have peeked() \n
|
||||||
* before invoking this as else there will result lost memory pointers.
|
* before invoking this as else there will result lost memory pointers.
|
||||||
*
|
*
|
||||||
|
* MUST HOLD MUTEX WHEN CALLING
|
||||||
|
*
|
||||||
* @param pointer to threadpool
|
* @param pointer to threadpool
|
||||||
* @return point to job on success,
|
* @return point to job on success,
|
||||||
* NULL if there is no job in queue
|
* NULL if there is no job in queue
|
||||||
|
@ -251,11 +303,44 @@ static job_t* jobqueue_pull(thpool_t* thpool);
|
||||||
static void jobqueue_destroy(thpool_t* thpool);
|
static void jobqueue_destroy(thpool_t* thpool);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binary semaphore
|
|
||||||
*
|
|
||||||
|
/* ======================== SYNCHRONISATION ========================= */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inits semaphore to given value
|
||||||
|
* @param binary semaphore
|
||||||
|
* @param value 1 or 0
|
||||||
|
* */
|
||||||
|
static void bsem_init(bsem_t *bsem, int value);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets semaphore to 0
|
||||||
|
* @param binary semaphore
|
||||||
|
* */
|
||||||
|
static void bsem_reset(bsem_t *bsem);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets semaphore to one and notifies at least one thread
|
||||||
|
* @param binary semaphore
|
||||||
* */
|
* */
|
||||||
static void bsem_post(bsem_t *bsem);
|
static void bsem_post(bsem_t *bsem);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets semaphore to one and notifies all threads
|
||||||
|
* @param binary semaphore
|
||||||
|
* */
|
||||||
|
static void bsem_post_all(bsem_t *bsem);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Waits on semaphore until semaphore has value 0
|
||||||
|
* @param binary semaphore
|
||||||
|
* */
|
||||||
static void bsem_wait(bsem_t *bsem);
|
static void bsem_wait(bsem_t *bsem);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue