int main() { coro_initialize(); enum { STACKSIZE = 4096 }; struct timeval tpend, tpstart; void* stack; stack = malloc(STACKSIZE); void* args = NULL; int count = 0; coro_create(testContext, test, args, stack, STACKSIZE); gettimeofday(&tpstart, 0); while(count++ < 1000000) { coro_transfer(mainContext, testContext); } gettimeofday(&tpend, 0); float timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec; timeuse /= 1000000; printf("libcoro 切换1百万次耗时: %f 秒\n",timeuse); free(stack); // printf("\nreturn to the main\n"); return 0; }
int _prepareFiber( Fiber *to, void *code, uintptr_t arg ) { /* Need to allocate stack manually. */ to->sptr = last_stack ? (char *)last_stack : (char *)malloc( STACK_SIZE ); coro_create( &to->coro_ctx, (coro_func)code, (void *)arg, to->sptr, STACK_SIZE ); return 0; }
int main(void){ CoroP b = coro_create("ping", ping); CoroP c = coro_create("pong", pong); int i,j = 0; for(i=0; i<5; i++){ coro_resume(b, j); j++; printf("main: %d\n", i); coro_resume(c, j); printf("main: %d\n", i); } j = coro_resume(b,0); j = coro_resume(c,0); return 0; }
int32_t sche_spawn(sche_t s,void*(*fun)(void*),void*arg) { if(s->coro_size > s->max_coro) return -1; coro_t co = coro_create(s,s->stack_size,coro_fun); co->arg = arg; co->fun = fun; ++s->coro_size; double_link_push(&s->coros,&co->dblink); uthread_switch(s->co->ut,co->ut,co); return 0; }
sche_t sche_create(int32_t max_coro,int32_t stack_size,void (*idel)(void*),void *idel_arg) { init_system_time(10); sche_t s = calloc(1,sizeof(*s)); s->stack_size = stack_size; s->max_coro = max_coro; s->active_list_1 = LINK_LIST_CREATE(); s->active_list_2 = LINK_LIST_CREATE(); s->_minheap = minheap_create(max_coro,_less); s->next_check_timeout = GetSystemMs() + 200; s->co = coro_create(s,0,NULL); s->idel = idel; s->idel_arg = idel_arg; double_link_clear(&s->coros); set_current_coro(s->co); return s; }
coroutine* coro_alloc(void (*fn)(void*), void *arg, size_t stack) { coroutine *co = nil; co = cs_alloc(sizeof(coroutine) + stack); if(co == nil) { log_error("%s", "coro_alloc fail"); return nil; } memset(co, 0, sizeof(coroutine)); //co->cid = coroidgen++; void* stk = (void*)(co + 1); coro_create(&co->ctx, fn, arg, stk, stack); co->status = M_FREE; co->sched = nil; co->need_parallel = false; return co; }
void uvc_create(char *name, unsigned int size, coro_func func, void *arg){ uvc_ctx *ctx = (uvc_ctx *)malloc(sizeof(uvc_ctx)); memset(ctx, 0, sizeof(uvc_ctx)); //ctx->data=arg; coro_stack_alloc(&ctx->stack, size); coro_create(&ctx->cur, func, arg, ctx->stack.sptr, ctx->stack.ssze); if (name == NULL || strlen(name) == 0){ sprintf(ctx->name, "coro"); } else{ sprintf(ctx->name, name); } uvc_ready(ctx); //uvc_resume(ctx); return; }
static uvc_thread_env *uvc_get_env(){ uvc_ctx *ctx = NULL; uv_once(&once,uvc_init); uvc_thread_env *env=(uvc_thread_env *)uv_key_get(&uvc_key); if(env==NULL){ env=(uvc_thread_env *)malloc(sizeof(uvc_thread_env)); memset(env,0,sizeof(uvc_thread_env)); env->loop = uv_loop_new(); queue_init(&env->pending_queue); queue_init(&env->ready_queue); ctx = (uvc_ctx *)malloc(sizeof(uvc_ctx)); memset(ctx, 0, sizeof(uvc_ctx)); coro_stack_alloc(&ctx->stack, 0); coro_create(&ctx->cur, NULL, NULL, ctx->stack.sptr, ctx->stack.ssze); sprintf(ctx->name, "ROOT"); env->schedule_task = ctx; env->runing_task = ctx; ctx->status = UVC_STATUS_RUNING; uv_key_set(&uvc_key,env); } return env; }
void swoole_websocket_onOpen(http_context *ctx) { #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #endif int fd = ctx->fd; swConnection *conn = swWorker_get_connection(SwooleG.serv, fd); if (!conn) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%d] is closed.", fd); return; } conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; zend_fcall_info_cache *cache = php_swoole_server_get_cache(SwooleG.serv, conn->from_fd, SW_SERVER_CB_onOpen); if (cache) { swServer *serv = SwooleG.serv; zval *zserv = (zval *) serv->ptr2; zval *zrequest_object = ctx->request.zobject; zval *retval = NULL; #ifndef SW_COROUTINE zval **args[2]; args[0] = &zserv; args[1] = &zrequest_object; #else zval *args[2]; args[0] = zserv; args[1] = zrequest_object; #endif #ifndef SW_COROUTINE zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, conn->from_fd, SW_SERVER_CB_onOpen); if (sw_call_user_function_fast(zcallback, cache, &retval, 2, args TSRMLS_CC) == FAILURE) { swoole_php_error(E_WARNING, "onOpen handler error"); } #else int ret = coro_create(cache, args, 2, &retval, NULL, NULL); if (ret != 0) { if (ret == CORO_LIMIT) { SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } return; } #endif if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { sw_zval_ptr_dtor(&retval); } } }
int swoole_websocket_onMessage(swEventData *req) { #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #endif int fd = req->info.fd; zval *zdata; SW_MAKE_STD_ZVAL(zdata); char frame_header[2]; php_swoole_get_recv_data(zdata, req, frame_header, 2); long finish = frame_header[0] ? 1 : 0; long opcode = frame_header[1]; zval *zframe; SW_MAKE_STD_ZVAL(zframe); object_init_ex(zframe, swoole_websocket_frame_class_entry_ptr); zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("fd"), fd TSRMLS_CC); zend_update_property_bool(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("finish"), finish TSRMLS_CC); zend_update_property_long(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("opcode"), opcode TSRMLS_CC); zend_update_property(swoole_websocket_frame_class_entry_ptr, zframe, ZEND_STRL("data"), zdata TSRMLS_CC); swServer *serv = SwooleG.serv; zval *zserv = (zval *) serv->ptr2; #ifndef SW_COROUTINE zval **args[2]; args[0] = &zserv; args[1] = &zframe; #else zval *args[2]; args[0] = zserv; args[1] = zframe; #endif zval *retval = NULL; #ifndef SW_COROUTINE zend_fcall_info_cache *fci_cache = php_swoole_server_get_cache(serv, req->info.from_fd, SW_SERVER_CB_onMessage); zval *zcallback = php_swoole_server_get_callback(SwooleG.serv, req->info.from_fd, SW_SERVER_CB_onMessage); if (sw_call_user_function_fast(zcallback, fci_cache, &retval, 2, args TSRMLS_CC) == FAILURE) { swoole_php_error(E_WARNING, "onMessage handler error"); } #else zend_fcall_info_cache *cache = php_swoole_server_get_cache(serv, req->info.from_fd, SW_SERVER_CB_onMessage); int ret = coro_create(cache, args, 2, &retval, NULL, NULL); if (ret != 0) { sw_zval_ptr_dtor(&zdata); sw_zval_ptr_dtor(&zframe); if (ret == CORO_LIMIT) { SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } return SW_OK; } #endif if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { sw_zval_ptr_dtor(&retval); } sw_zval_ptr_dtor(&zdata); sw_zval_ptr_dtor(&zframe); return SW_OK; }
static PHP_METHOD(swoole_coroutine_util, create) { zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback) == FAILURE) { return; } sw_zval_add_ref(&callback); callback = sw_zval_dup(callback); char *func_name = NULL; zend_fcall_info_cache *func_cache = emalloc(sizeof(zend_fcall_info_cache)); if (!sw_zend_is_callable_ex(callback, NULL, 0, &func_name, NULL, func_cache, NULL TSRMLS_CC)) { swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name); sw_zval_free(callback); efree(func_name); return; } efree(func_name); php_swoole_check_reactor(); if (swReactorCheckPoint == NULL) { coro_init(TSRMLS_C); } zval *retval = NULL; zval *args[1]; jmp_buf *prev_checkpoint = swReactorCheckPoint; swReactorCheckPoint = emalloc(sizeof(jmp_buf)); php_context *cxt = emalloc(sizeof(php_context)); coro_save(cxt); int ret = coro_create(func_cache, args, 0, &retval, NULL, NULL); efree(func_cache); efree(swReactorCheckPoint); if (ret < 0) { sw_zval_free(callback); RETURN_FALSE; } //save callback COROG.current_coro->function = callback; swReactorCheckPoint = prev_checkpoint; coro_resume_parent(cxt, retval, retval); efree(cxt); if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } RETURN_TRUE; }
static void ugh_client_wcb_recv(EV_P_ ev_io *w, int tev) { int nb; ugh_client_t *c = aux_memberof(ugh_client_t, wev_recv, w); nb = aux_unix_recv(w->fd, c->buf_recv.data, c->buf_recv.size); log_debug("client recv: %d: %.*s", nb, nb, c->buf_recv.data); if (0 == nb) { ugh_client_del(c); return; } if (0 > nb) { if (EAGAIN == errno) { ev_timer_again(loop, &c->wev_timeout); return; } ugh_client_del(c); return; } c->buf_recv.data += nb; c->buf_recv.size -= nb; ev_timer_again(loop, &c->wev_timeout); if (NULL == c->request_end) { int status = ugh_parser_client(c, c->buf_recv.data - nb, nb); if (UGH_AGAIN == status) { return; } if (UGH_HTTP_BAD_REQUEST <= status) { ugh_client_send(c, status); return; } if (UGH_HTTP_POST == c->method) { ugh_header_t *hdr_content_length = ugh_client_header_get_nt(c, "Content-Length"); if (0 != hdr_content_length->value.size) { c->content_length = atoi(hdr_content_length->value.data); if (c->content_length > (c->buf_recv.size + (c->buf_recv.data - c->request_end))) { c->body.data = aux_pool_nalloc(c->pool, c->content_length); c->body.size = c->buf_recv.data - c->request_end; memcpy(c->body.data, c->request_end, c->body.size); c->buf_recv.data = c->body.data + c->body.size; c->buf_recv.size = c->content_length - c->body.size; } else { c->body.data = c->request_end; c->body.size = c->buf_recv.data - c->request_end; } if (c->body.size < c->content_length) { return; } } } } else if (UGH_HTTP_POST == c->method) { c->body.size += nb; if (c->body.size < c->content_length) { return; } } ev_io_stop(loop, &c->wev_recv); ev_timer_stop(loop, &c->wev_timeout); #if 1 /* prepare post args */ ugh_header_t *hdr_content_type = ugh_client_header_get_nt(c, "Content-Type"); if (sizeof("application/x-www-form-urlencoded") - 1 == hdr_content_type->value.size && 0 == strncmp(hdr_content_type->value.data, "application/x-www-form-urlencoded", hdr_content_type->value.size)) { ugh_parser_client_body(c, c->body.data, c->body.size); } #endif #if 1 /* UGH_CORO ENABLE */ c->stack = aux_pool_malloc(c->pool, UGH_CORO_STACK); if (NULL == c->stack) { ugh_client_send(c, UGH_HTTP_INTERNAL_SERVER_ERROR); return; } coro_create(&c->ctx, ugh_client_ccb_handle, c, c->stack, UGH_CORO_STACK, &ctx_main); is_main_coro = 0; coro_transfer(&ctx_main, &c->ctx); is_main_coro = 1; #endif #if 0 /* UGH_CORO DISABLE */ ugh_client_ccb_handle(c); #endif }