unix, windows: make uv_barrier_wait() return bool

Make uv_barrier_wait() return a boolean value indicating whether this
thread was the "serializer".

From `man pthread_barrier_wait`:

    Upon successful completion, the pthread_barrier_wait() function
    shall return PTHREAD_BARRIER_SERIAL_THREAD for a single (arbitrary)
    thread synchronized at the barrier and zero for each of the other
    threads.

Exposing that information from libuv is useful because it can make
cleanup significantly easier:

    if (uv_barrier_wait(&barrier) > 0)
      uv_barrier_destroy(&barrier);

Signed-off-by: Fedor Indutny <fedor@indutny.com>
This commit is contained in:
Ben Noordhuis 2014-06-02 14:39:40 +02:00 committed by Fedor Indutny
parent eee4776549
commit 91985d48f6
4 changed files with 27 additions and 10 deletions

View File

@ -2219,7 +2219,7 @@ UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex,
UV_EXTERN int uv_barrier_init(uv_barrier_t* barrier, unsigned int count);
UV_EXTERN void uv_barrier_destroy(uv_barrier_t* barrier);
UV_EXTERN void uv_barrier_wait(uv_barrier_t* barrier);
UV_EXTERN int uv_barrier_wait(uv_barrier_t* barrier);
/* Runs a function once and only once. Concurrent calls to uv_once() with the
* same guard will block all callers except one (it's unspecified which one).

View File

@ -399,7 +399,9 @@ void uv_barrier_destroy(uv_barrier_t* barrier) {
}
void uv_barrier_wait(uv_barrier_t* barrier) {
int uv_barrier_wait(uv_barrier_t* barrier) {
int serial_thread;
uv_mutex_lock(&barrier->mutex);
if (++barrier->count == barrier->n) {
uv_sem_wait(&barrier->turnstile2);
@ -411,7 +413,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
uv_sem_post(&barrier->turnstile1);
uv_mutex_lock(&barrier->mutex);
if (--barrier->count == 0) {
serial_thread = (--barrier->count == 0);
if (serial_thread) {
uv_sem_wait(&barrier->turnstile1);
uv_sem_post(&barrier->turnstile2);
}
@ -419,6 +422,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
uv_sem_wait(&barrier->turnstile2);
uv_sem_post(&barrier->turnstile2);
return serial_thread;
}
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
@ -434,10 +438,11 @@ void uv_barrier_destroy(uv_barrier_t* barrier) {
}
void uv_barrier_wait(uv_barrier_t* barrier) {
int uv_barrier_wait(uv_barrier_t* barrier) {
int r = pthread_barrier_wait(barrier);
if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
abort();
return r == PTHREAD_BARRIER_SERIAL_THREAD;
}
#endif /* defined(__APPLE__) && defined(__MACH__) */

View File

@ -660,7 +660,9 @@ void uv_barrier_destroy(uv_barrier_t* barrier) {
}
void uv_barrier_wait(uv_barrier_t* barrier) {
int uv_barrier_wait(uv_barrier_t* barrier) {
int serial_thread;
uv_mutex_lock(&barrier->mutex);
if (++barrier->count == barrier->n) {
uv_sem_wait(&barrier->turnstile2);
@ -672,7 +674,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
uv_sem_post(&barrier->turnstile1);
uv_mutex_lock(&barrier->mutex);
if (--barrier->count == 0) {
serial_thread = (--barrier->count == 0);
if (serial_thread) {
uv_sem_wait(&barrier->turnstile1);
uv_sem_post(&barrier->turnstile2);
}
@ -680,6 +683,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
uv_sem_wait(&barrier->turnstile2);
uv_sem_post(&barrier->turnstile2);
return serial_thread;
}

View File

@ -29,6 +29,8 @@ typedef struct {
uv_barrier_t barrier;
int delay;
volatile int posted;
int main_barrier_wait_rval;
int worker_barrier_wait_rval;
} worker_config;
@ -38,7 +40,7 @@ static void worker(void* arg) {
if (c->delay)
uv_sleep(c->delay);
uv_barrier_wait(&c->barrier);
c->worker_barrier_wait_rval = uv_barrier_wait(&c->barrier);
}
@ -52,11 +54,13 @@ TEST_IMPL(barrier_1) {
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
uv_sleep(100);
uv_barrier_wait(&wc.barrier);
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
ASSERT(0 == uv_thread_join(&thread));
uv_barrier_destroy(&wc.barrier);
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
}
@ -71,11 +75,13 @@ TEST_IMPL(barrier_2) {
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
uv_barrier_wait(&wc.barrier);
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
ASSERT(0 == uv_thread_join(&thread));
uv_barrier_destroy(&wc.barrier);
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
}
@ -89,10 +95,12 @@ TEST_IMPL(barrier_3) {
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
uv_barrier_wait(&wc.barrier);
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
ASSERT(0 == uv_thread_join(&thread));
uv_barrier_destroy(&wc.barrier);
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
return 0;
}