Giter Site home page Giter Site logo

mfkiwl / lw_coroutine Goto Github PK

View Code? Open in Web Editor NEW

This project forked from xiaoliang314/lw_coroutine

0.0 1.0 0.0 23 KB

纯C语言高性能的轻量级协程,比protothread更高效,仅一个bp.h文件。 Lightweight coroutine with high performance in pure C language, more efficient than protothread, only one bp.h file.

License: Other

C 100.00%

lw_coroutine's Introduction

lw_coroutine

仅一个bp.h文件,它类似于protothread,但采用了不同的实现机制,它使用switch-goto实现,相比protothread有如下优势:

  • 最低的资源占用,仅使用1字节进行状态保存
  • bp支持在switch中进行yield, 而protothread不支持(仅gcc编译器支持,但移植性差)
  • bp有更高效的跳转能力,因为bp中的case是从0连续的,因此可以被优化成最高效的跳转表,而protothread使用行号,具有随机性,因此protothread的跳转性能较差
  • bp的断点号是非常容易识别的,因此可以在bp_begin之前可用于判断当前yield的位置,以实现特殊的需求。而protothread使用的行号是不可识别的,因此其状态信息不能在begin之前被解读出来。
  • bp更精简,使用时仅依赖一个状态变量,因此可以被用于任何的异步回调中,以实现协程。

用例:

#include "bp.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
    /* resource */
    short res;

    /* consumer coroutine breakpoint */
    unsigned char consumer_bp;

    /* produce coroutine breakpoint */
    unsigned char producer_bp;
} res_t;

#define TRUE    1
#define FALSE   (!TRUE)

int consumer(res_t *res)
{
    /* bpd coroutine default breakpoint pointer */
    unsigned char *bpd = &res->consumer_bp;

    /* coroutine begin */
    bpd_begin(2);

    while (1)
    {
        /* wait number of resource > 0 */
        while (res->res <= 0)
        {
            bpd_yield(1) FALSE;
        }

        /* consume */
        res->res--;
        printf("consume a resource, number of res:%d\n", res->res);

        /* wait next consume */
        bpd_yield(2) TRUE;
    }

    /* coroutine end */
    bpd_end();
}

int producer(res_t *res)
{
    /* bpd coroutine default breakpoint pointer */
    unsigned char *bpd = &res->producer_bp;

    /* coroutine begin */
    bpd_begin(2);

    while (1)
    {
        /* wait number of resource < 30 */
        while (res->res >= 30)
        {
            bpd_yield(1) FALSE;
        }

        /* produce */
        res->res++;
        printf("produce a resource, number of res:%d\n", res->res);

        /* wait next produce */
        bpd_yield(2) TRUE;
    }

    /* coroutine end */
    bpd_end();
}

int main()
{
    res_t res = {0, BP_INIT_VAL, BP_INIT_VAL};
    int nrand;

    /* initialize random */
    srand(122);

    /* randomly produce and consume */
    while (1)
    {
        nrand = rand() % 16;
        while (nrand--)
        {
            if (consumer(&res) == FALSE)
                break;
        }

        nrand = rand() % 16;
        while (nrand--)
        {
            if (producer(&res) == FALSE)
                break;
        }
    }

    return 0;
}

lw_coroutine

There is only one bp.h file, which is similar to protothread, but uses a different implementation mechanism. It is implemented using switch-goto and has the following advantages over protothread:

  • Lowest resource usage, use only 1 byte for state preservation
  • bp supports yield in switch, but protothread does not support (only gcc compiler support, but poor portability)
  • bp has a more efficient ability to jump, because the case in bp is continuous from 0, so it can be optimized to the most efficient jump table, and protothread use the line number, with randomness, so the protothread jump performance is poor
  • The breakpoint number of bp is very easy to identify, so it can be used to determine the current yield position before bp_begin to achieve special needs. The line number used by protothread is unrecognizable, so its status information cannot be interpreted before PT_BEGIN.
  • The bp is more streamlined, using only one state variable when used, so it can be used in any asynchronous callback to implement coroutines.

Usage:

#include "bp.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
    /* resource */
    short res;

    /* consumer coroutine breakpoint */
    unsigned char consumer_bp;

    /* produce coroutine breakpoint */
    unsigned char producer_bp;
} res_t;

#define TRUE    1
#define FALSE   (!TRUE)

int consumer(res_t *res)
{
    /* bpd coroutine default breakpoint pointer */
    unsigned char *bpd = &res->consumer_bp;

    /* coroutine begin */
    bpd_begin(2);

    while (1)
    {
        /* wait number of resource > 0 */
        while (res->res <= 0)
        {
            bpd_yield(1) FALSE;
        }

        /* consume */
        res->res--;
        printf("consume a resource, number of res:%d\n", res->res);

        /* wait next consume */
        bpd_yield(2) TRUE;
    }

    /* coroutine end */
    bpd_end();
}

int producer(res_t *res)
{
    /* bpd coroutine default breakpoint pointer */
    unsigned char *bpd = &res->producer_bp;

    /* coroutine begin */
    bpd_begin(2);

    while (1)
    {
        /* wait number of resource < 30 */
        while (res->res >= 30)
        {
            bpd_yield(1) FALSE;
        }

        /* produce */
        res->res++;
        printf("produce a resource, number of res:%d\n", res->res);

        /* wait next produce */
        bpd_yield(2) TRUE;
    }

    /* coroutine end */
    bpd_end();
}

int main()
{
    res_t res = {0, BP_INIT_VAL, BP_INIT_VAL};
    int nrand;

    /* initialize random */
    srand(122);

    /* randomly produce and consume */
    while (1)
    {
        nrand = rand() % 16;
        while (nrand--)
        {
            if (consumer(&res) == FALSE)
                break;
        }

        nrand = rand() % 16;
        while (nrand--)
        {
            if (producer(&res) == FALSE)
                break;
        }
    }

    return 0;
}

lw_coroutine's People

Contributors

xiaoliang314 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.