7

我试图弄清楚如何摆脱对 pthread_timedjoin_np 的依赖,因为我正在尝试在 OSX 上构建一些代码。

现在我有一个线程队列,我从中弹出,执行 pthread_timedjoin_np,如果它们不返回,它们会被推回队列。

为每个线程调用的 thread_function 的末尾执行 pthread_exit(0); 以便接收线程可以检查返回值是否为零。

我想我可能会尝试使用 pthread_cond_timedwait() 来达到类似的效果,但是我认为我错过了一步。

我想我可以让工作线程 A 发出一个条件信号,并且在互斥体中使用 pthread_exit(),然后工作线程 B 可以在信号上唤醒,然后是 pthread_join()。问题是,线程 B 不知道哪个线程抛出了条件信号。我是否需要明确地将其作为条件信号的一部分传递或什么?

谢谢

德里克

4

3 回答 3

6

这是一个可移植的实现pthread_timedjoin_np。这有点贵,但它是一个完整的替代品:

struct args {
    int joined;
    pthread_t td;
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    void **res;
};

static void *waiter(void *ap)
{
    struct args *args = ap;
    pthread_join(args->td, args->res);
    pthread_mutex_lock(&args->mtx);
    args->joined = 1;
    pthread_mutex_unlock(&args->mtx);
    pthread_cond_signal(&args->cond);
    return 0;
}

int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *ts)
{
    pthread_t tmp;
    int ret;
    struct args args = { .td = td, .res = res };

    pthread_mutex_init(&args.mtx, 0);
    pthread_cond_init(&args.cond, 0);
    pthread_mutex_lock(&args.mtx);

    ret = pthread_create(&tmp, 0, waiter, &args);
    if (!ret)
            do ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts);
        while (!args.joined && ret != ETIMEDOUT);

    pthread_mutex_unlock(&args.mtx);

    pthread_cancel(tmp);
    pthread_join(tmp, 0);

    pthread_cond_destroy(&args.cond);
    pthread_mutex_destroy(&args.mtx);

    return args.joined ? 0 : ret;
}

由于我是在现场写的并且没有测试它,所以可能会有一些小错误,但是这个概念是合理的。

于 2012-07-19T00:18:46.150 回答
2

生产者-消费者队列。让线程在它们退出之前将它们自己排队,以及它们的结果(如果有的话)到队列中。排队等候。

没有轮询,没有延迟。

对于您当前的设计,您必须 join() 返回的线程获取 valueptr 并确保它们被销毁。

也许您有时可以转移到一个真正的线程池,其中任务项排队到永不终止的线程(因此消除了线程创建/终止/销毁开销)?

于 2012-07-19T06:11:30.707 回答
0

解决方案alarm

pthread 应该启用取消,因此它可以通过外部停止。(即使使用pthread_timedjoin_np)。

pthread_timedjoin_npETIMEOUT等待时间后返回。

  1. 设置alarm,使用alarm也可以给出“TIMEOUT”信号。
  2. 在处理程序中,只是pthread_cancel它。(只有超时运行这个)。
  3. pthread_join它在主线程中。
  4. 重置alarm

我在这里写测试代码:github

于 2015-10-25T01:49:14.193 回答