加入收藏 | 设为首页 | 会员中心 | 我要投稿 52站长网 (https://www.52zhanzhang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux线程池实现之改进

发布时间:2022-10-14 04:00:49 所属栏目:Linux 来源:网络
导读: 上一篇写到实现了一个线程池,但是那个线程池的任务回调函数却用到了四个变量之多,自己又仔细思考了一下线程池linux,这样做只是为了把任务函数的参数传进行去而以,这样做真的是多此一举

上一篇写到实现了一个线程池,但是那个线程池的任务回调函数却用到了四个变量之多,自己又仔细思考了一下线程池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);
}

(编辑:52站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!