深入解析evpp项目中的自管理定时器实现

深入解析evpp项目中的自管理定时器实现

evpp A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols. evpp 项目地址: https://gitcode.com/gh_mirrors/ev/evpp

前言

在evpp这个基于C++11的高性能网络库中,实现了一个非常精巧的自管理定时器功能。这个定时器不仅能够自动执行预设的回调函数,还能在不需要时自动销毁自己,极大地简化了开发者的使用负担。本文将深入剖析这一功能的实现原理和技术细节。

基础概念

定时器的基本需求

一个完善的定时器通常需要满足以下基本需求:

  1. 能够在指定时间后触发回调
  2. 能够被取消
  3. 能够自动管理生命周期
  4. 支持周期性触发

关键技术点

实现这样一个定时器需要解决几个关键技术问题:

  1. 如何确保定时器对象在回调执行期间不会被意外销毁
  2. 如何实现定时器的自我销毁
  3. 如何支持定时器的取消操作
  4. 如何实现周期性定时器

基础实现

最简单的定时器

最基础的定时器实现非常简单:

class InvokeTimer {
public:
    InvokeTimer(event_base* evloop, double timeout_ms, const std::function<void()>& f);
    ~InvokeTimer();
    void Start();
private:
    event_base* loop_;
    double timeout_ms_;
    std::function<void()> functor_;
    std::shared_ptr<TimerEventWatcher> timer_;
};

这种实现方式虽然简单,但存在明显的问题:定时器的生命周期需要由调用者管理,容易造成内存泄漏或提前销毁的问题。

自我管理实现

自我销毁机制

为了实现定时器的自我管理,我们可以在回调函数中执行delete this

void InvokeTimer::OnTimerTriggered() {
    functor_();
    delete this;
}

这种方式虽然解决了生命周期管理问题,但存在以下限制:

  1. 对象必须在堆上创建
  2. 无法在定时器触发前取消
  3. 无法支持周期性定时器

智能指针解决方案

使用shared_ptr和enable_shared_from_this

更完善的解决方案是使用shared_ptrenable_shared_from_this

class InvokeTimer : public std::enable_shared_from_this<InvokeTimer> {
public:
    static std::shared_ptr<InvokeTimer> Create(event_base* evloop, 
                                             double timeout_ms, 
                                             const std::function<void()>& f);
private:
    std::shared_ptr<InvokeTimer> self_; // 持有自身的引用
};

这种实现的关键点在于:

  1. 定时器对象持有自身的shared_ptr引用
  2. 在回调完成后再释放这个引用
  3. 支持外部通过shared_ptr持有定时器

取消机制实现

基于shared_ptr的实现可以很方便地支持取消操作:

void InvokeTimer::Cancel() {
    if (timer_) {
        timer_->Cancel();
    }
}

取消时会触发取消回调,然后释放自身引用:

void InvokeTimer::OnCanceled() {
    if (cancel_callback_) {
        cancel_callback_();
    }
    self_.reset(); // 释放自身引用
}

周期性定时器实现

周期性触发机制

在回调函数中重新启动定时器即可实现周期性触发:

void InvokeTimer::OnTimerTriggered() {
    functor_();
    if (periodic_) {
        timer_->AsyncWait(); // 重新启动定时器
    } else {
        self_.reset(); // 单次定时器则释放自身
    }
}

实现细节分析

引用计数管理

整个实现中最关键的部分是引用计数的管理:

  1. 创建时:self_ = shared_from_this()增加引用计数
  2. 触发或取消时:self_.reset()减少引用计数
  3. 外部持有shared_ptr也会影响引用计数

线程安全性考虑

由于libevent本身是线程安全的,且shared_ptr的引用计数操作是原子的,因此这个实现在多线程环境下也是安全的。

使用示例

基本使用

auto timer = InvokeTimer::Create(base, 1000.0, []{
    std::cout << "Timer triggered" << std::endl;
});
timer->Start();

周期性定时器

auto timer = InvokeTimer::Create(base, 1000.0, []{
    std::cout << "Periodic timer" << std::endl;
}, true);
timer->Start();

取消定时器

auto timer = InvokeTimer::Create(base, 1000.0, []{
    std::cout << "This won't be printed" << std::endl;
});
timer->Start();
// ...
timer->Cancel();

性能考量

这种实现方式的性能特点:

  1. 创建和销毁涉及shared_ptr操作,有一定开销
  2. 定时器触发时只有一次函数调用开销
  3. 内存占用较小,只有一个shared_ptr和几个基本成员

总结

evpp中的自管理定时器实现展示了C++11智能指针的强大能力,通过shared_ptrenable_shared_from_this的巧妙组合,实现了既安全又易用的定时器功能。这种模式不仅适用于定时器,也可以推广到其他需要自我管理的异步对象实现中。

对于开发者来说,理解这种实现方式的原理和细节,有助于在自己的项目中实现类似的功能,或者更好地使用evpp提供的定时器功能。

evpp A modern C++ network library for developing high performance network services in TCP/UDP/HTTP protocols. evpp 项目地址: https://gitcode.com/gh_mirrors/ev/evpp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

虞熠蝶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值