Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

alternative to pthread_timedjoin_np

Tags:

c

macos

pthreads

I am trying to figure out how to get rid of a reliance on the pthread_timedjoin_np because I am trying to build some code on OSX.

Right now I have a Queue of threads that I am popping from, doing that pthread_timedjoin_np and if they dont return, they get pushed back on the queue.

The end of the thread_function that is called for each thread does a pthread_exit(0); so that the recieving thread can check for a return value of zero.

I thought i might try to use pthread_cond_timedwait() to achieve a similar effect, however I think i am missing a step.

I thought I would be able to make worker Thread A signal a condition AND pthread_exit() within a mutex, , and worker Thread B could wake up on the signal, and then pthread_join(). The problem is, Thread B doesn't know which thread threw the conditional signal. Do I need to explicitly pass that as part of the conditonal signal or what?

Thanks

Derek

like image 832
Derek Avatar asked Jul 18 '12 22:07

Derek


1 Answers

Here is a portable implementation of pthread_timedjoin_np. It's a bit costly, but it's a full drop-in replacement:

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;
}

There may be small errors since I wrote this on the spot and did not test it, but the concept is sound.

like image 126
R.. GitHub STOP HELPING ICE Avatar answered Oct 24 '22 19:10

R.. GitHub STOP HELPING ICE