ThreadPool.h
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <stdbool.h>
#include <pthread.h>
struct ThreadJob
{
void* (*CallbackFunction)(void *arg); // 线程回调函数
void * Arg; // 回调函数参数
struct ThreadJob * Next;
};
typedef struct
{
int ThreadCount; // 线程池中开启线程的个数
int QueueMaxCount; // 队列中最大ThreadJob的个数
struct ThreadJob * JobQueueHead; // 指向ThreadJob的头指针
struct ThreadJob * JobQueueTail; // 指向ThreadJob的尾指针
pthread_t * Threads; // 线程池中所有线程的pthread_t
pthread_mutex_t Mutex; // 互斥信号量
pthread_cond_t QueueEmptyCond; // 队列为空的条件变量
pthread_cond_t QueueNotEmptyCond; // 队列不为空的条件变量
pthread_cond_t QueueNotFullCond; // 队列不为满的条件变量
int QueueCount; // 队列当前的ThreadJob个数
bool IsQueueClosed; // 队列是否已经关闭
bool IsPoolClosed; // 线程池是否已经关闭
} ThreadPool;
/*
* Function: ThreadPool_Init
* Description: 初始化线程池。
* Arguments:
* @threadCount: 线程池大小。
* @queueMaxCount: 线程池队列大小。
* Return: 指向线程池的指针。
*/
ThreadPool * ThreadPool_Init(int threadCount, int queueMaxCount);
/*
* Function: ThreadPool_AddJob
* Description: 向线程池添加任务。
* Arguments:
* @threadPool: 指向线程池的指针。
* @callbackFunction: 线程回调函数。
* @arg: 回调函数参数。
* Return: null。
*/
void ThreadPool_AddJob(ThreadPool * threadPool, void * (*callbackFunction)(void * arg), void * arg);
/*
* Function: ThreadPool_Destroy
* Description: 销毁线程池。
* Arguments:
* @threadPool: 指向线程池的指针。
* Return: null。
*/
void ThreadPool_Destroy(ThreadPool * threadPool);
#endif
ThreadPool.c
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "ThreadPool.h"
static void * _function(void * arg)
{
if(!arg)
{
fprintf(stderr, "[_function()] Argument 'arg' is invalid");
exit(EXIT_FAILURE);
}
ThreadPool * threadPool = (ThreadPool *)arg;
struct ThreadJob *threadJob = NULL;
while (true)
{
pthread_mutex_lock(&(threadPool->Mutex));
//队列为空时,就等待队列非空
while (threadPool->QueueCount == 0 && !threadPool->IsPoolClosed)
pthread_cond_wait(&(threadPool->QueueNotEmptyCond), &(threadPool->Mutex));
//线程池关闭
if (threadPool->IsPoolClosed)
{
pthread_mutex_unlock(&(threadPool->Mutex));
pthread_exit(NULL);
}
threadPool->QueueCount--;
threadJob = threadPool->JobQueueHead;
if (threadPool->QueueCount == 0)
{
threadPool->JobQueueHead = NULL;
threadPool->JobQueueTail = NULL;
}
else
threadPool->JobQueueHead = threadJob->Next;
// 若队列为空,就可以通知ThreadPool_Destroy函数,销毁线程函数
if (threadPool->QueueCount == 0)
pthread_cond_signal(&(threadPool->QueueEmptyCond));
// 队列非满,就可以通知ThreadPool_AddJob函数,添加新任务
if (threadPool->QueueCount == threadPool->QueueMaxCount - 1)
pthread_cond_broadcast(&(threadPool->QueueNotFullCond));
pthread_mutex_unlock(&(threadPool->Mutex));
// 线程真正要做的任务,回调函数的调用
(*(threadJob->CallbackFunction))(threadJob->Arg);
free(threadJob);
}
}
ThreadPool * ThreadPool_Init(int threadCount, int queueMaxCount)
{
ThreadPool * threadPool = NULL;
threadPool = malloc(sizeof(ThreadPool));
if (!threadPool)
{
perror("[ThreadPool_Init()] malloc");
exit(EXIT_FAILURE);
}
threadPool->ThreadCount = threadCount;
threadPool->QueueMaxCount = queueMaxCount;
threadPool->QueueCount = 0;
threadPool->JobQueueHead = NULL;
threadPool->JobQueueTail = NULL;
if (pthread_mutex_init(&(threadPool->Mutex), NULL))
{
perror("[ThreadPool_Init()] pthread_mutex_init");
exit(EXIT_FAILURE);
}
if (pthread_cond_init(&(threadPool->QueueEmptyCond), NULL))
{
perror("[ThreadPool_Init()] pthread_mutex_init");
exit(EXIT_FAILURE);
}
if (pthread_cond_init(&(threadPool->QueueNotEmptyCond), NULL))
{
perror("[ThreadPool_Init()] pthread_cond_init");
exit(EXIT_FAILURE);
}
if (pthread_cond_init(&(threadPool->QueueNotFullCond), NULL))
{
perror("[ThreadPool_Init()] pthread_cond_init");
exit(EXIT_FAILURE);
}
threadPool->Threads = malloc(sizeof(pthread_t) * threadCount);
if (!threadPool->Threads)
{
perror("[ThreadPool_Init()] malloc");
exit(EXIT_FAILURE);
}
threadPool->IsQueueClosed = false;
threadPool->IsPoolClosed = false;
for (int i = 0; i < threadPool->ThreadCount; ++i)
pthread_create(&(threadPool->Threads[i]), NULL, _function, threadPool);
return threadPool;
}
void ThreadPool_AddJob(ThreadPool * threadPool, void * (*callbackFunction)(void * arg), void * arg)
{
if(!threadPool)
{
fprintf(stderr, "[ThreadPool_AddJob()] Argument 'threadPool' is invalid");
exit(EXIT_FAILURE);
}
if(!callbackFunction)
{
fprintf(stderr, "[ThreadPool_AddJob()] Argument 'callbackFunction' is invalid");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&(threadPool->Mutex));
// 队列满的时候就等待
while (threadPool->QueueCount == threadPool->QueueMaxCount
&& !(threadPool->IsQueueClosed || threadPool->IsPoolClosed))
pthread_cond_wait(&(threadPool->QueueNotFullCond), &(threadPool->Mutex));
// 队列关闭或者线程池关闭就退出
if (threadPool->IsQueueClosed || threadPool->IsPoolClosed)
{
fprintf(stderr, "[ThreadPool_AddJob()] ThreadPool or Queue has been closed");
exit(EXIT_FAILURE);
}
struct ThreadJob * threadJob = malloc(sizeof(struct ThreadJob));
if (!threadJob)
{
perror("[ThreadPool_AddJob()] malloc");
exit(EXIT_FAILURE);
}
threadJob->CallbackFunction = callbackFunction;
threadJob->Arg = arg;
threadJob->Next = NULL;
if (threadPool->JobQueueHead == NULL)
{
threadPool->JobQueueHead = threadJob;
threadPool->JobQueueTail = threadJob;
// 队列空的时候,有任务来时就通知线程池中的线程:队列非空
pthread_cond_broadcast(&(threadPool->QueueNotEmptyCond));
}
else
{
threadPool->JobQueueTail->Next = threadJob;
threadPool->JobQueueTail = threadJob;
}
threadPool->QueueCount++;
pthread_mutex_unlock(&(threadPool->Mutex));
}
void ThreadPool_Destroy(ThreadPool * threadPool)
{
if(!threadPool)
{
fprintf(stderr, "[ThreadPool_AddJob()] Argument 'threadPool' is invalid");
exit(EXIT_FAILURE);
}
pthread_mutex_lock(&(threadPool->Mutex));
// 若线程池或队列已经关闭,则说明已发生内部错误
if (threadPool->IsQueueClosed || threadPool->IsPoolClosed)
{
fprintf(stderr, "[ThreadPool_Destroy()] ThreadPool or Queue has been closed");
exit(EXIT_FAILURE);
}
// 设置队列关闭
threadPool->IsQueueClosed = true;
// 等待队列为空
while (threadPool->QueueCount != 0)
pthread_cond_wait(&(threadPool->QueueEmptyCond), &(threadPool->Mutex));
// 设置线程池关闭
threadPool->IsPoolClosed = true;
pthread_mutex_unlock(&(threadPool->Mutex));
// 唤醒线程池中正在阻塞的线程
pthread_cond_broadcast(&(threadPool->QueueNotEmptyCond));
//唤醒添加任务的ThreadPool_AddJob函数
pthread_cond_broadcast(&(threadPool->QueueNotFullCond));
// 等待线程池的所有线程执行完毕
for (int i = 0; i < threadPool->ThreadCount; ++i)
pthread_join(threadPool->Threads[i], NULL);
/* 清理相关资源 */
pthread_mutex_destroy(&(threadPool->Mutex));
pthread_cond_destroy(&(threadPool->QueueEmptyCond));
pthread_cond_destroy(&(threadPool->QueueNotEmptyCond));
pthread_cond_destroy(&(threadPool->QueueNotFullCond));
free(threadPool->Threads);
struct ThreadJob * p = NULL;
while (threadPool->JobQueueHead != NULL)
{
p = threadPool->JobQueueHead;
threadPool->JobQueueHead = p->Next;
free(p);
}
free(threadPool);
}