souce / coevent

coevent is a coroutine library for C.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

coevent

coevent is a coroutine library for C, based on "ae" and "pt", the coroutine scheduling by IO events.

Example

/*
 * clean up
 */
static void ce_done(struct coevent *ce, int err){
    if(NULL == ce){
        return; //relax take it easy, for there is nothing that we can do
    }

    if(AE_ERR == err){
        perror("connection err");
    }else if(EVENTS_TIMEOUT == err){
        perror("connection timeout");
    }else if(0 != err){
        fprintf(stderr, "unknown err:%d (%s)\n", errno, strerror(errno));
    }

    if(NULL != ce->priv){
        http_free_client((struct http_client *)(ce->priv));
    }
    COEVENT_FREE(ce);
}

/*
 * handling the HTTP request
 */
static COEVENT_COROUTINE(ce_process(struct coevent *ce)){
    struct http_client *cli = (struct http_client *)(ce->priv);

    //define local variables for coroutines
    struct{
        int retry;
        //Other variables ...
    } *local_vars = COEVENT_GET_VARS(ce, sizeof(*local_vars));
    if(NULL == local_vars){
        printf("init local variables err, errno:%d, client ip:%s", errno, cli->ip);
        goto over;
    }

    COEVENT_BEGIN(ce);

    //read HTTP request
    local_vars->retry = 0;
    while(MAX_RETRY_COUNT > local_vars->retry++){
        //wait for the read event to be triggered before proceeding
        COEVENT_YIELD_UNTIL(ce, cli->cli_fd, EVENTS_READABLE, MAX_WAIT_TIMEOUT);
        if(AIO_ERR == aio_read(cli->cli_fd, (byte *)cli->req_buf, sizeof(cli->req_buf), &(cli->readn))){
            break; //connection reset by peer, or other exception
        }
        if(HTTP_OK == http_parse_request_line(cli)){
            break; //request line is complete
        }
    }

    //check request parameters ...

    COEVENT_YIELD(ce); //immediately interrupt the coroutine function and return, and wait until the next event cycle

    //processing HTTP requests
    if(HTTP_ERR == http_service(RESOURCE_PATH, cli)){
        goto over;
    }

    COEVENT_YIELD(ce); //immediately interrupt the coroutine function and return, and wait until the next event cycle

    //write HTTP response
    local_vars->retry = 0;
    while(MAX_RETRY_COUNT > local_vars->retry++ && cli->res_len > cli->written){
        //try "write" once before the event is triggered
        if(AIO_ERR == aio_write(cli->cli_fd, (byte *)cli->res_buf, cli->res_len, &(cli->written))){
            goto over;
        }
        COEVENT_YIELD_UNTIL(ce, cli->cli_fd, EVENTS_WRITABLE, MAX_WAIT_TIMEOUT); //wait for the event
    }
    //do not try again even if the response data is not finished
    errno = 0;

over:
    //normal end or exception encountered
    COEVENT_END(ce, errno);
}

/*
 * accept the client connection, and start the coroutine
 */
static void handle_request(aeEventLoop *loop, int server_fd, void *data, int mask){
    //...
    //accept a connection request from a client
    client_fd = socket_handle_client(server_fd);
    //...

    //start a new coroutine to handle each request
    ce = COEVENT_CREATE(loop, ce_process, ce_done, (void *)cli, STACK_SIZE);
    if(NULL == ce){
        perror("create ce failed in dispatcher!");
        goto err;
    }
    //start the coroutine and process the request
    COEVENT_RUN(ce);
    //...
}

About

coevent is a coroutine library for C.

License:MIT License


Languages

Language:C 100.0%