void connection_consumer_start(void *arg) { int rc; struct server_ctx *ctx; uv_loop_t* loop; ctx = arg; loop = uv_loop_new(); listener_event_loops[ctx->index] = *loop; http_request_cache_configure_listener(loop, &listener_async_handles[ctx->index]); uv_barrier_wait(listeners_created_barrier); rc = uv_async_init(loop, &ctx->async_handle, connection_consumer_close); uv_unref((uv_handle_t*) &ctx->async_handle); /* Wait until the main thread is ready. */ uv_sem_wait(&ctx->semaphore); get_listen_handle(loop, (uv_stream_t*) &ctx->server_handle); uv_sem_post(&ctx->semaphore); rc = uv_listen((uv_stream_t*)&ctx->server_handle, 128, connection_consumer_new_connection); rc = uv_run(loop, UV_RUN_DEFAULT); uv_loop_delete(loop); }
static PyObject * Barrier_func_wait(Barrier *self) { RAISE_IF_NOT_INITIALIZED(self, NULL); Py_BEGIN_ALLOW_THREADS uv_barrier_wait(&self->uv_barrier); Py_END_ALLOW_THREADS Py_RETURN_NONE; }
static void thread_main(void* arg) { struct thread_ctx* ctx; char buf[4096]; ssize_t n; ctx = arg; uv_barrier_wait(&ctx->barrier); do n = read(ctx->fd, buf, sizeof(buf)); while (n > 0 || (n == -1 && errno == EINTR)); ASSERT(n == 0); }
void reader(void *n) { int num = *(int*)n; int i; for (i = 0; i < 20; ++i) { uv_rwlock_rdlock(&numlock); printf("Reader %d: acquired lock\n", num); printf("Reader %d: shared num = %d\n", num, shared_num); uv_rwlock_rdunlock(&numlock); printf("Reader %d: released lock\n", num); } uv_barrier_wait(&blocker); }
void writer(void *n) { int num = *(int*)n; int i; for (i = 0; i < 20; ++i) { uv_rwlock_wrlock(&numlock); printf("Writer %d: acquired lock\n", num); shared_num++; printf("Writer %d: incremented shared num = %d\n", num, shared_num); uv_rwlock_wrunlock(&numlock); printf("Writer %d: released lock\n", num); } uv_barrier_wait(&blocker); }
// https://github.com/thlorenz/libuv-dox/blob/master/methods.md#uv_rwlock_wrlock void writer_entry(void *n) { int r; int num = *(int*)n; for (int i = 0; i < ROUNDS; i++) { do { r = uv_rwlock_trywrlock(&numlock); // see: reader_entry if (r && r != -EBUSY && r != -EAGAIN) ERROR("obtaining write lock", r); } while(r); fprintf(stderr, "Writer %d: aquired lock\n", num); shared_num++; fprintf(stderr, "Writer %d: incremented shared num = %d\n", num, shared_num); uv_rwlock_wrunlock(&numlock); fprintf(stderr, "Writer %d: released lock\n", num); } uv_barrier_wait(&blocker); }
int main() { uv_thread_t threads[3]; int thread_nums[] = {1, 2, 1}; uv_barrier_init(&blocker, 4); shared_num = 0; uv_rwlock_init(&numlock); uv_thread_create(&threads[0], reader, &thread_nums[0]); uv_thread_create(&threads[1], reader, &thread_nums[1]); uv_thread_create(&threads[2], writer, &thread_nums[2]); uv_barrier_wait(&blocker); uv_barrier_destroy(&blocker); uv_rwlock_destroy(&numlock); return 0; }
// https://github.com/thlorenz/libuv-dox/blob/master/methods.md#uv_rwlock_rdlock void reader_entry(void *n) { int r; int num = *(int*)n; for (int i = 0; i < ROUNDS; i++) { do { r = uv_rwlock_tryrdlock(&numlock); // implementation ./src/unix/thread.c aborts the process unless return value was EBUSY or EAGAIN // so checking here again is redundant and mainly done for documentation // fact is that the only r we'd ever get would be EBUSY or EAGAIN (negated) if (r && r != -EBUSY && r != -EAGAIN) ERROR("obtaining read lock", r); } while(r); fprintf(stderr, "Reader %d: aquired lock and shared num = %d\n", num, shared_num); uv_rwlock_rdunlock(&numlock); fprintf(stderr, "Reader %d: released lock\n", num); } uv_barrier_wait(&blocker); }
// thread function: used by all except the main thread void jl_threadfun(void *arg) { jl_threadarg_t *targ = (jl_threadarg_t*)arg; // initialize this thread (set tid, create heap, set up root task) jl_init_threadtls(targ->tid); void *stack_lo, *stack_hi; jl_init_stack_limits(0, &stack_lo, &stack_hi); jl_init_root_task(stack_lo, stack_hi); jl_ptls_t ptls = jl_get_ptls_states(); jl_gc_state_set(ptls, JL_GC_STATE_SAFE, 0); uv_barrier_wait(targ->barrier); // free the thread argument here free(targ); (void)jl_gc_unsafe_enter(ptls); jl_current_task->exception = jl_nothing; jl_finish_task(jl_current_task, jl_nothing); // noreturn }
// same as ./10-locks, but using try* functions when obtaining read and write locks // int main() { int r; const int count = 4; fprintf(stderr, "barrier: init\n"); uv_barrier_init(&blocker, count); shared_num = 0; // https://github.com/thlorenz/libuv-dox/blob/master/methods.md#rwlock fprintf(stderr, "rwlock: init\n"); r = uv_rwlock_init(&numlock); if (r) ERROR("rwlock_init", r); uv_thread_t threads[3]; int thread_nums[] = { 1, 2, 1 }; r = uv_thread_create(&threads[0], reader_entry, &thread_nums[0]); if (r) ERROR("thread_create", r); r = uv_thread_create(&threads[1], reader_entry, &thread_nums[1]); if (r) ERROR("thread_create", r); r = uv_thread_create(&threads[2], writer_entry, &thread_nums[2]); if (r) ERROR("thread_create", r); // https://github.com/thlorenz/libuv-dox/blob/master/methods.md#barrier fprintf(stderr, "barrier: wait\n"); uv_barrier_wait(&blocker); fprintf(stderr, "barrier: destroy\n"); uv_barrier_destroy(&blocker); fprintf(stderr, "rwlock: destroy\n"); uv_rwlock_destroy(&numlock); if (r) ERROR("rwlock_destroy", r); return 0; }
static mrb_value mrb_uv_barrier_wait(mrb_state *mrb, mrb_value self) { uv_barrier_wait((uv_barrier_t*)mrb_uv_get_ptr(mrb, self, &barrier_type)); return self; }