fiber_manager_t* fiber_manager_create() { fiber_manager_t* const manager = calloc(1, sizeof(*manager)); if(!manager) { errno = ENOMEM; return NULL; } manager->thread_fiber = fiber_create_from_thread(); manager->current_fiber = manager->thread_fiber; manager->queue_one = wsd_work_stealing_deque_create(); manager->queue_two = wsd_work_stealing_deque_create(); manager->schedule_from = manager->queue_one; manager->store_to = manager->queue_two; manager->done_fibers = wsd_work_stealing_deque_create(); if(!manager->thread_fiber || !manager->queue_one || !manager->queue_two || !manager->done_fibers) { wsd_work_stealing_deque_destroy(manager->queue_one); wsd_work_stealing_deque_destroy(manager->queue_two); wsd_work_stealing_deque_destroy(manager->done_fibers); fiber_destroy(manager->thread_fiber); free(manager); return NULL; } return manager; }
int fiber_scheduler_wsd_init(fiber_scheduler_wsd_t* scheduler, size_t id) { assert(scheduler); scheduler->queue_one = wsd_work_stealing_deque_create(); scheduler->queue_two = wsd_work_stealing_deque_create(); scheduler->schedule_from = scheduler->queue_one; scheduler->store_to = scheduler->queue_two; scheduler->id = id; scheduler->steal_count = 0; scheduler->failed_steal_count = 0; if(!scheduler->queue_one || !scheduler->queue_two) { wsd_work_stealing_deque_destroy(scheduler->queue_one); wsd_work_stealing_deque_destroy(scheduler->queue_two); return 0; } return 1; }
int main(int argc, char* argv[]) { wsd_circular_array_t* wsd_a = wsd_circular_array_create(8); test_assert(wsd_a); test_assert(wsd_circular_array_size(wsd_a) == 256); wsd_circular_array_put(wsd_a, 1, (void*)1); test_assert((void*)1 == wsd_circular_array_get(wsd_a, 1)); wsd_circular_array_destroy(wsd_a); wsd_work_stealing_deque_t* wsd_d = wsd_work_stealing_deque_create(); int i; for(i = 0; i < 1000; ++i) { wsd_work_stealing_deque_push_bottom(wsd_d, (void*)(intptr_t)i); } for(i = 1000; i > 0; --i) { void* item = wsd_work_stealing_deque_pop_bottom(wsd_d); test_assert((intptr_t)item == i-1); } wsd_work_stealing_deque_destroy(wsd_d); wsd_d2 = wsd_work_stealing_deque_create(); pthread_t reader[NUM_THREADS]; for(i = 1; i < NUM_THREADS; ++i) { pthread_create(&reader[i], NULL, &run_func, (void*)(intptr_t)i); } for(i = 0; i < SHARED_COUNT; ++i) { wsd_work_stealing_deque_push_bottom(wsd_d2, (void*)(intptr_t)i); if((i & 7) == 0) { void* val = wsd_work_stealing_deque_pop_bottom(wsd_d2); if(val != WSD_EMPTY && val != WSD_ABORT) { __sync_add_and_fetch(&results[0][(intptr_t)val], 1); __sync_add_and_fetch(&total, (intptr_t)val); ++run_func_count[0]; } } } void* val = 0; do { val = wsd_work_stealing_deque_pop_bottom(wsd_d2); if(val != WSD_EMPTY && val != WSD_ABORT) { __sync_add_and_fetch(&results[0][(intptr_t)val], 1); __sync_add_and_fetch(&total, (intptr_t)val); ++run_func_count[0]; } } while(val != WSD_EMPTY); done = 1; for(i = 1; i < NUM_THREADS; ++i) { pthread_join(reader[i], NULL); } uint64_t expected_total = 0; for(i = 0; i < SHARED_COUNT; ++i) { int sum = 0; int j; for(j = 0; j < NUM_THREADS; ++j) { sum += results[j][i]; } test_assert(sum == 1); expected_total += i; } test_assert(total == expected_total); for(i = 0; i < NUM_THREADS; ++i) { test_assert(run_func_count[i] > 0); } return 0; }