gcc协程演示

main h1=00000000 h2=00000000
 main h1=009B0048 h2=00000000
  main h1=009B0048 h2=009C0078
   main h1=009B0048 h2=009C0078
coroutine:  0 @ 009B005C
coroutine:  9 @ 009C008C
   main h1=009B0048 h2=009C0078
coroutine:  1 @ 009B005C
coroutine: 10 @ 009C008C
   main h1=009B0048 h2=009C0078
coroutine:  2 @ 009B005C
coroutine: 11 @ 009C008C

// cr_func是协程函数。main里启动了两个协程,参数不同
// 协程里printf("coroutine: %2d @ %p\n", i++, &i);
int main() {
    HCR h1, h2; printf("main h1=%p h2=%p\n", h1, h2);
    cr_func(&h1, 0); printf(" main h1=%p h2=%p\n", h1, h2);
    cr_func(&h2, 9); printf("  main h1=%p h2=%p\n", h1, h2);
    for (int i = 0; i < 3; ++i) {
        printf("   main h1=%p h2=%p\n", h1, h2);
        h1.resume(), h2.resume();
    }
    h2.destroy(), h1.destroy();
}

勾起兴趣再往下看:

struct awaitable : public std::suspend_always {
    HCR* m_phcr;
    awaitable(HCR* phcr) : m_phcr(phcr) {}
    void await_suspend(HCR new_handle) { *m_phcr = new_handle; }
};

cr_ret_type cr_func(HCR* phcr, int i) {
    char    data[65536];
    awaitable   a(phcr); // *phcr = new_handle;修改的是main里的handle.
    while (1) {
        co_await a; // 干3件事:
        // 1. Save all local variables (如data) and "jmp_buf" to a heap-allocated object.
        // 2. "setjmp", 设置一个"书签", 以后再"longjmp"跳回来继续执行(resume)。官话:
        //    Create a new coroutine handle X and pass it to a.await_suspend().
        //    HCR是the heap-allocated object的句柄,是个void*, 黑盒子能用不能看。
        // 3. "return"
        // resume回来后执行"return"后的下一条语句。
        // jmp_buf ~= 数据寄存器和instruction pointer/program counter. 局部变量宜只放个指针:
        // struct big_data* pdata;
        printf("coroutine: %2d @ %p\n", i++, &i);
    }
}

丑陋的东西在最后:

typedef std::coroutine_handle<> HCR;

struct cr_ret_type {
  struct promise_type {
    cr_ret_type get_return_object() { return {}; }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }
    void unhandled_exception() {}
  };
};

// https://www.scs.stanford.edu/dm/blog/c++-coroutines.html
// g++ -fcoroutines crdemo.cpp (gcc 10.2或更高版; tdm-gcc-10.3.0.exe ok)
#include <coroutine>
#include <stdio.h>

协程必须返回cr_ret_type,void cr_func()是不行的。cr_ret_type里的东西不要改。可以像python那样做生成器。

上一篇:深入前端研发效能治理:数据化运营思路及其实践


下一篇:推迟势