zoukankan      html  css  js  c++  java
  • c++定时器

    定时器作为常用的组件,通常的实现方式有几种:链表,最小堆,时间轮,等等。

    1 链表

    性能比较弱,适用于简单的场景,查询、插入、删除效率都不高

    2 最小堆

    性能比较高,适用于定时器需求较多的场景

    3 时间轮

    性能比较高,适用于定时器需求很大的场景

        在网上查了一些资料,真正可以直接用的代码并不多,不可以直接运行,就不能给读者以更加感性的认识,也就不愿意更多的去分析代码和学习。所以,以 https://www.cnblogs.com/junye/p/5836552.html 为例,将它的最小堆实现,做了一些修改,可以接在gcc 4.8.2以上的环境编译通过并运行。将代码保存为 a.cc,编译命令为

    g++ -g -o a a.cc -std=c++11
    

    具体的代码如下:

    #include <iostream>
    #include <chrono>
    #include <thread>
    #include <vector>
    #include <sys/time.h>
    
    // global declaration
    typedef void (*Fun)(void);
    
    class Timer;
    class TimerManager;
    
    // header file for Timer
    class Timer
    {
    public:
        enum TimerType { ONCE, CIRCLE };
    
        Timer(TimerManager& manager);
        ~Timer();
    
        void Start(Fun fun, unsigned interval, TimerType timeType = CIRCLE);
        void Stop();
    
    private:
        void OnTimer(unsigned long long now);
    
    private:
        friend class TimerManager;
        TimerManager& manager_;
        TimerType timerType_;
        Fun timerFun_;
        unsigned interval_;
        unsigned long long expires_;
    
        int heapIndex_;
    };
    
    // header file for TimerManager
    class TimerManager
    {
    public:
        static unsigned long long GetCurrentMillisecs();
        void DetectTimers();
    
    private:
        friend class Timer;
        void AddTimer(Timer* timer);
        void RemoveTimer(Timer* timer);
    
        void UpHeap(int index);
        void DownHeap(int index);
        void SwapHeap(int, int index2);
    
    private:
        struct HeapEntry
        {
            unsigned long long time;
            Timer* timer;
        };
        std::vector<HeapEntry> heap_;
    };
    
    // implemetation of Timer
    
    Timer::Timer(TimerManager& manager)
        : manager_(manager)
        , heapIndex_(-1)
    {
        // to-do
    }
    
    Timer::~Timer()
    {
        Stop();
    }
    
    inline void Timer::Start(Fun fun, unsigned interval, TimerType timeType)
    {
        Stop();
        interval_ = interval;
        timerFun_ = fun;
        timerType_ = timeType;
        this->expires_ = this->interval_ + TimerManager::GetCurrentMillisecs();
        manager_.AddTimer(this);
    }
    
    void Timer::Stop()
    {
        if (heapIndex_ != -1)
        {
            manager_.RemoveTimer(this);
            heapIndex_ = -1;
        }
    }
    
    void Timer::OnTimer(unsigned long long now)
    {
        if (timerType_ == Timer::CIRCLE)
        {
            expires_ = interval_ + now;
            manager_.AddTimer(this);
        }
        else
        {
            heapIndex_ = -1;
        }
        timerFun_();
    }
    
    // implemetation of TimerManager
    
    void TimerManager::AddTimer(Timer* timer)
    {
        timer->heapIndex_ = heap_.size();
        HeapEntry entry = { timer->expires_, timer };
        heap_.push_back(entry);
        UpHeap(heap_.size() - 1);
    }
    
    void TimerManager::RemoveTimer(Timer* timer)
    {
        int index = timer->heapIndex_;
        if (!heap_.empty() && index < heap_.size())
        {
            if (index == heap_.size() - 1)
            {
                heap_.pop_back();
            }
            else
            {
                SwapHeap(index, heap_.size() - 1);
                heap_.pop_back();
                int parent = (index - 1) / 2;
                if (index > 0 && heap_[index].time < heap_[parent].time)
                {
                    UpHeap(index);
                }
                else
                {
                    DownHeap(index);
                }
            }
        }
    }
    
    void TimerManager::DetectTimers()
    {
        unsigned long long now = GetCurrentMillisecs();
    
        while (!heap_.empty() && heap_[0].time <= now)
        {
            Timer* timer = heap_[0].timer;
            RemoveTimer(timer);
            timer->OnTimer(now);
        }
    }
    
    void TimerManager::UpHeap(int index)
    {
        int parent = index >> 1;
        while (index > 0 && heap_[index].time < heap_[parent].time)
        {
            SwapHeap(index, parent);
            index = parent;
            parent = index >> 1;
        }
    }
    
    void TimerManager::DownHeap(int index)
    {
        int child = (index << 1) + 1;
        while (child < heap_.size())
        {
            int minChild = (child + 1 == heap_.size() || heap_[child].time < heap_[child + 1].time)? child : child + 1;
            if (heap_[index].time < heap_[minChild].time)
                break;
            SwapHeap(index, minChild);
            index = minChild;
            child = (index << 1) + 1;
        }
    }
    
    void TimerManager::SwapHeap(int index1, int index2)
    {
        HeapEntry tmp = heap_[index1];
        heap_[index1] = heap_[index2];
        heap_[index2] = tmp;
        heap_[index1].timer->heapIndex_ = index1;
        heap_[index2].timer->heapIndex_ = index2;
    }
    
    unsigned long long TimerManager::GetCurrentMillisecs()
    {
        timeval tv;
        ::gettimeofday(&tv, 0);
        unsigned long long ret = tv.tv_sec;
        return ret * 1000 + tv.tv_usec / 1000;
    }
    
    // test code
    
    void TimerHandler_1()
    {
        std::cout << "TimerHandler_1" << std::endl;
    }
    
    void TimerHandler_2()
    {
        std::cout << "TimerHandler_2" << std::endl;
    }
    
    void TimerHandler_3()
    {
        std::cout << "TimerHandler_3" << std::endl;
    }
    
    void TimerHandler_4()
    {
        std::cout << "TimerHandler_4" << std::endl;
    }
    
    int main()
    {
        TimerManager tm;
    
        Timer t1(tm);
        t1.Start(&TimerHandler_1, 1000);
    
        Timer t2(tm);
        t2.Start(&TimerHandler_2, 500);
    
        Timer t3(tm);
        t3.Start(&TimerHandler_3, 1500);
    
        Timer t4(tm);
        t4.Start(&TimerHandler_4, 100);
    
        while (true)
        {
            tm.DetectTimers();
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
        return 0;
    }
    

      

  • 相关阅读:
    Guns 01 项目基本运行
    个人 比较好用的软件
    个人 软件开发 综合技能提升
    开源框架 综合知识
    开源框架 工作流框架
    开源框架 Java 开发框架 1
    开源框架 Java 管理系统
    开源框架 C#
    scp(安全拷贝)和rsync(增量复制)
    完全分布式集群的准备工作
  • 原文地址:https://www.cnblogs.com/warnet/p/10528650.html
Copyright © 2011-2022 走看看