开关基于协同程序

switch-based coroutines

本文关键字:程序 于协同 开关      更新时间:2023-10-16

我注意到C和c++中协同程序的习惯用法或模式:

struct cofunctor {
    int state = 0;
    void operator () () {
        switch ( state ) {
        case 0: // Caller must initialize to 0
            if ( bar1 ) return;
            while ( bar2 ) {
        state = 1; case 1:
                if ( bar3 ) return;
        state = 2; case 2:
                if ( bar4 ) return;
            }
        state = 3; case 3:
            return;
        }
    }
};

函数执行时,它更新一个持久检查点变量。下次调用它时,使用该值跳转到执行的中间。在实践中,检查点将不仅仅是一个int,而且将包含"局部"变量。

我在用c++写。我的用例很少产生结果,所以我想只在异常处理期间更新检查点。

这个模式在实际实践中是已知的,还是仅仅作为一个好奇的记录?c++中存在可重用的实现吗?

(据我所知,Boost。协程使用不符合标准的堆栈hack,这与longjmp多线程没有什么不同。我的应用程序很少使用协程控制流,并且在众多的"线程"中堆栈使用量可能非常高,因此不适合这样的实现。

c++中存在可重用的实现吗?

本文还讨论了驻留在Boost中的一个单头、无堆栈实现。ASIO图书馆。

另一个ASIO报头似乎表明他们比之前的状态更进一步,但我对这个不太了解。

我不久前在标准c++中实现了可重用的堆栈协程,它允许您拥有局部变量(定义为协程类的成员)。为了调用协程(在我的实现中我称之为"纤维"),你首先初始化一个包含状态的callstack对象,然后启动协程。下面是我如何定义协程的示例:

struct fiber_func_test
{ PFC_FIBER_FUNC();
  // locals
  unsigned loop_count;
  // test function
  fiber_func_test(unsigned loops_): loop_count(loops_) {}
  bool tick(fiber_callstack &fc_, ufloat &dt_)
  {
    PFC_FIBER_BODY_BEGIN
    while(loop_count--)
    {
      PFC_FIBER_CALL(fc_, dt_, fiber_func_sleep, (0.3f));
    }
    PFC_FIBER_BODY_END
  }
};

loop_count是一个局部变量,其状态存储在堆栈中。它的名字是这样的:

fiber_callstack fc;
PFC_FIBER_START(fc, fiber_func_test, (10));
while(fc.tick(0.1f))
  thread_nap();

下面是代码的链接:http://sourceforge.net/p/spinxengine/code/HEAD/tree/sxp_src/core/mp/mp_fiber.h

欢呼,Jarkko

是的,它存在,被记录并使用在知名的分布式应用程序(Putty,但不是c++)中。

  • http://www.chiark.greenend.org.uk/~ sgtatham/coroutines.html

关于Duff设备使用的另一页:

  • http://research.swtch.com/duff

Duff甚至评论了这种用法,说他把它用于中断驱动状态机(现在被称为"Async"):

  • http://brainwagon.org/2005/03/05/coroutines-in-c/

协例程不会破坏堆栈——它只是使用底层调用约定的调用约定(由ABI定义)。你可以说它只是一个函数调用+存储/恢复指令和堆栈指针。