C / C ++与被叫协同程序?

时间:2011-09-14 11:39:45

标签: coroutine

似乎协程通常在更高级别的语言中找到。

wikipedia/en/wiki/Coroutine

似乎也有几种不同的定义。我试图找到在C中特别称为coroutines,就像我们在Lua中一样。

 function foo()     
     print("foo", 1) 
     coroutine.yield() 
     print("foo", 2) 
 end 

感谢您阅读 - Patrick

5 个答案:

答案 0 :(得分:2)

对于C或C ++中的协同程序,没有语言级别的支持。

您可以使用汇编程序或光纤实现它们,但结果将不可移植,而在C ++的情况下,您几乎肯定会失去使用异常的能力,并且无法依赖堆栈展开进行清理。

在我看来,你应该使用支持它们的语言或不使用它们 - 用不支持它们的语言实现你自己的版本就会遇到麻烦。

答案 1 :(得分:1)

抱歉 - C和C ++都不支持协同程序。然而,简单搜索“C coroutine:在问题上产生以下引人入胜的论文:http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html,虽然你可能会发现他的解决方案有点 - 嗯 - 不切实际

答案 2 :(得分:1)

Boost C ++库中有一个新的(自1.53.0版本起)coroutine库:http://www.boost.org/doc/libs/1_53_0/libs/coroutine/doc/html/index.html

我不知道有一个C库 - 我遇到了这个问题寻找一个。

答案 3 :(得分:0)

C ++有很多协程库。来自RethinkDB的Here's one

还有mine header-only library,它适合与回调一起使用。我已经尝试了Boost coroutines,但由于incompatibility with valgrind我还没有使用它们。我的实现使用ucontext.h,到目前为止在valgrind下工作正常。

使用“标准”协程,你必须跳过一些箍来使用它们进行回调。例如,以下是一个工作线程安全(但泄漏)的Cherokee处理程序如何看待Boost协程:

typedef coroutine<void()> coro_t;
auto lock = make_shared<std::mutex>();
coro_t* coro = new coro_t ([handler,buffer,&coro,lock](coro_t::caller_type& ca)->void {
  p1: ca();  // Pass the control back in order for the `coro` to initialize.
  coro_t* coro_ = coro;  // Obtain a copy of the self-reference in order to call self from callbacks.
  cherokee_buffer_add (buffer, "hi", 2); handler->sent += 2;
  lock->lock();  // Prevents the thread from calling the coroutine while it still runs.
  std::thread later ([coro_,lock]() {
    //std::this_thread::sleep_for (std::chrono::milliseconds (400));
    lock->lock();  // Wait for the coroutine to cede before resuming it.
    (*coro_)();  // Continue from p2.
  }); later.detach();
  p2: ca();  // Relinquish control to `cherokee_handler_frople_step` (returning ret_eagain).
  cherokee_buffer_add (buffer, ".", 1); handler->sent += 1;
});
(*coro)(); // Back to p1.
lock->unlock(); // Now the callback can run.

以下是我的看法:

struct Coro: public glim::CBCoro<128*1024> {
  cherokee_handler_frople_t* _handler; cherokee_buffer_t* _buffer;
  Coro (cherokee_handler_frople_t *handler, cherokee_buffer_t* buffer): _handler (handler), _buffer (buffer) {}
  virtual ~Coro() {}
  virtual void run() override {
    cherokee_buffer_add (_buffer, "hi", 2); _handler->sent += 2;
    yieldForCallback ([&]() {
      std::thread later ([this]() {
        //std::this_thread::sleep_for (std::chrono::milliseconds (400));
        invokeFromCallback();
      }); later.detach();
    });
    cherokee_buffer_add_str (_buffer, "."); _handler->sent += 1;
  }
};

答案 4 :(得分:0)

如今,C++ 本身提供了协同程序作为 C++20 的一部分。

关于 C 语言,它们本身不受支持,但有几个库提供了它们。有些是不可移植的,因为它们依赖于一些依赖于体系结构的汇编指令,但有些是可移植的,因为它们使用标准库函数,如 setjmp()/longjmp() getcontext()/setcontext()/makecontext()/swapcontext()。还有一些像 one 这样的原创命题,它使用了 Duff's device 中的 C 语言技巧。