LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1325|回复: 4

阻塞在条件变量上的线程处理函数唤醒疑问

[复制链接]
发表于 2007-7-18 17:04:12 | 显示全部楼层 |阅读模式
这段时间在看线程池的一些东西,在网上搜索到一个程序是创建可动态调整线程数目的线程池实现。

其中有两个函数:
/*真正的线程处理函数,阻塞在cond上 */
static void *tp_work_thread(void *pthread)

/*外部处理函数接口,使线程处理函数对外部透明 */
void tp_process_job(tp_thread_pool *this, tp_work *worker, tp_work_desc *job)

线程处理函数tp_work_thread会调用tp_process_job

我的问题是,线程处理函数tp_work_thread是阻塞在调用tp_process_job之前的条件变量上的,当条件不满足时应该是不会调用tp_process_job的吧,那么这个线程处理函数是通过什么唤醒的;另外,tp_process_job有唤醒条件变量的函数,难道用tp_process_job的唤醒函数能够唤醒tp_work_thread的吗?
这两个函数之间的逻辑关系到底是怎样的,我很糊涂,请大家帮忙指点一下,谢谢。

两个函数的源代码分别为:
/**
  * member function reality. main interface opened.
  * after getting own worker and job, user may use the function to process the task.
  * para:
  *     this: thread pool struct instance ponter
  * worker: user task reality.
  * job: user task para
  * return:
  */
void tp_process_job(tp_thread_pool *this, tp_work *worker, tp_work_desc *job){
    int i;
    int tmpid;

    //fill this->thread_info's relative work key
    for(i=0;i<this->cur_th_num;i++){
        pthread_mutex_lock(&this->thread_info.thread_lock);
        if(!this->thread_info.is_busy){
            printf("tp_process_job: %d thread idle, thread id is %d\n", i, this->thread_info.thread_id);
            //thread state be set busy before work
            this->thread_info.is_busy = TRUE;
            pthread_mutex_unlock(&this->thread_info.thread_lock);

            this->thread_info.th_work = worker;
            this->thread_info.th_job = job;

            printf("tp_process_job: informing idle working thread %d, thread id is %d\n", i, this->thread_info.thread_id);
            pthread_cond_signal(&this->thread_info.thread_cond);

            return;
        }
        else
            pthread_mutex_unlock(&this->thread_info.thread_lock);
    }//end of for

    //if all current thread are busy, new thread is created here
    pthread_mutex_lock(&this->tp_lock);
    if( this->add_thread(this) ){
        i = this->cur_th_num - 1;
        tmpid = this->thread_info.thread_id;
        this->thread_info.th_work = worker;
        this->thread_info.th_job = job;
    }
    pthread_mutex_unlock(&this->tp_lock);

    //send cond to work thread
    printf("tp_process_job: informing idle working thread %d, thread id is %d\n", i, this->thread_info.thread_id);
    pthread_cond_signal(&this->thread_info.thread_cond);
    return;
}



/**
  * internal interface. real work thread.
  * para:
  *     pthread: thread pool struct ponter
  * return:
  */
static void *tp_work_thread(void *pthread){
    pthread_t curid;//current thread id
    int nseq;//current thread seq in the this->thread_info array
    tp_thread_pool *this = (tp_thread_pool*)pthread;//main thread pool struct instance

    //get current thread id
    curid = pthread_self();

    //get current thread's seq in the thread info struct array.
    nseq = this->get_thread_by_id(this, curid);
    if(nseq < 0)
        return;
    printf("entering working thread %d, thread id is %d\n", nseq, curid);

    //wait cond for processing real job.
    while( TRUE ){
        pthread_mutex_lock(&this->thread_info[nseq].thread_lock);
        pthread_cond_wait(&this->thread_info[nseq].thread_cond, &this->thread_info[nseq].thread_lock);
        pthread_mutex_unlock(&this->thread_info[nseq].thread_lock);

        printf("%d thread do work!\n", pthread_self());

        tp_work *work = this->thread_info[nseq].th_work;
        tp_work_desc *job = this->thread_info[nseq].th_job;

        //process
        work->process_job(work, job);

        //thread state be set idle after work
        pthread_mutex_lock(&this->thread_info[nseq].thread_lock);
        this->thread_info[nseq].is_busy = FALSE;
        pthread_mutex_unlock(&this->thread_info[nseq].thread_lock);

        printf("%d do work over\n", pthread_self());
    }
}
发表于 2007-7-18 23:15:12 | 显示全部楼层
[
线程处理函数tp_work_thread会调用tp_process_job
哪里写的?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-19 12:10:18 | 显示全部楼层
tp_work_thread不是有一句work->process_job(work, job);吗?
我忘说了,头文件里他是用函数指针定义了一个函数指针抽象,process_job和tp_process_job是一样的。

这里我把整个文件发到附件吧,可以全局的看一下,看是不是哪里我还有理解错误。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2007-7-19 20:05:51 | 显示全部楼层
可能楼主有点混淆了,tp_process_job是线程池的成员函数,而线程的th_work->process_job是需要开发人员自己定义的一个外部处理函数

我说一下使用流程,因为以前也没接触过线程池,所以咱们一起研究一下:

首先要创建一个线程池,初始化成员变量和函数:

然后初始化线程池,创建min_th_num个线程;

需要注意的是,在每一次调用pthread_create的时候,被创建的线程就立即去执行tp_work_thread了,在这个函数中,在每一次执行pthread_cond_wait时,被加入到条件变量的等待队列中休眠,直到线程池的成员函数tp_process_job发来一个pthread_cond_signal后,再执行开发人员指定的线程处理例程,然后又会被加入到条件变量的等待队列中休眠,如此直到被KILL掉
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-7-19 20:26:53 | 显示全部楼层
嗯,这个流程我大概是清楚的

谢谢wawxdyy兄的提醒,我刚刚又看了一下代码,还是不仔细的问题,我把头文件中
struct tp_work_s {
    void (*process_job)(tp_work *this, tp_work_desc *job);
}



struct tp_thread_pool_s {
    void (*process_job)(tp_thread_pool *this, tp_work *worker, tp_work_desc *job);
}

两个弄混了,把它们认为是一个函数了,tp_work_s结构体中的process_job是需要用户自己定义的,在这个库中并没有实现是吧。

看来连续几天熬夜还是不行的,这都能弄混了,呵呵,多谢wawxdyy兄的指点了,我太菜了,以后有问题还请多多帮助。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表