首页 > 解决方案 > 提升继续恢复断言失败

问题描述

我尝试测试继续,我的代码如下

ctx::continuation fc1; 
ctx::continuation fc2;

ctx::continuation foo1(ctx::continuation&& c) {
    LOG_DBUG("enter");
    c = c.resume();
    LOG_DBUG("done 1");
    fc2 = fc2.resume();
    LOG_DBUG("done 2");
    fc2 = fc2.resume();
    return std::move(c);
}

ctx::continuation foo2(ctx::continuation&& c) {
    LOG_DBUG("enter");
    c = c.resume();
    LOG_DBUG("done 1");
    fc1 = fc1.resume();
    LOG_DBUG("done 2");
    fc1 = fc1.resume();
    return std::move(c);
}


int main() {
    fc1 = ctx::callcc(foo1);
    fc2 = ctx::callcc(foo2);

    LOG_INFO("after callcc");

    for (;;) {
        while(fc1 = fc1.resume()) LOG_DBUG("main c1");
        while(fc2 = fc2.resume()) LOG_DBUG("main c2");
        break;
    }
    std::cout << "main: done" << std::endl;
    return 0;
}

标准输出得到

DBUG [coepoll.cpp:36] [foo1]进入

DBUG [coepoll.cpp:46] [foo2]进入

INFO [coepoll.cpp:61] [main]在 callcc 之后

DBUG [coepoll.cpp:38] [foo1] 完成 1

DBUG [coepoll.cpp:48] [foo2] 完成 1

./myboost/include/boost/context/continuation_fcontext.hpp:263: boost::context::continuation boost::context::continuation::resume() &&: 断言 `nullptr != fctx_' 失败。

似乎在函数foo2调用fc1 = fc1.resume()导致断言失败。我的代码中有错误吗?

标签: c++boost

解决方案


resume调用时,对象continuation无效。

参考说:

continuation 是一次性的 continuation - 它只能使用一次,在调用 continuation::resume() 或 continuation::resume_with() 后它会失效。

以下伪代码显示了resume函数的工作原理:

 foo(continutation&& mainContext) {
            mainContext = mainContext.resume(); 
     //                 | 
     //                 |   [2] resume is called;
     //                 |   [2] resume invalidates mainContext; 
     //                 |   [2] no return value is assigned to mainContext!
     //                 |   [2] we go back to main
     // [4]             |
     // make assignment |
     // now mainContext | 
     // is valid        |
 }

int main(){
    fooContext = callcc( foo );          // [1] we enter into foo function;
    fooContext = fooContext.resume();    // [3] we go back to foo 
}

以下是您的代码的简化版本,让我们对其进行分析:

ctx::continuation foo1(ctx::continuation&& main) {
    main = main.resume(); // [2]
    fc2 = fc2.resume(); // [6]
    fc2 = fc2.resume();
    return std::move(c);
}

ctx::continuation foo2(ctx::continuation&& main) {
    main = main.resume(); // [4]
    fc1 = fc1.resume(); // [7]
    fc1 = fc1.resume();
    return std::move(c);
}


int main() {
    fc1 = ctx::callcc(foo1); // [1]
    fc2 = ctx::callcc(foo2); // [3]

    for (;;) {
        while(fc1 = fc1.resume()) LOG_DBUG("main c1"); // [5]
        while(fc2 = fc2.resume()) LOG_DBUG("main c2");
        break;
    }
  1. foo1开始。
  2. 执行返回main
  3. foo2开始。
  4. 执行返回main
  5. resume被调用fc1fc1无效。控制执行返回[6]。
  6. 在这一行中执行foo2被恢复,我们跳转到[7]。
  7. resume在invalidated 上调用fc1,程序被中止。

推荐阅读