使用boost的deadline_timer實現一個異步定時器

概述

最近在工做上須要用到定時器,而後看到boost裏面的deadline_timer能夠實現一個定時器,因此就直接將其封裝成了ATimer類,方便使用,ATimer有如下優勢:ios

  1. 能夠支持納秒、毫秒、秒、分、小時定時。
  2. 能夠隨時中止定時器。
  3. 支持單次調用。
  4. 由於使用了deadline_timer,因此定時比較準確。

ATimer和Qt的QTimer使用方法相似,若沒有相似的Timer類,使用最原始的方法,咱們的代碼可能會是這樣的:git

m_timerThread = std::thread([this]
{
    while (!m_bThreadStoped)
    {
        ++m_sleepCount;
        Sleep(SLEEP_DURATION_TIME);

        if (m_sleepCount == m_sleepAllCount)
        {
            m_sleepCount = 0;
            doSomeThing();
        }
    }
});

若使用QTimer的話,書寫是這樣的:github

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);

再來看看ATimer的使用:async

ATimer<> t;
t.bind([]{ std::cout << "Hello C++" << std::endl; });
t.start(1000);

從上面的例子能夠看到,QTimer和ATimer的使用都很是方便,接下來看看ATimer的具體實現:this

// ATimer.hpp
#ifndef _ATIMER_H
#define _ATIMER_H

#include <vector>
#include <thread>
#include <atomic>
#include <functional>
#include <boost/timer.hpp>
#include <boost/asio.hpp>

template<typename Duration = boost::posix_time::milliseconds>
class ATimer
{
public:
    ATimer() : m_timer(m_ios, Duration(0)), m_isSingleShot(false) {}
    ~ATimer()
    {
        stop();
    }

    void start(unsigned int duration)
    {
        if (m_ios.stopped())
        {
            return;
        }

        m_isActive = true;
        m_duration = duration;
        m_timer.expires_at(m_timer.expires_at() + Duration(m_duration));
        m_func = [this]
        {
            m_timer.async_wait([this](const boost::system::error_code&)
            {
                for (auto& func : m_funcVec)
                {
                    func();
                }

                if (!m_isSingleShot)
                {
                    m_timer.expires_at(m_timer.expires_at() + Duration(m_duration));
                    m_func();
                }
            });
        };

        m_func();
        m_thread = std::thread([this]{ m_ios.run(); });
    }

    void stop()
    {
        m_ios.stop();
        if (m_thread.joinable())
        {
            m_thread.join();
        }
        m_isActive = false;
    }

    void bind(const std::function<void()>& func)
    {
        m_funcVec.emplace_back(func);
    }

    void setSingleShot(bool isSingleShot)
    {
        m_isSingleShot = isSingleShot; 
    }

    bool isSingleShot() const
    {
        return m_isSingleShot;
    }

    bool isActive() const
    {
        return m_isActive;
    }

private:
    boost::asio::io_service m_ios;
    boost::asio::deadline_timer m_timer;
    std::function<void()> m_func = nullptr;
    std::vector<std::function<void()>> m_funcVec;
    std::thread m_thread;
    unsigned int m_duration = 0;
    std::atomic<bool> m_isSingleShot;
    bool m_isActive = false;
};

#endif

下面是ATimer的具體使用例子:atom

// main.cpp
#include <iostream>
#include "ATimer.hpp"

void test()
{
    std::cout << "Timer thread id: " << std::this_thread::get_id() << std::endl;
}

int main()
{
    std::cout << "Main thread id: " << std::this_thread::get_id() << std::endl;

    ATimer<boost::posix_time::minutes> t0;
    t0.setSingleShot(true);// 單次調用
    t0.bind(test);
    t0.start(1);// 一分鐘以後調用

    ATimer<> t;//默認使用毫秒定時器
    t.bind(test);
    t.bind([]{ std::cout << "Hello C++" << std::endl; });
    t.start(1000);//每1000ms調用一次

    std::cin.get();
    t0.stop();
    t.stop();
    std::cout << "Tiemr stop" << std::endl;

    std::cin.get();
    std::cout << "Process end" << std::endl;

    return 0;
}

該例子的github地址:https://github.com/chxuan/samples/tree/master/ATimercode

相關文章
相關標籤/搜索