是否支持在同一条链上执行 boost::asio::~strand<> ?

问题描述 投票:0回答:1

精简版

是否支持在同一个

boost::asio::~strand<>
上执行
strand

找到文档

文档似乎不一致,“遗留/已弃用”

boost::asio::io_context::strand::~strand
文档

通过链发布的尚未被调用的处理程序仍将以满足非并发保证的方式进行调度。

boost::asio::strand::~strand
则不然。我认为两条线索在这方面基本上是相同的,并且提到的句子暗示着我的场景得到支持,但我并没有帮助这个案例获得一个自信的答案。

背景即问题

我在其文档和演讲中使用了

shared_from_this
会话的生命周期自我管理,例如 tcp 会话,就像 boost asio propagtes 一样。由于除了会话类本身之外没有人持有
std::shared_ptr
,因此出现了一个问题:自然地,会话本身执行的代码最终将解构最后一个
shared_ptr
,触发其自己的析构函数
~session
。 在 boost::asio 的示例中,这是不用担心的,因为执行器是否有一个具有持久生命周期或类似的
boost::asio::context&
,并且代码可以使用隐式链。

但是假设session需要一个显式的

boost::asio::strand
,因为我们需要一些并发的业务代码或者我们自己的保活定时器,作为执行器。然后最后一个作用域关闭
}
代码,该代码将执行
~session()
,该代码将在该确切链上执行时执行
~strand()

示例

#include <iostream>
#include <memory>

#include <boost/asio.hpp>

//More specific could be a tcp session for example
struct session : std::enable_shared_from_this<session> {
    session (boost::asio::io_context& context) : strand(boost::asio::make_strand(context)), timer(context){}
    void start() {
        boost::asio::co_spawn(strand, loop(shared_from_this()), boost::asio::detached);
    }

    //Lets say is called from another co_routine, like a tcp eof
    void stop () {
        boost::asio::post(boost::asio::bind_executor(strand, [me = shared_from_this()] () {
            me->timer.cancel();
        }));
    }

private:
    boost::asio::strand<boost::asio::io_context::executor_type> strand;
    boost::asio::steady_timer timer;

    boost::asio::awaitable<void> loop(std::shared_ptr<session> self) {
        while (true)  {
            timer.expires_from_now(std::chrono::seconds{5});
            co_await timer.async_wait(boost::asio::use_awaitable);
            std::cout << "5 seconds expired" << std::endl;
            self->stop();
        }
    } //Triggers ~session which, deconstructs strand, implications? UB?
};


int main(int argc, char* argv[]) {
    boost::asio::io_context context;
    {
        auto s = std::make_shared<session>(context);
        s->start();
    }
    while (true) {
        try {
            context.run();
            break;
        } catch (std::exception const& e) {
            std::cerr << "Exception in context::run(): " << e.what() << std::endl;
        }
    }
}

c++ boost c++20 boost-asio
1个回答
1
投票

不,这不是问题。你不用担心的原因是“新股”是一个执行者。

执行器可以廉价复制并按值传递。任何保留它的东西都会有它的副本。您可以将执行器想象成一个句柄。当然,实现仍然存在于执行上下文中注册的相应服务中。

请注意,您在问题中比较的不同类型的股具有不同的服务实现。坚持一种风格的股线会更有效(当然是现代风格)。

© www.soinside.com 2019 - 2024. All rights reserved.