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 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_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
|
/* 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).
|
* 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);
|
uv_mutex_lock(&barrier->mutex);
|
||||||
if (++barrier->count == barrier->n) {
|
if (++barrier->count == barrier->n) {
|
||||||
uv_sem_wait(&barrier->turnstile2);
|
uv_sem_wait(&barrier->turnstile2);
|
||||||
@ -411,7 +413,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
|
|||||||
uv_sem_post(&barrier->turnstile1);
|
uv_sem_post(&barrier->turnstile1);
|
||||||
|
|
||||||
uv_mutex_lock(&barrier->mutex);
|
uv_mutex_lock(&barrier->mutex);
|
||||||
if (--barrier->count == 0) {
|
serial_thread = (--barrier->count == 0);
|
||||||
|
if (serial_thread) {
|
||||||
uv_sem_wait(&barrier->turnstile1);
|
uv_sem_wait(&barrier->turnstile1);
|
||||||
uv_sem_post(&barrier->turnstile2);
|
uv_sem_post(&barrier->turnstile2);
|
||||||
}
|
}
|
||||||
@ -419,6 +422,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
|
|||||||
|
|
||||||
uv_sem_wait(&barrier->turnstile2);
|
uv_sem_wait(&barrier->turnstile2);
|
||||||
uv_sem_post(&barrier->turnstile2);
|
uv_sem_post(&barrier->turnstile2);
|
||||||
|
return serial_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !(defined(__APPLE__) && defined(__MACH__)) */
|
#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);
|
int r = pthread_barrier_wait(barrier);
|
||||||
if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
if (r && r != PTHREAD_BARRIER_SERIAL_THREAD)
|
||||||
abort();
|
abort();
|
||||||
|
return r == PTHREAD_BARRIER_SERIAL_THREAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(__APPLE__) && defined(__MACH__) */
|
#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);
|
uv_mutex_lock(&barrier->mutex);
|
||||||
if (++barrier->count == barrier->n) {
|
if (++barrier->count == barrier->n) {
|
||||||
uv_sem_wait(&barrier->turnstile2);
|
uv_sem_wait(&barrier->turnstile2);
|
||||||
@ -672,7 +674,8 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
|
|||||||
uv_sem_post(&barrier->turnstile1);
|
uv_sem_post(&barrier->turnstile1);
|
||||||
|
|
||||||
uv_mutex_lock(&barrier->mutex);
|
uv_mutex_lock(&barrier->mutex);
|
||||||
if (--barrier->count == 0) {
|
serial_thread = (--barrier->count == 0);
|
||||||
|
if (serial_thread) {
|
||||||
uv_sem_wait(&barrier->turnstile1);
|
uv_sem_wait(&barrier->turnstile1);
|
||||||
uv_sem_post(&barrier->turnstile2);
|
uv_sem_post(&barrier->turnstile2);
|
||||||
}
|
}
|
||||||
@ -680,6 +683,7 @@ void uv_barrier_wait(uv_barrier_t* barrier) {
|
|||||||
|
|
||||||
uv_sem_wait(&barrier->turnstile2);
|
uv_sem_wait(&barrier->turnstile2);
|
||||||
uv_sem_post(&barrier->turnstile2);
|
uv_sem_post(&barrier->turnstile2);
|
||||||
|
return serial_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -29,6 +29,8 @@ typedef struct {
|
|||||||
uv_barrier_t barrier;
|
uv_barrier_t barrier;
|
||||||
int delay;
|
int delay;
|
||||||
volatile int posted;
|
volatile int posted;
|
||||||
|
int main_barrier_wait_rval;
|
||||||
|
int worker_barrier_wait_rval;
|
||||||
} worker_config;
|
} worker_config;
|
||||||
|
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ static void worker(void* arg) {
|
|||||||
if (c->delay)
|
if (c->delay)
|
||||||
uv_sleep(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));
|
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
||||||
|
|
||||||
uv_sleep(100);
|
uv_sleep(100);
|
||||||
uv_barrier_wait(&wc.barrier);
|
wc.main_barrier_wait_rval = uv_barrier_wait(&wc.barrier);
|
||||||
|
|
||||||
ASSERT(0 == uv_thread_join(&thread));
|
ASSERT(0 == uv_thread_join(&thread));
|
||||||
uv_barrier_destroy(&wc.barrier);
|
uv_barrier_destroy(&wc.barrier);
|
||||||
|
|
||||||
|
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,11 +75,13 @@ TEST_IMPL(barrier_2) {
|
|||||||
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
||||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
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));
|
ASSERT(0 == uv_thread_join(&thread));
|
||||||
uv_barrier_destroy(&wc.barrier);
|
uv_barrier_destroy(&wc.barrier);
|
||||||
|
|
||||||
|
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +95,12 @@ TEST_IMPL(barrier_3) {
|
|||||||
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
ASSERT(0 == uv_barrier_init(&wc.barrier, 2));
|
||||||
ASSERT(0 == uv_thread_create(&thread, worker, &wc));
|
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));
|
ASSERT(0 == uv_thread_join(&thread));
|
||||||
uv_barrier_destroy(&wc.barrier);
|
uv_barrier_destroy(&wc.barrier);
|
||||||
|
|
||||||
|
ASSERT(1 == (wc.main_barrier_wait_rval ^ wc.worker_barrier_wait_rval));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user