ChunelFeng / CGraph

【A common used C++ DAG framework】 一个通用的、无三方依赖的、跨平台的、收录于awesome-cpp的、基于流图的并行计算框架。欢迎star & fork & 交流
http://www.chunel.cn
MIT License
1.71k stars 318 forks source link

异步执行时,立刻执行yield可能失效。 #403

Closed ceykmc closed 1 month ago

ceykmc commented 1 month ago

在示例T20-YieldResume.cpp中:

CGRAPH_ECHO("pipeline async run, BEGIN.");
auto result = pipeline->asyncRun();
CGRAPH_SLEEP_MILLISECOND(2600)

CGRAPH_ECHO("pipeline async run, YIELD.");
status += pipeline->yield();    // 暂停执行,保留当前pipeline内部所有参数信息和状态信息

调用 pipeline->yield(); 期望得到线程暂停执行的效果。 在代码实现上,是将是所有element的status设置为GElementState::YIELD

如果在pipeline->asyncRun()之后,立刻调用pipeline->yield(),也即:

auto result = pipeline->asyncRun();
status += pipeline->yield(); 

由于是在另外一个线程中异步执行,可能会先执行pipeline->yield(),将所有element的status设置为GElementState::YIELD。 然后执行asyncRun()。在run函数中:

CStatus GPipeline::run() {
    CGRAPH_FUNCTION_BEGIN
    CGRAPH_ASSERT_INIT(true)

    /**
     * 1. 将所有 GElement 的状态设定为 NORMAL
     * 2. 将所有的 GParam 设置为初始值
     * 3. 执行dag逻辑
     * 4. 将所有 GElement 的状态恢复为 NORMAL
     * 5. 等到所有异步事件执行结束
     * 6. 将所有的 GParam 复原
     */
    status += repository_.setup();
    status += param_manager_->setup();
    CGRAPH_FUNCTION_CHECK_STATUS

    status = element_manager_->run();
    status += repository_.reset();    // 等异步的逻辑执行,并且获取异步执行的结果信息
    status += event_manager_->reset();    // 所有的事件(特指异步事件)执行结束
    param_manager_->resetWithStatus(status);
    CGRAPH_FUNCTION_END
}

status += repository_.setup();重新将element的status设置为GElementState::NORMAL

这样的情况下,yield其实是被重置了,会和预期的效果不一致。使用时,需要注意下。

ChunelFeng commented 1 month ago

emmm,我们后期可能会加入一种新的状态,确保再未启动 run 的状态下,无法正常使用 yield, 类似的逻辑。

也欢迎老铁 pr相关逻辑。