查看带有协程的Boost ASIO http服务器示例,我想知道所使用的克隆方法是否安全:
// We "fork" by cloning a new server coroutine to handle the connection.
// After forking we have a parent coroutine and a child coroutine. Both
// parent and child continue execution at the following line. They can
// be distinguished using the functions coroutine::is_parent() and
// coroutine::is_child().
fork server(*this)();
从当前对象复制一个服务器对象。
但是,难道不存在下列情况发生的可能性吗?
- 克隆子协程发出yield
- 因此,子进程的协程主体被留下
- 因此,子进程的
operator()()
方法为 - 父对象销毁子对象
- 父级开始一个新的迭代并产生
- 子线程调用的异步方法完成
- 因此,现在(被销毁)的子协程被重新进入
如果它是安全的,为什么?
父对象不破坏子对象。
这是因为协程对象是要调用的实际完成处理程序,并且副本保存在服务的队列中。
由于字段(通常)是共享指针,因此实际数据在副本之间"轻微"传输,仅在最后一个完成处理程序完成时才被销毁,并且协程退出,而不是产生。
让所有字段都是共享指针的另一种选择可能是让协程派生enable_shared_from_this
,就像许多其他Asio示例所示的那样。我实际上还没有在协程中使用这个,但我认为它有优点(减少引用计数对yield的开销),并且不能立即想到为什么它不适用于协程的原因。