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:
parent
eee4776549
commit
91985d48f6
@ -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).
|
||||
|
||||
@ -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__) */
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user