(P28)muduo_base库源码分析:定时器,lower_bound&upper_bound,RVO

1.定时器

  • muduo的定时器由三个类实现,TimerId(外部类)、Timer、TimerQueue,用户只能看到第一个类,其它两个都是内部实现细节
  • TimerQueue的接口很简单,只有两个函数addTimer和cancel
  • EventLoop
runAt		在某个时刻运行定时器
runAfter		过一段时间运行定时器
runEvery		每隔一段时间运行定时器
上面三个函数会调用到TimerQueue.addTimer()

cancel		取消定时器
会调用到TimerQueue.cancel()
  • TimerQueue数据结构的选择,能快速根据当前时间找到已到期的定时器(到期的定时器能够按照时间先后进行排序),也要高效的添加和删除Timer,因而可以用二叉搜索树,用map或者set
不使用map的原因是:
map<Timestamp, Timer*>,因为TimerQueue管理了很多定时器,有可能2个定时器的时间戳Timestamp是一样的,
但是实际的定时器操作Timer*是不一样的。
map不支持key是一样的,所以不适使用map

可以使用multimap,但是multimap不常用。后期可以尝试使用multimap

使用set的原因是:
typedef std::pair<Timestamp, Timer*> Entry;
typedef std::set<Entry> TimerList;//set只包含一个key,key的类型是pair对
<Timestamp, Timer*> 是整个key,即使Timestamp相等,但是定时器的地址Timer*也是不等的,所以key也是不等的。


  • Channel的时序图
    在这里插入图片描述
  • EventLoop时序图
    (1)Poller返回了activeChannels,首先回调handleEvent(),handleEvent()会根据Channels是POLLIN可读还是可写事件?来调用TimerQueue.handleRead();
    (2)TimerQueue.handleRead()会getExpired()获取所有的超时的定时器,回调onTimer();
    在这里插入图片描述
  • eg:
    28\jmuduo\muduo\net\TimerId.h
    28\jmuduo\muduo\net\Timer.h
    28\jmuduo\muduo\net\Timer.cc
    28\jmuduo\muduo\base\Timestamp.h
    28\jmuduo\muduo\net\TimerQueue.h
    28\jmuduo\muduo\net\TimerQueue.cc
    28\jmuduo\muduo\net\CMakeLists.txt

2.lower_bound&upper_bound

  • eg1:
#include <set>
#include <iostream>

using namespace std;

int main(void)
{
	int a[] = { 1, 2, 3, 4, 5 };
	set<int> s(a, a+5);//key是int,set和map都会自动排序的

	cout<<*s.lower_bound(2)<<endl;//会返回第一个值>=2的迭代器的位置,取*,//应该返回=2
	cout<<*s.upper_bound(2)<<endl; ;//二分查找会返回第一个值>2的迭代器的位置,取*,应该返回=3
	return 0;
}
  • 测试:
    在这里插入图片描述

3.RVO

  • 返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制

  • eg:

struct Foo   
{   
	Foo() { cout << "Foo ctor" << endl; }
	Foo(const Foo&) { cout << "Foo copy ctor" << endl; }
	void operator=(const Foo&) { cout << "Foo operator=" << endl; } 
	~Foo() { cout << "Foo dtor" << endl; }
};  
Foo make_foo()   
{
	//return Foo();
	Foo f;//这里调用构造函数
	return f;//若没有RVO优化,这里会调用拷贝构造函数
		//若有RVO优化,则会将对象f直接返回回去,不需要再拷贝构造,相当于对象f提升了,提升成不是一个局部对象,return时它不会释放的
}  
int main(void)
{
	make_foo();
	return 0;
}

  • 测试
    在这里插入图片描述
    使用vs2008 debug编译运行
    在这里插入图片描述
    在这里插入图片描述
    使用vs2008 release编译运行
    在这里插入图片描述

在这里插入图片描述

  • eg测试:28\jmuduo\tests\Reactor_test04.cc
    28\jmuduo\tests\CMakeLists.txt
  • 测试:
    ./build clean可以清空以前的编译文件
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    直到打印20次时,g_loop->quit(),则这里的loop.loop();也就退出来了
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值