参考:https://www.cnblogs.com/yangang92/p/5485868.html
1.condition.h
#ifndef __CONDITION_H__
#define __CONDITION_H__
#include <pthread.h>
typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
}condition_t;
int condition_init(condition_t *cond);
int condition_lock(condition_t *cond);
int condition_unlock(condition_t *cond);
int condition_wait(condition_t *cond);
int condition_timedwait(condition_t *cond, const struct timespec *adstime);
int condition_signal(condition_t * cond);
int condition_broadcast(condition_t *cond);
int condition_destroy(condition_t *cond);
#endif
2.condition.c
#include "condition.h"
int condition_init(condition_t *cond)
{
int status=-1;
if((status = pthread_mutex_init(&cond->pmutex, NULL)))
{
return status;
}
if((status = pthread_cond_init(&cond->pcond, NULL)))
{
return status;
}
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond->pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond->pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond->pcond, &cond->pmutex);
}
int condition_timedwait(condition_t *cond, const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond, &cond->pmutex, abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond->pcond);
}
int condition_destroy(condition_t *cond)
{
int status=-1;
if((status = pthread_mutex_destroy(&cond->pmutex))){
return status;
}
// if(status = pthread_cond_destroy(&cond->pcond)){
if((status = pthread_cond_destroy(&cond->pcond))){
return status;
}
return 0;
}
3.threadpool.h
#ifndef __THREAD_POOL_H__
#define __THREAD_POOL_H__
#include "condition.h"
typedef struct task
{
void *(*run)(void *args);
void *arg;
struct task *next;
}task_t;
typedef struct threadpool
{
condition_t ready;
task_t *first;
task_t *last;
int counter;
int idle;
int max_threads;
int quit;
}threadpool_t;
void threadpool_init(threadpool_t *pool, int threads);
void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg);
void threadpool_destroy(threadpool_t *pool);
#endif
4.threadpool.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
//#include <linux/posix_clock.h>
//#include <linux/time.h>
#include "threadpool.h"
void *thread_routine(void *arg)
{
struct timespec abstime;
struct timeval *time;
time = (struct timeval *)malloc(sizeof(struct timeval));
memset(time, 0, sizeof(struct timeval));
int timeout;
printf("thread %d is starting \n", (int)pthread_self());
threadpool_t *pool = (threadpool_t *)arg;
while(1){
timeout = 0;
condition_lock(&pool->ready);
pool->idle++;
while(pool->first == NULL && !pool->quit)
{
printf("thread %d is waitting \n", (int )pthread_self());
//clock_gettime(CLOCK_REALTIME, &abstime);
gettimeofday(time, NULL);
abstime.tv_sec = time->tv_sec + 2;
abstime.tv_nsec = 0;
int status=0;
status = condition_timedwait(&pool->ready, &abstime);
//status = condition_timedwait(&pool->ready, time);
if(status == ETIMEDOUT){
printf("thread %d wait timed out \n", (int)pthread_self());
timeout = 1;
break;
}
}
pool->idle--;
if(pool->first != NULL){
task_t *t = pool->first;
pool->first = t->next;
condition_unlock(&pool->ready);
t->run(t->arg);
free(t);
condition_lock(&pool->ready);
}
if(pool->quit && pool->first == NULL){
pool->counter--;
if(pool->counter == 0){
condition_signal(&pool->ready);
}
condition_unlock(&pool->ready);
break;
}
if(timeout == 1){
pool->counter--;
condition_unlock(&pool->ready);
break;
}
condition_unlock(&pool->ready);
}
printf("thread %d is exiting \n", (int)pthread_self());
return NULL;
}
void threadpool_init(threadpool_t *pool, int threads)
{
memset(pool, 0, sizeof(threadpool_t));
condition_init(&pool->ready);
pool->first = NULL;
pool->last = NULL;
pool->counter = 0;
pool->idle = 0;
pool->max_threads = threads;
pool->quit = 0;
}
void threadpool_add_task(threadpool_t *pool, void *(*run)(void *arg), void *arg)
{
task_t *newtask = (task_t *)malloc(sizeof(task_t));
newtask->run = run;
newtask->arg = arg;
newtask->next = NULL;
condition_lock(&pool->ready);
if(pool->first == NULL){
pool->first = newtask;
}else{
pool->last->next = newtask;
}
pool->last = newtask;
if( pool->idle > 0 ){
condition_signal(&pool->ready);
}else if(pool->counter < pool->max_threads){
pthread_t tid;
pthread_create(&tid, NULL, thread_routine, pool);
pool->counter++;
}
condition_unlock(&pool->ready);
}
void threadpool_destroy(threadpool_t *pool)
{
if(pool->quit){
return;
}
condition_lock(&pool->ready);
pool->quit = 1;
if(pool->counter > 0){
if(pool->idle > 0){
condition_broadcast(&pool->ready);
}
while(pool->counter)
{
condition_wait(&pool->ready);
}
condition_unlock(&pool->ready);
condition_destroy(&pool->ready);
}
}
5.main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "condition.h"
#include "threadpool.h"
void *mytask(void *arg)
{
printf("thread %d is working on task %d \n", (int)pthread_self(), *(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main(int argc, char *argv[])
{
threadpool_t pool;
threadpool_init(&pool, 3);
int i=-1;
// sleep(5);
for(i=0; i<10; i++){
int *arg = malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool, mytask, arg);
}
threadpool_destroy(&pool);
return 0;
}