void *generator_new_(void (*fn)(void *), size_t retsize) { char *base; size_t size = DEFAULT_STATE_SIZE; size_t metasize = generator_metasize(retsize); struct coroutine_stack *stack; void *ret; struct generator_ *gen; base = malloc(size); if (!base) abort(); retsize = (retsize + STATE_ALIGN) & ~(STATE_ALIGN - 1); stack = coroutine_stack_init(base, size, metasize); gen = coroutine_stack_to_metadata(stack, metasize); ret = gen + 1; gen->base = base; gen->complete = false; coroutine_init(&gen->gen, fn, ret, stack); return ret; }
int main() { coenv_t env = coroutine_init(); myctx ctx1 = {1}; myctx ctx2 = {2}; myctx ctx3 = {3}; int i; int co1, co2, co3; co1 = coroutine_new(env, cofunc, &ctx1); printf("coroutine_new %d\n", co1); co2 = coroutine_new(env, cofunc, &ctx2); printf("coroutine_new %d\n", co2); co3 = coroutine_new(env, cofunc, &ctx3); printf("coroutine_new %d\n", co3); for (i = 0; i < 10; i++) { coroutine_resume(env, co1); coroutine_resume(env, co2); coroutine_resume(env, co3); } coroutine_uninit(env); getchar(); return 0; }
static rich_Sink* json_new_sink(void* _self, Output* out) { JSONSink* self = malloc(sizeof(JSONSink)); self->base._impl = &json_sink_impl; self->out = out; coroutine_init(self->co); coroutine_push(self->co, &root_state, 0); return &self->base; }
rich_Sink* rich_bind_sink(rich_Schema* schema, void* to) { BoundSink* self = malloc(sizeof(BoundSink)); self->base._impl = &bound_sink_impl; self->schema = schema; self->to = to; coroutine_init(self->co); *(BoundSink**)coroutine_push(self->co, &sink_root_state, sizeof(BoundSink*)) = self; return &self->base; }
static gboolean connect_delayed(gpointer data) { SpiceChannel *channel = data; spice_channel *c = channel->priv; struct coroutine *co; SPICE_DEBUG("Open coroutine starting %p", channel); c->connect_delayed_id = 0; co = &c->coroutine; co->stack_size = 16 << 20; /* 16Mb */ co->entry = spice_channel_coroutine; co->release = NULL; coroutine_init(co); coroutine_yieldto(co, channel); return FALSE; }
static void test_coroutine_simple(void) { struct coroutine *self = coroutine_self(); struct coroutine co = { .stack_size = 16 << 20, .entry = co_entry_42, }; gpointer result; g_assert(coroutine_self_is_main()); coroutine_init(&co); result = coroutine_yieldto(&co, GINT_TO_POINTER(42)); g_assert_cmpint(GPOINTER_TO_INT(result), ==, 0x42); g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*"); coroutine_yieldto(&co, GINT_TO_POINTER(42)); g_test_assert_expected_messages(); g_assert(self == coroutine_self()); g_assert(coroutine_self_is_main()); } static gpointer co_entry_two(gpointer data) { struct coroutine *self = coroutine_self(); struct coroutine co = { .stack_size = 16 << 20, .entry = co_entry_check_self, }; g_assert(!coroutine_self_is_main()); coroutine_init(&co); coroutine_yieldto(&co, &co); g_assert(self == coroutine_self()); return NULL; } static void test_coroutine_two(void) { struct coroutine *self = coroutine_self(); struct coroutine co = { .stack_size = 16 << 20, .entry = co_entry_two, }; coroutine_init(&co); coroutine_yieldto(&co, NULL); g_assert(self == coroutine_self()); } static gpointer co_entry_yield(gpointer data) { gpointer val; g_assert(data == NULL); val = coroutine_yield(GINT_TO_POINTER(1)); g_assert_cmpint(GPOINTER_TO_INT(val), ==, 2); g_assert(!coroutine_self_is_main()); val = coroutine_yield(GINT_TO_POINTER(3)); g_assert_cmpint(GPOINTER_TO_INT(val), ==, 4); return NULL; } static void test_coroutine_yield(void) { struct coroutine *self = coroutine_self(); struct coroutine co = { .stack_size = 16 << 20, .entry = co_entry_yield, }; gpointer val; coroutine_init(&co); val = coroutine_yieldto(&co, NULL); g_assert(self == coroutine_self()); g_assert_cmpint(GPOINTER_TO_INT(val), ==, 1); val = coroutine_yieldto(&co, GINT_TO_POINTER(2)); g_assert(self == coroutine_self()); g_assert_cmpint(GPOINTER_TO_INT(val), ==, 3); val = coroutine_yieldto(&co, GINT_TO_POINTER(4)); g_assert(self == coroutine_self()); g_assert(val == NULL); g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*"); coroutine_yieldto(&co, GINT_TO_POINTER(42)); g_test_assert_expected_messages(); } int main(int argc, char* argv[]) { g_test_init(&argc, &argv, NULL); g_test_add_func("/coroutine/simple", test_coroutine_simple); g_test_add_func("/coroutine/two", test_coroutine_two); g_test_add_func("/coroutine/yield", test_coroutine_yield); return g_test_run (); }