第13章 网络 Page724 asio定时器

 程序代码:

11行,声明一个ios对象

13行,使用ios对象作为参数声明一个定时器,此时,定时器和ios完成了关联,后面定时器如果有任务的话,就可以将任务交给ios

16行,为定时器设置一个定时任务,13行,定时器已经和ios已经了关联,定时器就可以将定时器交给ios,定时工作由操作系统完成,所以这一行实际上,是将任务添加到io_service身上,因为这个定时任务,是由操作系统完成的。将任务添加到io_service身上,并不需要ios“转”起来

23~33行,使用定时器的async_wait()方法,为定时器设置一个回调动作(函数指针,函数对象,Lambda表达式,std::function对象都可以),当定时器的定时任务由ios完成以后(操作系统完成),操作系统则“吐”出一个事件给ios,告诉ios,定时任务完成了,你可以发起回调动作了, 如果ios空闲,并且ios的run()方法正在被调用,则ios处理此事件,发起回调动作,就是本例中Lamabda表达式。

37行,启动io_service服务,定时器定时任务由ios交给操作系统完成后,操作系统回馈给ios一个事件,通知ios任务已经完成,ios接收到此事件,便会发起回调动作。启动定时器的回调活动(async_wait()函数的参数)。若被注释掉,则定时任务完成后,不会启动回调活动。

综合起来,过程是这样的,13行,完成定时器与ios的关联,16行,为定时器设置一个任务,这个任务会被ios交给操作系统完成(这一步不需要ios“转”起来),操作系统完成任务完成后,回馈一个事件给ios, 通知ios,任务已经完成了,可以发起回调了,37行,如果ios的run()方法已经调用了,则,ios将发起回调动作,就是执行23行(设置一个回调动作)的Lambda表达式。

ios_service

ios_service(输入输出_服务),在asio新版中也叫io_context(输入输出_上下文)。更好的名称应是“io_engine(输入输出_引擎)”;run一词,不能简单地认为是有个小人在跑,而是要想到"运转"这个词。

本文中的程序第16行,就是往ios_service身上丢个定时任务

当我们调用io_service的run()方法,引擎的齿轮就转了起来,然后需要说三遍的重要事情来了:io_service对象的run()方法并非永久地转下去,它只是转到没有任务就立即停转(函数返回)

当io_service对象“转”起来(即run()方法正在执行),它就会去处理身上的事件当全部任务的全部事件都处理完成,该io_service对象就不再转动。后续要是又有新任务往它身上加,除非再次调用run(),否则任务都不会被执行,最终也许任务堆积成山。

任务来自何处?任务谁来完成?任务去往何处?

一、任务来自何处?

任务来自应用程序,比如我们写的代码:

timer_1.async_wait(...); 

timer_1在执行async_wait()方法时,创建了一个异步任务,并且将该任务交给io_service对象,即本例中的ios变量timer_1什么时候认识的ios对象的呢?请看它的构造过程:

boost::asio::system_timer timer_1(ios);

time_1是一个对象,它拥有一件有赖外部环境推动完成的任务这样的对象在asio中称为“I/O对象”。比如说“定时器”,之前在“异步、异步、异步”小节中演示了两种实现方法:一是当前应用程序的当前线程直接堵塞“睡”上一段时间,二是当前应用程序新开一个线程,让那个线程“睡上”上一段时间。尽管后者的表现效果是"异步",但与前者没有本质区别,因为在等待事情完成的期间,都百分百地耗费当前应用程序的一个线程。asio提供的timer,则将定时的工作交给操作系统或特定支撑框架,因为底层往往可以提供低成本的定时器实现。

小提示:定时器和“I/O”有关系吗?

可以这样理解,我们交个操作系统一个时长,经过该时长后,操作系统回馈一个信号以示“定时到啦”,这一进一出不就是“I/O”?

二、任务谁来完成?

答:任务本例中为定时工作被io_service交给操作系统完成

三、任务去往何处?

答:任务完成后就结束使命了,但为了让上层应用程序知道任务完成了,io_service对象会触发一个事件。事件就是创建任务时指定的回调动作,比如本例中timer_1.async_wait(...)调用时入参所指定的lambda表达式。因此可以理解为任务走了,事件来了。当然,前提是有线程在调用该io_service对象的run()方法

现在,关于io_service的图示如图13-18所示

任务交给操作系统之后,线程就空闲了,可以去处理别的任务。而操作系统完成任务后将“吐”出事件给某个io_service对象,此时如果有一个线程正好在运行该io_service对象的run()方法,并且它空闲(没有在处理之前的事件),它就有机会接收并处理该事件。如果这样的线程有多个,asio保障只会有一个线程接收并处理同一个事件。如果没有任何这样的线程,新事件就会无人受理。

程序的调试

若我们在第25行打一个断点,则会发现,调试启动以后,程序并不会立即停在第25行,而是在定时器任务完成之后,触发回调活动,程序才会停在第25行,这充分说明,回调活动是异步执行的

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣-125. 验证回文串

文章目录 力扣题目代码 力扣题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。 字母和数字都属于字母数字字符。 给你一个字符串 s,如果它是 回文串 ,…

【日常聊聊】新年新征程:迎接学习的挑战

🍎个人博客:个人主页 🏆个人专栏:日常聊聊 ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 结语 我的其他博客 前言 随着新的一年的到来,程序员们站在了全新的起点。这是一个充满机遇和挑战的时刻&#xff0…

【JavaEE】_HTTP请求与响应

目录 1. HTTP协议 1.1 HTTP简介 1.2 Fiddler 2. HTTP请求 2.1 首行 2.2 请求头(header) 2.3 空行 2.4 正文(body) 3. HTTP响应 3.1 首行 3.2 响应头(header) 3.3 空行 3.4 正文(bo…

13.let、const、var的区别

(1)块级作用域: 块作用域由 { }包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题: 内层变量可能覆盖外层变量用来计数的循环变量泄露为全局变量 (2&…

51单片机编程基础(C语言):LED点阵屏

点阵屏介绍 类似于数码管,要用到肉眼视觉效应。扫描,才能把每一个LED都能选中,从而显示我们想要的图形,否则, 只能一次点亮一个LED, LED使用 51单片机点阵屏电路图: 实际连接顺序如下图&#…

Java中的乐观锁和悲观锁

使用场景及用法 悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,…

爱快使用VPN

文章目录 一、VPN服务器1. 各种VPN比较2. PPTP服务端配置3. 创建登录账号4. 创建端口映射5. 设置动态域名 二、Windows客户端1. 连接配置2. 不能连接 Internet 配置 一、VPN服务器 1. 各种VPN比较 PPTPIPSECOpenVPN简介微软推出的VPN协议,占用资源少更高级的VPN协…

php基础学习之分支结构和循环结构(不细讲,来对比一下和两大常用高级编程语言(C++/Java)的细微区别以便记忆)

分支结构 常见分支结构 编程语言常见分支结构有: if语句if-else语句if-elseif-else语句switch语句 其中,除了if-elseif-else语句外,另外3中分支语句在php中和C/Java是一模一样的! 而if-elseif-else的唯一不同点就在,【…

Linux查看日志的几种方法总结

摘要 Linux系统中查看日志的命令确实多种多样,每个命令都有其特定的用途和优势。常用的命令有:tail、cat、tac、head、echo,grep、less、awk、sed。 下面我会详细解释这些命令在查看日志时的用法和特点: tail命令: ta…

机器学习:ROC曲线笔记

ROC曲线(Receiver Operating Characteristic Curve)是一种用于评估二分类模型性能的图形化工具,主要用于展示在不同阈值(Threshold)下模型的真阳性率(True Positive Rate,TPR)和假阳…

比亚迪面试

HashMap的底层结构 HashMap 在 Java 中是基于散列算法实现的,其底层主要由数组和链表(Java 8 后加入了红黑树)构成。当一个元素被加入到 HashMap 中时,会使用散列函数计算出该元素的存储索引,然后将元素存储到对应索引…

elasticSearch使用场景深入详解

Elasticsearch 是一个基于 Lucene 的搜索引擎,它提供了一个分布式、支持多租户的全文搜索引擎,具有 HTTP Web 接口和无模式 JSON 文档。Elasticsearch 是 Elastic Stack 的核心,Elastic Stack 包括 Kibana、Beats 和 Logstash 等组件&#xf…

寒假作业:2024/2/14

作业1&#xff1a;编程实现二维数组的杨辉三角 代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc, const char *argv[]) {int n;printf("please enter n:");scanf("%d",&n);int a…

Windows 安装Redis教程

在Windows系统上安装Redis相对简单&#xff0c;主要步骤包括下载、解压、配置和启动Redis服务。以下是一个详细的安装教程&#xff1a; 1. 下载Redis 访问Redis官方网站下载页面&#xff1a;https://redis.io/download选择适用于Windows的安装包&#xff0c;通常有两个版本&a…

蓝桥杯---奇怪的数列

题目描述 从X星截获一份电码&#xff0c;是一些数字&#xff0c;如下&#xff1a; 13 1113 3113 132113 1113122113 .... YY博士经彻夜研究&#xff0c;发现了规律&#xff1a; 第一行的数字随便是什么&#xff0c;以后每一行都是对上一行“读出来” 比如第2行&#xff0c;是对…

springboot开启mybatis二级缓存

我的项目版本号如下&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.8</version><relativePath/> <!-- lookup parent from reposito…

Redis核心技术与实战【学习笔记】 - 31.番外篇:Redis客户端如何与服务器端交换命令和数据

简述 Redis 使用 RESP 协议&#xff08;Redis Serialzation Protocol&#xff09;协议定义了客户端和服务器端交互的命令、数据的编码格式。在 Redis 2.0 版本中&#xff0c;RESP 协议正式称为客户端和服务器端的标准通信协议。从 Redis 2.0 到 Redis 5.0 &#xff0c;RESP 协…

leetcode:55.跳跃游戏

1.解题思路&#xff1a;贪心算法看最大覆盖范围 2.模拟过程&#xff1a; 1.若数组长度等于1&#xff0c;直接返回True 2.循环遍历覆盖范围&#xff0c;选取最大的覆盖范围&#xff1b;若覆盖范围覆盖到了最后一个元素&#xff0c;直接返回true. 3.代码&#xff1a;(贪心无套…

Python struct.pack/struct.unpack 和 encoding/decoding的区别

一直觉得这两对函数有种微妙的对应&#xff0c;两者都涉及到数据的转换&#xff0c;struct.pack/struct.unpack 在二进制数据和 Python 对象之间进行转换&#xff0c;而 encoding/decoding 在文本数据和字节流之间进行转换 下面理一理它们的区别&#xff1a; 目的和用途&#…

ros自定义msg记录

文章目录 自定义msg1. 定义msg文件2. 修改 package.xml3. 修改 CMakeLists.txt4. message_publisher.py5. message_subscriber.py6. 运行 catkin build 测试 自定义msg ros 版本&#xff1a;kinetic 自定义test包的文件结构如下 |-- test | |-- CMakeLists.txt | |-- msg…