如何将对象的所有异步操作纳入boost::asio::strand?两种方案可行吗?
Boost.Asio strand 方案有效性分析
背景
官方Boost.Asio教程中展示了用boost::asio::bind_executor函数返回新处理器,自动通过strand对象调度完成处理器的用法,示例代码如下:
#include <boost/asio.hpp> #include <iostream> #include <thread> class Printer1 { public: Printer1(boost::asio::io_context& io) : m_strand{boost::asio::make_strand(io)} , m_timer1{io} , m_timer2{io} { m_timer1.async_wait(boost::asio::bind_executor(m_strand, [this](const boost::system::error_code& error){std::cout << "1 ";})); m_timer2.async_wait(boost::asio::bind_executor(m_strand, [this](const boost::system::error_code& error){std::cout << "2 ";})); } private: boost::asio::strand<boost::asio::io_context::executor_type> m_strand; boost::asio::steady_timer m_timer1; boost::asio::steady_timer m_timer2; };
现在需要验证:以下两种实现方案能否将定时器的所有操作都放入同一个strand中?
方案一(Printer2)
代码实现
class Printer2 { public: Printer2(boost::asio::io_context& io) : m_strand{boost::asio::make_strand(io)} , m_timer1{m_strand} , m_timer2{m_strand} { m_timer1.async_wait([this](const boost::system::error_code& error){std::cout << "1 ";}); m_timer1.async_wait([this](const boost::system::error_code& error){std::cout << "2 ";}); } private: boost::asio::strand<boost::asio::io_context::executor_type> m_strand; boost::asio::steady_timer m_timer1; boost::asio::steady_timer m_timer2; };
有效性分析
可以达到目标。当用strand对象初始化steady_timer时,定时器会将strand作为自己的默认执行器。后续调用async_wait时,如果没有显式指定其他执行器,定时器会自动使用这个strand来调度完成处理器。因此,所有定时器的异步操作完成后,对应的回调都会在同一个strand中串行执行,保证线程安全。
方案二(Printer3)
代码实现
class Printer3 { public: template <typename Executor> Printer3(Executor executor) : m_timer1{executor} , m_timer2{executor} { m_timer1.async_wait([this](const boost::system::error_code& error){std::cout << "1 ";}); m_timer1.async_wait([this](const boost::system::error_code& error){std::cout << "2 ";}); } private: boost::asio::steady_timer m_timer1; boost::asio::steady_timer m_timer2; }; int main() { boost::asio::io_context io; Printer3 p{boost::asio::make_strand(io)}; // ... }
有效性分析
同样可以达到目标。这里通过模板构造函数接收一个strand执行器,并用它初始化两个定时器。和方案一原理一致,定时器的默认执行器被设置为传入的strand,后续async_wait的回调会自动通过该strand串行调度。这种写法更灵活,允许调用者决定使用哪种执行器(strand或直接用io_context),但在当前场景下,传入strand后就能保证所有定时器操作都在同一个strand中执行。
内容的提问来源于stack exchange,提问作者Daniel F
相关产品推荐
相关产品推荐

