一、实现原理
1.线程池:一个包括互斥锁、条件变量、任务链表、线程id集合、等待任务数目、线程数目、以及开关的结构体,
实现多个线程处理任务。对此结构体的操作包括初始化、投放任务、增加线程、销毁线程池等。
2.文件拷贝(任务):以系统IO函数:open、read、write、close实现对源文件的读取,对新建的目标文件的写入。
3.以递归方式遍历得到每个目录下的所有文件的路径,使用mkdir以及closedir函数创建新的目录,投放任务。
二、源代码
2.1线程池相关
#include "thread_pool.h"
/****线程取消例程****/
void handler(void *arg)
{
pthread_mutex_unlock((pthread_mutex_t *) arg);
}
/****线程执行函数(去完成任务)****/
void *func(void *arg)
{
thread_pool *pool = (thread_pool *)arg;
struct task *p;
while(1)
{
/*1.访问任务队列前加锁,并注册取消例程防止取消死锁*/
pthread_mutex_lock(&pool->lock);
pthread_cleanup_push(handler, (void *)&pool->lock);
/*2.如果任务队列没有任务而且线程池开关
打开,线程等待条件变量*/
if(pool->waiting_tasks == 0 && pool->shutdown == false)
{
pthread_cond_wait(&pool->cond, &pool->lock);
}
/*3.如果任务队列没有任务而且线程池开关关闭,
立即释放互斥锁并退出线程*/
if(pool->waiting_tasks == 0 && pool->shutdown == true)
{
pthread_mutex_unlock(&pool->lock);
pthread_exit(NULL);
}
/*4.如果任务队列存在任务,则取出任务*/
if(pool->waiting_tasks > 0)
{
p = pool->task_link->next;
pool->task_link->next = p->next;
pool -> waiting_tasks --;
}
/*5.释放互斥锁,并弹栈(不执行取消例程)*/
pthread_mutex_unlock(&pool->lock);
pthread_cleanup_pop(0);
/*6.执行取出的任务,期间不允许响应取消请求*/
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);//关闭取消请求
//测试printf("p->arg->src%s\n", ((struct file *)p->arg)->src);
(p->task)(p->arg);
//测试printf("\n copy %s success\n",((struct file *)p->arg)->src);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);//打开取消请求
free(p);
}
pthread_exit(NULL);
}
/****1.初始化线程池****/
bool init_pool(thread_pool *pool, unsigned int thread_num)
{
/*1.初始化互斥锁以及条件变量*/
pthread_cond_init(&pool->cond, NULL);
pthread_mutex_init(&pool->lock, NULL);
/*1.2动态分配任务链表头节点空间*/
pool->task_link = malloc(sizeof(struct task));
if(pool->task_link == NULL )
{
perror("task_link () malloc faild");
return false;
}
pool->task_link->next = NULL;
/*1.3动态分配所有线程id的存放空间*/
pool->tids = malloc(MAX_THREAD_NUM *sizeof(pthread_t));
/*1.4活跃线程个数以及等待任务个数赋初值*/
pool->waiting_tasks = 0;
pool->active_threads = thread_num;
/*1.5创建指定个数的线程*/
for(int i = 0; itids[i]), NULL, func, (void *)pool) != 0)
{
perror("pthread_create () faild");
return false;
}
}
/*1.5线程销毁开关为false*/
pool->shutdown = false;
return true;
}
/****2.投放任务****/
bool add_task(thread_pool *pool , void *(*task)(void *arg), void *arg)
{
//pthread_mutex_lock(&pool->lock);
/*2.1新建任务节点*/
struct task *new = malloc(sizeof(struct task));
if(new == NULL )
{
perror("malloc new_task ()faild");
return false;
}
new->task = task;
new->arg = arg;
new->next = NULL;
/*2.2将任务放至任务队列*/
/*2.2.1 加锁*/
pthread_mutex_lock(&pool->lock);
if(pool->waiting_tasks >= MAX_TASK_NUM)
{
pthread_mutex_unlock(&pool->lock);
fprintf(stderr, "too many task\n");
free(new);
return false;
}
struct task*tmp = pool->task_link;
while(tmp->next != NULL)
{
tmp = tmp->next;
}
tmp->next = new;
pool->waiting_tasks++;
/*2.3释放互斥锁唤醒阻塞在等待任务的一个线程*/
pthread_mutex_unlock(&pool->lock);
pthread_cond_signal(&pool->cond);
usleep(100000);
return true;
}
/****3.增加线程****/
int add_thread(thread_pool *pool, unsigned int num)
{
if(num ==0 )
return 0;
unsigned int total_num = pool->active_threads+num;
int actual_num = 0;//实际创建数目
/*3.1循环创建线程*/
for(int i = pool->active_threads; itids[i]), NULL, func, (void*)pool) != 0)
{
perror("pthread_create () faild");
if(actual_num == 0)
return 0;
break;
}
actual_num++;
}
pool->active_threads += actual_num;
return actual_num;
}
/****4.取消线程****/
int remove_thread(thread_pool *pool ,unsigned int rm_num)
{
if(rm_num == 0)
return pool->active_threads;
int remain_num = pool->active_threads - rm_num;//保留的线程数目
remain_num = remain_num>0 ? remain_num:1;
int i;
for( i = pool->active_threads; i>remain_num -1; --i)
{
errno = pthread_cancel(pool->tids[i]);
if(errno!=0)
break;
}
if(i == pool->active_threads -1)
return -1;
else
{
pool->active_threads = i+1;
return i+1;
}
}
/****5.删除线程池****/
bool destory_pool(thread_pool *pool)
{
pool->shutdown = true;
pthread_cond_broadcast(&pool->cond);
for( int i = 0;iactive_threads; ++i)
{
errno = pthread_join(pool->tids[i], NULL);
if(errno != 0)
{
printf("join tids[%d] error:%s\n", i, strerror(errno));
}
else
printf("[%u] is joined\n", (unsigned ) pool->tids[i]);
}
printf("%d thread exit suceess\n", pool->active_threads);
free(pool->task_link);
free(pool->tids);
free(pool);
return true;
}