基于lnux的线程池实现目录拷贝

一、实现原理

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;
}

你可能感兴趣的:(基于lnux的线程池实现目录拷贝)