folly中的KeepAlive
KeepAlive是什么?
本质上是Executor的一个指针,如果Executor支持keepAlive功能,那么只要有一个指向该Executor的KeepAlive对象还存活,那么这个Executor就不会被析构。
KeepAlive实现的原理?
KeepAlive对象本质就是一个uintptr_t
(只有一个该成员),但是因为内存对齐的原因,Executor
对象的地址总是4的倍数,也就是说Executor*
的最后两位总是0,KeepAlive在这两位存了信息:最后一位标识所指向的Executor对象是否支持KeepAlive功能(0表示支持),倒数第二位标识Executor对象的析构函数是否需要等待该KeepAlive对象生命周期结束(0表示需要)。
KeepAlive是如何实现让Executor的析构函数等它生命周期结束的呢?
Executor定义了两个接口virtual bool keepAliveAcquire() noexcept
和virtual void keepAliveRelease() noexcept
,在新建KeepAlive对象的时候,调用keepAliveAcquire
接口,在析构的时候调用keepAliveRelease
接口,这样Executor对象就知道有几个KeepAlive
对象存活了
什么情况下Executor对象不需要等待一个KeepAlive对象的生命周期结束呢?
- Executor对象不支持KeepAlive功能
- KeepAlive对象
A
是调用另一个KeepAlive对象B
的get_alias()
方法得到的,此时不需要等待A
的生命周期结束。这个时候需要保证B
的生命周期比A
的要长
【TODO】什么情况下会调用get_alias
呢?
获取KeepAlive对象的方法?
在folly
命名空间中,定义了Executor::KeepAlive<ExecutorT> getKeepAliveToken(ExecutorT* executor)
和Executor::KeepAlive<ExecutorT> getKeepAliveToken(ExecutorT& executor)
两个自由模板函数来获取KeepAlive
对象,Executor
类中也定义了两个同名的static
模板方法。另外,folly
中还定义了Executor::KeepAlive<ExecutorT> getKeepAliveToken(Executor::KeepAlive<ExecutorT>& ka)
来复制一个KeepAlive
对象
KeepAlive类的重要属性?
可复制、移动、赋值
可以直接作为Executor对象的指针使用(定义了operator*
和operator->
),可以判空(定义了operator bool
)
可以get_alias()
获取Executor未记录的KeepAlive对象