timer

mac2026-08-30  11

#pragma once #include <stdint.h> #include <mutex> #include <list> #include <atomic> #include <vector>

#define  CountArrar(arr) (sizeof(arr)/sizeof(arr[0]))

class TimeWheel { private:     struct TimerEvent{         uint16_t    server_id_;         clock_t        interval_;         clock_t        nxt_trigger_time_;         void(*call_back_)(void* data);         void*        data_;         uint32_t    timer_id_;         int            repeat_;     };     typedef std::list<TimerEvent*> list_timer_event; public:     const static int s_arr_timer_count = 4;          static TimeWheel* get_instance(){ return &s_instance; }

    void        init();     bool        run_sink();     uint32_t    add_timer(uint16_t server_id, int interval, void(*call_back)(void*), void* data, int repeat = 1);     bool        delete_timer(uint32_t timer_id); private:     TimeWheel() {}     TimeWheel(const TimeWheel&) {}     ~TimeWheel();

    void        add(TimerEvent* timer_event);     inline TimerEvent* create_timer();     inline void release_timer(TimerEvent* timer_event);

    static TimeWheel s_instance;     const static int            s_arr_timer[s_arr_timer_count - 1]; private:     bool                    running_;     std::atomic<uint32_t>    cur_time_id_;

    clock_t                    cur_clock_;

    clock_t                    nxt_clock_[s_arr_timer_count - 1];     list_timer_event         timer_type_[s_arr_timer_count];     list_timer_event        timer_storage_;     list_timer_event        timer_all_;     std::mutex                timer_mutex_; };

 

///

#include "TimeWheel.h" #include<thread> #include <ctime>

TimeWheel TimeWheel::s_instance; const int TimeWheel::s_arr_timer[s_arr_timer_count - 1] = { 1000, 60 * 1000, 60 * 60 * 1000 };

TimeWheel::~TimeWheel(){     for (auto it : timer_all_){         delete it;     }     timer_all_.clear();     timer_storage_.clear();     for (int i = 0; i < s_arr_timer_count; i++){         timer_type_[i].clear();     } }

void TimeWheel::init(){     clock_t clock = static_cast<clock_t> (std::clock() * 1000 / CLOCKS_PER_SEC);

    for (int i = 0; i < CountArrar(nxt_clock_); i++){         nxt_clock_[i] = clock + s_arr_timer[i];     } }

bool TimeWheel::run_sink(){     std::this_thread::sleep_for(std::chrono::milliseconds(20));

    std::unique_lock<std::mutex> lock(timer_mutex_);     clock_t clock = static_cast<clock_t> (std::clock() * 1000 / CLOCKS_PER_SEC);

//    list_timer_event ll;     bool big_clock = false;     for (int i = CountArrar(nxt_clock_) - 1; i >= 0; i--){         if (big_clock || clock >= nxt_clock_[i]){             big_clock = true;             nxt_clock_[i] = clock + s_arr_timer[i];             for (auto it = timer_type_[i + 1].begin(); it != timer_type_[i + 1].end(); ){                 if ((*it)->nxt_trigger_time_ - clock < s_arr_timer[i]){         //            if (!add(*it)){         //                ll.push_back(*it);         //            }                     timer_type_[i].push_back(*it);                     it = timer_type_[i + 1].erase(it);                 }                 else{                     it++;                 }             }         }     }

    for (auto it = timer_type_[0].begin(); it != timer_type_[0].end();){         bool erase = false;         if ((*it)->nxt_trigger_time_ <= clock){             (*it)->call_back_((*it)->data_);// need to post

            if (--(*it)->repeat_ <= 0){                 release_timer(*it);                 it = timer_type_[0].erase(it);                 erase = true;             }             else{                 (*it)->nxt_trigger_time_ = clock + (*it)->interval_;                 if ((*it)->interval_ >= s_arr_timer[0]){                     add(*it);                     it = timer_type_[0].erase(it);                     erase = true;                 }             }         }         if (!erase){             it++;         }     }

//     for (auto it : ll){ //         if (--(it->repeat_) > 0){ //             // post //             it->nxt_trigger_time_ += it->interval_; //             add(it); //         } //         it->call_back_(it->data_); //     }

    return true; }

void TimeWheel::add(TimerEvent* timer_event) {     for (int i = CountArrar(nxt_clock_) - 1; i >= 0; i--){         if (timer_event->nxt_trigger_time_ >= nxt_clock_[i]){             timer_type_[i + 1].push_back(timer_event);             return;         }     }

    timer_type_[0].push_back(timer_event);     return; }

uint32_t TimeWheel::add_timer(uint16_t server_id, int interval, void(*call_back)(void*), void* data, int repeat/* = 1*/){     if (interval <= 0){         return 0;     }     std::unique_lock<std::mutex> lock(timer_mutex_);

    TimerEvent* timer_event = create_timer();     timer_event->timer_id_ = cur_time_id_++;     timer_event->server_id_ = server_id;     timer_event->interval_ = static_cast<clock_t>(interval);     timer_event->call_back_ = call_back;     timer_event->data_ = data;     timer_event->nxt_trigger_time_ = timer_event->interval_ + static_cast<clock_t> (std::clock() * 1000 / CLOCKS_PER_SEC);     timer_event->repeat_ = repeat;

    add(timer_event);     return timer_event->timer_id_; }

bool TimeWheel::delete_timer(uint32_t timer_id){     std::unique_lock<std::mutex> lock(timer_mutex_);

    for (int i = 0; i < CountArrar(timer_type_); i++){         auto& ll = timer_type_[i];         for (auto it = ll.begin(); it != ll.end(); it++){             if ((*it)->timer_id_ == timer_id){                 release_timer(*it);                 ll.erase(it);                 return true;             }         }     }

    return false; }

inline TimeWheel::TimerEvent* TimeWheel::create_timer(){     TimerEvent* timer_event = nullptr;     if (timer_storage_.empty()){         try         {             timer_event = new TimerEvent;             timer_all_.push_back(timer_event);         }         catch (...)         {             // log error             exit(1);         }     }     else{         timer_event = timer_storage_.front();         timer_storage_.pop_front();     }     memset(timer_event, 0, sizeof(*timer_event));     return timer_event; }

inline void TimeWheel::release_timer(TimerEvent* timer_event){     timer_storage_.push_back(timer_event); }  

 

// Time.cpp : 定义控制台应用程序的入口点。 // #include "TimeWheel.h" #include <thread> #include <iostream> using namespace std;

int _tmain(int argc, _TCHAR* argv[]) {     TimeWheel* time_wheel =  TimeWheel::get_instance();     std::thread t([&]{         time_wheel->init();         while (1){             if (!time_wheel->run_sink()){                 break;             }         }          });     t.detach();

    time_wheel->add_timer(1, 100, [](void*){         cout << "100 is called" << endl;     }, nullptr, 100);

    int id = time_wheel->add_timer(1, 1000, [](void*){         cout << "1000 is called ***********" << endl;     }, nullptr, 100);

    time_wheel->add_timer(1, 10000, [](void*){         cout << "10000 is called" << endl;     }, nullptr, 100);

    time_wheel->add_timer(1, 300, [](void*){         cout << "300 is called" << endl;     }, nullptr, 100);

    int nloop = 0;     while (1)     {         this_thread::sleep_for(chrono::milliseconds(1500));         time_wheel->add_timer(1, 1000, [](void*){             cout << "1000 2 is called" << endl;         }, nullptr);

        if (nloop++ == 2)             time_wheel->delete_timer(id);     }

    return 0; }

 

 

最新回复(0)