2011-10-19 36 views
0

我正在从头开始创建一个线程池作为赋值的一部分,并且能够创建线程池,然后将每个创建的线程传递一个不断循环的函数。我的问题是我如何接受输入并将它传递给正在执行的pthread。在弄清楚这一点之后,我将添加互斥锁来将函数锁定到特定的线程,但我无法进入该部分。Pthread传递函数池

class ThreadPool{ 
public: 
    ThreadPool(size_t threadCount); 
    int dispatch_thread(void *(dispatch_function(void *)), void *arg); 
    bool thread_avail(); 
    int numThreads; 
    pthread_t * thread; 
    pthread_mutex_t * mutexes; 
}; 


int ThreadPool::dispatch_thread(void *(dispatch_function(void *)), void *arg){ 

    flag = 1; 
//This is where I would like to pass the function the running pthread 
} 

void *BusyWork(void *t) 
{ 
    while(true){ 
    //This is where I would like to run the passed function from each thread 
    //I can run the passed function by itself, but need to pass it to the threadpool 
    } 
} 

ThreadPool::ThreadPool(size_t threadCount){ 
pthread_t thread[threadCount]; 

for(t=0; t<threadCount; t++) { 
//printf("Main: creating thread %ld\n", t); 
rc = pthread_create(&thread[t], NULL, BusyWork, (void *)t); 
} 
} 

void *test_fn(void *par) 
{ 
    cout << "in test_fn " << *(int *)par << endl; 
} 

int main(){ 
    ThreadPool th(3); 
    int max = 100; 

    for (int i = 0; i < 20; i++) { 
    max = 100 * i; 
    th.dispatch_thread(test_fn, (void *)&max); 
    sleep(1); 
    } 
} 
+0

共享数据+(互斥量,条件变量)应该这样做 – sehe

+0

我同意,我只是不知道传递dispatch_thread函数的void *(dispatch_function(void *)),void * arg)参数的正确方法作为条件变量或全局声明的方式。我不知道是否有某种基于语法的方法来执行此操作,或者是否有可用的全新选项。 – patemotter

回答

2

我能想到的最佳模式是使用某种队列将消息传递给线程池。这些消息可能包含要运行的函数以及用于关闭线程池的一些控制消息。正如你已经猜到的,队列必须是线程安全的。

该队列的一个简单方法是使用一个固定大小的数组,您可以将它变成循环缓冲区。该数组在访问数组时会有一个Mutex来锁定它,并使用一个Condition Variable来唤醒线程池线程。

将项目放在队列中时,我们锁定互斥锁,添加到队列中,然后用条件变量向线程池发送信号。

线程池中的每个正在运行的线程将通过锁定互斥锁并等待条件变化(自动解锁互斥锁)来启动生命。唤醒时,它将从队列中移除项目,然后解锁互斥锁。它现在免费做它的东西。完成后,它会进入休眠状态,直到重新发信号。

作为一般建议,避免在线程之间共享内存,因为这会导致竞争条件(如果访问未受保护)或导致互锁(如果访问被锁定)。还要避免在执行任何长时间运行操作(如调用new(malloc),delete(free)或任何系统调用)时锁定互斥锁。

+0

因此,如果我按照您的描述使用排队方法,我会创建一个包含函数名称以及传递给它的参数的结构。如果是这样,那么将从dispatch_function中提取该信息的方法是什么。我在提取函数名称时遇到了困难。 – patemotter

+0

该队列将包含条目(这将是一个结构)。一个非常简单的想法是结构包含一个签名void fn(void *)的函数点。用void *的第二个参数。或者,您可以传递包含函数void run()的对象。皮肤有很多种方法去皮肤。 – doron

+0

这就是我在阅读你的评论前最终做了什么。感谢您的帮助。 – patemotter