似乎协程通常在更高级别的语言中找到。
似乎也有几种不同的定义。我试图找到在C中特别称为coroutines,就像我们在Lua中一样。
function foo()
print("foo", 1)
coroutine.yield()
print("foo", 2)
end
感谢您阅读 - Patrick
答案 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 语言技巧。