上一篇写到实现了一个线程池,但是那个线程池的任务回调函数却用到了四个变量之多,自己又仔细思考了一下线程池linux,这样做只是为了把任务函数的参数传进行去而以,这样做真的是多此一举,既然参数据设定为void *类型的,那就完全可以传进行所有类型的参数,完全可以将参数组成一个结构体, 将结构体的指针传给回调函数。
改进代码如下:
ThreadWorker结构体改进
typedef struct worker{
void (*process)(void * arg);
void * arg;
struct worker *next;
} ThreadWorker;
AddWorker方法改进,只有一个参数:
void ThreadPool::AddWorker(void (*process)(void * ), void * arg)
{
ThreadWorker * new_worker = (ThreadWorker *)malloc(sizeof(ThreadWorker));
new_worker->process = process;
new_worker->arg = arg;
new_worker->next = NULL;
pthread_mutex_lock(&m_queueLock);
ThreadWorker * wk = m_workerHead;
if (wk == NULL)
{
m_workerHead = new_worker;
}else
{
while(wk->next != NULL)
wk = wk->next;
wk->next = new_worker;
}
assert(m_workerHead != NULL);
m_workerSize++;
pthread_mutex_unlock(&m_queueLock);
pthread_cond_signal(&m_queueReady);
return;
}
thread_loop函数中的改进:
void * ThreadPool::__thread_loop(void * arg)
{
......
(*(worker->process))(worker->arg);
free(worker);
worker = NULL;
}
return NULL;
}
调用示例:
#include
#include
#include
#include
void do_one_mesh(char * base, char * updated, char *input_name, char * output_path);
void do_in_thread_pool(void * args);
//参数结构体
typedef struct {
char * output_path;
const char * mesh_name;
Regions base_regions;
Regions updated_regions;
} ThreadWorkerArgs;
int main(int argc, char ** argv)
{
char * root_path = NULL;
char * updated = NULL;
char * base = NULL;
char * input_name = NULL;
char * output_path = NULL;
bool one_mesh = false;
int thread_num = 1;
int c;
while((c = getopt(argc, argv, "j::o::n::r::b::u::Oh")) != -1)
{
switch(c)
{
case 'j':
thread_num = atoi(optarg);
break;
case 'r':
root_path = optarg;
break;
case 'n':
input_name = optarg;
break;
case 'O':
one_mesh = true;
break;
case 'b':
base = optarg;
break;
case 'u':
updated = optarg;
break;
case 'o':
output_path = optarg;
break;
case 'h':
printf("参数说明:\n");
printf("-O后面不需要带参数,其他均需参数\n");
printf("参数一定要紧跟选项后面\n");
printf("例如:-b/home/data\n");
printf("-n: 数据文件名\n");
printf("-b: 基板版本号,如果带-O选项,那么就是基板数据所在的目录\n");
printf("-u: 差分版版本号,如果带-O选项,那么就是差分版数据所在的目录\n");
printf("-r: 数据根目录,当带-O选项是,该选项无用\n");
printf("-O: 带此选项为直接指定差分版与基板数据路径\n");
printf("-o: 需带参数,为结果输出目录\n");
return 0;
case '?':
fprintf(stderr, "please use [-O] [-n] [-b] [-u] -[i] options\n");
return -1;
break;
}
}
if (updated == NULL || base == NULL || input_name == NULL || output_path == NULL)
{
fprintf(stderr, "-n, -b, -o options can not be empty!\n");
return -1;
}
if (one_mesh)
{
do_one_mesh(base, updated, input_name, output_path);
}else
{
int base_version = 0;
int updated_version = 0;
if (root_path == NULL)
{
fprintf(stderr, "-b options can not be empty!\n");
return -1;
}
if ((base_version = atoi(base)) == 0)
{
fprintf(stderr, "-b options must be an integer!\n");
return -1;
}
if ((updated_version = atoi(updated)) == 0)
{
fprintf(stderr, "-u options must be an integer!\n");
return -1;
}
std::map base_paths, updated_paths;
AutoGetPreVersion(root_path, base_version, updated_version, base_paths, updated_paths);
MeshRegions base_mesh_regions, updated_mesh_regions;
LoadAll(input_name, base_paths, updated_paths, base_mesh_regions, updated_mesh_regions);
int mesh_num = updated_mesh_regions.size();
ThreadPool * pool = new ThreadPool(thread_num);
pool->ThreadPoolInit();
BOOST_FOREACH(MeshRegionsPair & pair, updated_mesh_regions)
{
ThreadWorkerArgs *arg = new ThreadWorkerArgs();
arg->mesh_name = pair.first.c_str();
arg->output_path = output_path;
arg->base_regions = base_mesh_regions[pair.first];
arg->updated_regions = pair.second;
pool->AddWorker(do_in_thread_pool, arg);
}
while (pool->GetWorkerNum() != 0)
{
double process = (mesh_num - pool->GetWorkerNum())/mesh_num * 100;
//printf("\rprocessing: %f%%", process);
sleep(1);
}
pool->ThreadPoolDestroy();
//printf("\rprocessing: 100%%\n");
return 0;
}
return 0;
}
void do_one_mesh(char * base, char * updated, char * input_name, char * output_path)
{
Regions base_regions;
Regions updated_regions;
Regions del;
Regions add;
LoadOne(base, updated, input_name, base_regions, updated_regions);
DoOneDiff(base_regions, updated_regions, add, del);
WriteOne(output_path, add, del);
}
//线程池任务回调函数,注意参数结构体的作用
void do_in_thread_pool(void * args)
{
ThreadWorkerArgs * wk_args = (ThreadWorkerArgs *)args;
const char * mesh_name = wk_args->mesh_name;
char * output_path = wk_args->output_path;
Regions base_regions = wk_args->base_regions;
Regions updated_regions = wk_args->updated_regions;
Regions add;
Regions del;
printf("now doing mesh: %s\n", mesh_name);
DoOneDiff(base_regions, updated_regions, add, del);
printf("now writing result\n");
WriteByMesh(output_path, mesh_name, add, del);
printf("mesh: %s has been done\n", mesh_name);
}
(编辑:成都站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|