C++ 实现定时器的两种方法

我可以帮助您写一篇关于C++实现定时器的博客。定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。可以利用c++11的thread, mutex, condition_variable 来实现一个定时器。

  1. 使用C++11中的thread, mutex, condition_variable来实现一个定时器
#include <iostream>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>

class Timer {
public:
    Timer() :_expired(true), _try_to_expire(false) {}

    Timer(const Timer& t) {
        _expired = t._expired.load();
        _try_to_expire = t._try_to_expire.load();
    }

    ~Timer() {
        Expire();
    }

    void StartTimer(int interval, std::function<void()> task) {
        if (_expired == false) {
            return;
        }
        _expired = false;
        std::thread([this, interval, task]() {
            while (!_try_to_expire) {
                std::this_thread::sleep_for(std::chrono::milliseconds(interval));
                task();
            }
            {
                std::lock_guard<std::mutex> locker(_mutex);
                _expired = true;
                _expired_cond.notify_one();
            }
        }).detach();
    }

    void Expire() {
        if (_expired) {
            return;
        }

        if (_try_to_expire) {
            return;
        }
        _try_to_expire = true;
        {
            std::unique_lock<std::mutex> locker(_mutex);
            _expired_cond.wait(locker, [this] {return _expired == true; });
            if (_expired == true) {
                _try_to_expire = false;
            }
        }
    }

private:
    std::atomic<bool> _expired;
    std::atomic<bool> _try_to_expire;
    std::mutex _mutex;
    std::condition_variable _expired_cond;
};

int main() {
    Timer t;
    t.StartTimer(1000, []() {std::cout << "Hello World!" << std::endl; });
    std::this_thread::sleep_for(std::chrono::seconds(4));
    t.Expire();
    return 0;
}
  1. 使用时间轮算法:Linux内核就有这个算法。这里也有一个用户态的实现供参考:github.com/facebook/folly。它的高精度版本能实现微妙级别的定时。下面是一个简单的时间轮定时器的C++实现:
#include <chrono>
#include <functional>
#include <list>
#include <mutex>
#include <thread>
#include <vector>

class TimerWheel {
public:
    using Task = std::function<void()>;

    explicit TimerWheel(size_t wheel_size, int interval_ms)
        : wheel_size_(wheel_size),
          interval_ms_(interval_ms),
          wheel_(wheel_size),
          current_index_(0) {}

    ~TimerWheel() {
        Stop();
    }

    void Start() {
        if (running_) {
            return;
        }
        running_ = true;
        thread_ = std::thread([this]() {
            while (running_) {
                std::this_thread::sleep_for(std::chrono::milliseconds(interval_ms_));
                Tick();
            }
        });
    }

    void Stop() {
        if (!running_) {
            return;
        }
        running_ = false;
        if (thread_.joinable()) {
            thread_.join();
        }
    }

    void AddTask(int timeout_ms, Task task) {
        std::lock_guard<std::mutex> lock(mutex_);
        size_t ticks = timeout_ms / interval_ms_;
        size_t index = (current_index_ + ticks) % wheel_size_;
        wheel_[index].push_back(task);
    }

private:
    void Tick() {
        std::lock_guard<std::mutex> lock(mutex_);
        auto& tasks = wheel_[current_index_];
        for (const auto& task : tasks) {
            task();
        }
        //tasks.clear(); 
        current_index_ = (current_index_ + 1) % wheel_size_;
    }

private:
    size_t wheel_size_;
    int interval_ms_;
    std::vector<std::list<Task>> wheel_;
    size_t current_index_;
    bool running_ = false;
    std::thread thread_;
    std::mutex mutex_;
};

int main() {
    TimerWheel timer(10, 1000);
    timer.Start();
    timer.AddTask(3000, []() {std::cout << "Task 1" << std::endl; });
    timer.AddTask(5000, []() {std::cout << "Task 2" << std::endl; });
    std::this_thread::sleep_for(std::chrono::seconds(10));
    timer.Stop();
}

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值