我是一个有用的助手,可以翻译文本。
我有一个相当简单的线程池,关于线程结束我有一个问题。
这是我的工作代码片段:
static void* threadpool_worker(void* pool_instance)
{
int rc;
struct threadpool* pool = (struct threadpool*)pool_instance;
struct threadpool_task *task;
for(;;)
{
pthread_mutex_lock( &(pool->task_queue_mutex) );
while( pool->headp->tqh_first == NULL )
{
rc = pthread_cond_wait( &(pool->task_queue_cond), &(pool->task_queue_mutex) );
}
task = pool->headp->tqh_first;
TAILQ_REMOVE(pool->headp, pool->headp->tqh_first, entries);
pthread_mutex_unlock( &(pool->task_queue_mutex) );
task->routine_cb(task->data);
}
}
任务在这一行被执行:task->routine_cb(task->data);
为了结束工作线程,我以以下方式调用threadpool_enqueue_task:
for( i=0 ; i < pool->num_of_workers ; ++i)
{
threadpool_enqueue_task(pool, pthread_exit, NULL);
}
预计 pthread_exit 将在此处 task->routine_cb(task->data) 被调用,但事实并非如此。我没有看到任何明确的错误,只是在 valgrind 中出现了内存泄漏。
但是当我将工作线程代码更改为以下内容时:
if(task->routine_cb == pthread_exit)
{
pthread_exit(0);
}
task->routine_cb(task->data);
一切都很好结束了。我的问题是是否有一种选项可以停止工作者,只需以某种方式执行pthread_exit,而无需更改工作者代码。
编辑: 线程池任务声明如下:
struct threadpool_task
{
void (*routine_cb)(void*);
void *data;
TAILQ_ENTRY(threadpool_task) entries; /* List. */
}
据我的理解,在声明routine_cb时获取pthread_exit地址应该没有问题。
extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
pthread_exit()
中,记录它被调用了吗? - alk