关于 boost::asio::strand 初始化 socket、stream、resolver、deadline_timer 对象

在 boost::asio 之中默认情况下,大家使用 io_context 来为这些对象初始化传递的执行者,但我需要这里说明。

对于 boost::asio 构造类似 socket 对象必须构造传递 io_context 是个伪命题,boost::asio 对象并非只允许传递 boost::asio::io_context【重点】。
 

它的构造是接收一个 executor 的,这个 executor 不是非必须是 io_context,这个大家必须要了解,但凡仔细看过文档应该都明白才对,但可惜的国内很多人并不愿意多仔细的看看文档,看着那些所谓大牛的 aiso 经验,贴出来的 demo 代码就算是过了。

这样不好。

在 boost::asio 之中,不同的 asio 对象封装所需要构造传递的执行器略微有些限制,但可以确定的是都不允许:

boost::asio::io_context::strand 传递进去执行,对于传递 strand 的正确做法为:

声明:

            typedef boost::asio::io_context::executor_type                  executor_type;
            typedef boost::asio::strand<executor_type>                      strand;

构造:

方法一:

boost::asio::io_context ioc;

strand(ioc.get_executor());

方法二:

boost::asio::io_context ioc;

boost::asio::make_strand(ioc)

把这个构造出来的 strand 传递给 socket、stream 对象的构造函数就可以了。

当然,上面提到了 asio 的构造初始化并非只是 io_context,只要符合 executor 就可以。

比如:

boost::asio::any_io_executor、boost::asio:::any_completion_executor 就没问题,取决于每个不同 asio 对象构造执行器的限制类型。

比如:

如果我们希望 socket 都运行在一个 strand 上面,按照那些所谓大牛,文档都看不仔细的情况下,大概率是让人们构造一个共享的 boost::asio::io_context::strand,然后在 socket 的异步行为回调函数上都 warp 一次。

但我不建议大家这么做,正确的做法是上述形式,构造 strand 的执行器并在构造的时候传递给 socket 即可,这也包括其它的 asio 对象,如 resolver、DNS解析对象。

本人在此处实现了一个封装,用来模拟串化 io_context。

/* https://www.boost.org/doc/libs/1_71_0/libs/beast/example/websocket/client/async/websocket_client_async.cpp */ 
/* https://fossies.org/linux/boost/libs/asio/test/strand.cpp */
namespace poost {
    namespace asio {
        class io_context final {
        public:
            typedef boost::asio::io_context::executor_type                  executor_type;
            typedef boost::asio::strand<executor_type>                      strand;
            typedef boost::asio::io_context::work                           work;

        public:
            io_context() noexcept 
                : io_context(ppp::make_shared_object<boost::asio::io_context>()) {
                
            }
            io_context(const std::shared_ptr<boost::asio::io_context>& context) noexcept                                                                             
                : context_(context) /* context_->get_executor() */
                , strand_(boost::asio::make_strand(*context)) {
                
            }

        public:
            strand&                                                         get_strand() const noexcept { 
                return ppp::constantof(strand_); 
            }
            boost::asio::io_context&                                        get_context() const noexcept { 
                return *context_; 
            }
            std::shared_ptr<boost::asio::io_context>                        ptr_context() const noexcept { 
                return context_;
            }
            executor_type                                                   get_executor() const noexcept { 
                boost::asio::io_context& context = get_context();
                return context.get_executor(); 
            }
            std::shared_ptr<ppp::Byte>                                      ptr_buffers() const noexcept {
                return buffers_;
            }
            void                                                            ptr_buffers(const std::shared_ptr<ppp::Byte>& buffers) const noexcept {
                ppp::constantof(buffers_) = buffers;
            }

        public:
            template <typename LegacyCompletionHandler>                     
            void                                                            post(LegacyCompletionHandler&& handler) const noexcept { 
                strand& strand = get_strand();
                boost::asio::post(strand, handler); 
            }

            template <typename LegacyCompletionHandler>                     
            void                                                            dispatch(LegacyCompletionHandler&& handler) const noexcept { 
                strand& strand = get_strand();
                boost::asio::dispatch(strand, handler); 
            }

        public:
            void                                                            restart() noexcept { 
                boost::asio::io_context& context = get_context();
                context.restart(); 
            } 
            void                                                            run() noexcept;          
            void                                                            run(boost::system::error_code& ec) noexcept { 
                boost::asio::io_context& context = get_context();
                context.run(ec); 
            }
            void                                                            stop() noexcept { 
                boost::asio::io_context& context = get_context();
                context.stop(); 
            }
            bool                                                            stopped() noexcept { 
                boost::asio::io_context& context = get_context();
                return context.stopped(); 
            }

        private:
            mutable std::shared_ptr<boost::asio::io_context>                context_;
            mutable strand                                                  strand_;
            mutable std::shared_ptr<ppp::Byte>                              buffers_;
        };

        inline void                                                         io_context::run() noexcept {
            boost::system::error_code ec; 
            run(ec); 

            boost::asio::detail::throw_error(ec);
        }
    }
}

如何在 socket 上面使用它?

std::shared_ptr<poost::asio::io_context> context;

boost::asio::ip::udp::socket socket_(context->get_strand());

是不是很直观跟简单,那么运行效果会是什么样子呢?

看看线程的调用堆栈是会重叠一层 strand 滴:(所以根本不需要额外的 strand 手动处理)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/490028.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pyrealsense2获取保存点云

一、第一种实现代码 Python import sys import cv2 import pyrealsense2 as rs import numpy as np import keyboard import open3d as o3d import osif __name__ "__main__":output_folder output_data/os.makedirs(output_folder, exist_okTrue)pipeline rs.p…

git cherry pick merge部分提交

cherry pick merge 指定某次提交 1. git history 选择要从哪个分支merge 2. 找到提交记录,选择cherry pick 3.这个时候就可以直接push了

【面试题】ES文档写入和读取流程详解

前言&#xff1a;在回答这个问题之前我们先要搞清楚一个问题那就是什么是文档&#xff0c;避免不知所云&#xff01; 一、什么是文档&#xff1f; 在Elasticsearch中&#xff0c;文档&#xff08;Document&#xff09;是最基本的信息单元&#xff0c;用于表示和存储数据。文…

数据采集用,集成了主流工业通讯协议

IoTClient 是一个物联网设备通讯协议实现客户端&#xff0c;集成了主流工业通讯协议&#xff0c;包括主流PLC通信读取、ModBus协议、Bacnet协议等。该组件基于.NET Standard 2.0&#xff0c;适用于.NET的跨平台开发&#xff0c;可在Windows、Linux等系统上运行&#xff0c;甚至…

LinkedIn账号为什么被封?被封后如何解决?

近期会有一些小伙伴说自己遇到了帐号无法登录的情况&#xff0c;其实出现领英帐号被封号(被限制登录)主要会有两类情况&#xff0c;今天就给大家分享一下如果被封该如何解决&#xff0c;强烈建议收藏。 在电脑领英官网或者手机领英APP上&#xff0c;输入领英帐号密码点击登录后…

数据结构(五)单链表专题

在开始之前&#xff0c;我先来给大家讲一下顺序表与链表的区别&#xff1a; 它们在堆上存储的差异&#xff1a; 我们可以很容易的知道&#xff0c;循序表是连续的有序的&#xff0c;但链表是杂乱的&#xff0c;它们通过地址彼此联系起来。 1. 链表的概念及结构 概念&#xff1…

【光伏科普】光伏投融资计算的意义

光伏产业&#xff0c;作为清洁能源的重要组成部分&#xff0c;近年来在全球范围内得到了广泛的关注与发展。而在光伏项目的实施过程中&#xff0c;投融资计算显得尤为重要。本文旨在探讨光伏投融资计算的意义&#xff0c;以及它如何影响光伏产业的可持续发展。 首先&#xff0c…

无法找到filesystem头文件

无法找到filesystem头文件 一、前言 这段时间接老板命令&#xff0c;做目标识别模型的嵌入式部署。需要将模型运行环境编译后打包到瑞芯微开发板上运行&#xff0c;在此之前我对原C文件做过修改&#xff0c;为了能实现与厂商提供的数据接口对接。 我在用CMake打包过程中&…

jmeter接口测试及详细步骤以及项目实战教程

在接口测试项目实战中&#xff0c;JMeter是一款非常强大和流行的自动化测试工具&#xff0c;它可以测试各种类型的应用程序&#xff0c;并通过采样和报告来识别性能瓶颈和API的问题。本文将为你提供一个基于实际项目的JMeter接口测试项目实战教程&#xff0c;指导你如何使用JMe…

腾讯VS网易:一场不见终局的游戏未来之战

国内游戏霸主腾讯最近赚足了眼球。 总体上看&#xff0c;腾讯手握“游戏社交”两大王牌&#xff0c;最近发布的财报十分亮眼&#xff0c;其2023年总营收和净利润分别同比增长10%和36%&#xff0c;展现了互联网巨头的强劲活力。 然而巨头亦有焦虑&#xff0c;增值服务营收同比…

数学算法(算法竞赛、蓝桥杯)--分解质因数、唯一分解定理

1、B站视频链接&#xff1a;G07 分解质因数 唯一分解定理 试除法_哔哩哔哩_bilibili 题目链接&#xff1a;质因子分解 - 洛谷 #include <bits/stdc.h> using namespace std;int n; int a[100010];//质因子的个数void decompose(int x){for(int i2;i*i<x;i){//i增加&a…

Fastgpt 无法启动或启动后无法正常使用的讨论(启动失败、用户未注册等问题这里)

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01; FastGPT是非常实用并且相当厉害的个人知识库AI项目&#xff0c;项目是非常…

Linux Tomcat的服务器如何查看接口请求方式?

问题描述 最近在和安卓开发对接接口&#xff0c;遇到一个接口总是报405错误&#xff0c;有对接经验的开发应该都知道是请求方式不对&#xff0c;假如接口定义为POST请求的&#xff0c;但是客户端却用GET请求&#xff0c;这时候就会报这个错误。Android客户端那边使用xUtils框架…

扫雷大师:用C语言揭秘自动展开盘面与智能扫雷策略

目录 扫雷自动展开盘面智能扫雷更优策略完整代码 扫雷 扫雷游戏是一款经典的单人电脑游戏&#xff0c;其主要规则如下&#xff1a; 游戏目标&#xff1a;游戏的目标是在不触发任何地雷的情况下&#xff0c;找出所有非雷区域。玩家需要根据格子周围的数字来推断哪些格子含有地雷…

MFC(二)集成基础控件

目录 OnCreateCStatic【标签&#xff0c;图片】CEdit【文本框&#xff0c;密码框&#xff0c;数值框&#xff0c;文本区】CButton【按钮&#xff0c;单选按钮&#xff0c;多选按钮】CComboBox【下拉列表&#xff0c;列表】CSliderCtrl【滑动条】CListCtrl【表格】CAnimateCtrl【…

第十二届蓝桥杯JavaB组省赛真题 - ASC

解题思路&#xff1a; 这是目前为止做到过最简单的了 public class Main {public static void main(String[] args) {int res L-A 65;System.out.print(res);} }

东联直播音效助手

东方联盟创始人郭盛华为广大主播免费开发的一款专用的音效场控工具&#xff0c;通过这款软件&#xff0c;主播使用各种精彩的音效&#xff0c;避免直播间过于低沉和尴尬&#xff0c;从而更好的拉近观众的距离。音效有掌声、爆笑声、尖叫声、关注点赞、任务等各种音效. 【东方联…

【win10 win11添加右键】git bash

打开注册表编辑器。 按下Win键 R&#xff0c;然后输入”regedit”并按下回车键来打开注册表编辑器。计算机\HKEY_CLASSES_ROOT\Directory\Background\shell\git_bash\command2. 导航到注册表路径&#xff1a;依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。右键…

电商系列之仓储发货

疫情3年&#xff0c;大多数人都将购买需求转移到了线上。同时由于暴涨的订单数量、还在恢复中的物流运输等因素&#xff0c;导致用户的收货时间缓慢甚至是发货时间、收货时间延后。那么笔者就从订单的仓库作业流程入手&#xff0c;分析了用户订单发货延后的原因。 受到最近疫情…

2024年软件测试,“我“从初级到高级进阶,不再走弯路...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 现在2024年&#…