c++11实现异步定时器

    c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。 
    定时器要求在固定的时间异步执行一个操作,比如boost库中的boost::asio::deadline_timer,以及MFC中的定时器。这里,利用c++11的thread, mutex, condition_variable 来实现一个定时器: 
    定时器要求异步执行任务    ----> 开辟独立的线程 
    定时器要求能够启动和取消 ----> 提供安全的取消操作,使用互斥量和信号量 
    定时器要求每个定时时刻到达的时候执行的任务要尽可能节省时间

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef TIMER_H_
#define TIMER_H_
#include<functional>
#include<chrono>
#include<thread>
#include<atomic>
#include<memory>
#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();
        //      std::cout << "timer destructed!" << std::endl;
    }
 
    void StartTimer(int interval, std::function<void()> task){
        if (expired_ == false){
            //          std::cout << "timer is currently running, please expire it first..." << std::endl;
            return;
        }
        expired_ = false;
        std::thread([this, interval, task](){
            while (!try_to_expire_){
                std::this_thread::sleep_for(std::chrono::milliseconds(interval));
                task();
            }
            //          std::cout << "stop task..." << std::endl;
            {
                std::lock_guard<std::mutex> locker(mutex_);
                expired_ = true;
                expired_cond_.notify_one();
            }
        }).detach();
    }
 
    void Expire(){
        if (expired_){
            return;
        }
 
        if (try_to_expire_){
            //          std::cout << "timer is trying to expire, please wait..." << std::endl;
            return;
        }
        try_to_expire_ = true;
        {
            std::unique_lock<std::mutex> locker(mutex_);
            expired_cond_.wait(locker, [this]{return expired_ == true; });
            if (expired_ == true){
                //              std::cout << "timer expired!" << std::endl;
                try_to_expire_ = false;
            }
        }
    }
     
    template<typename callable, class... arguments>
    void SyncWait(int after, callable&& f, arguments&&... args){
 
        std::function<typename std::result_of<callable(arguments...)>::type()> task
            (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...));
        std::this_thread::sleep_for(std::chrono::milliseconds(after));
        task();
    }
    template<typename callable, class... arguments>
    void AsyncWait(int after, callable&& f, arguments&&... args){
        std::function<typename std::result_of<callable(arguments...)>::type()> task
            (std::bind(std::forward<callable>(f), std::forward<arguments>(args)...));
 
        std::thread([after, task](){
            std::this_thread::sleep_for(std::chrono::milliseconds(after));
            task();
        }).detach();
    }
     
private:
    std::atomic<bool> expired_;
    std::atomic<bool> try_to_expire_;
    std::mutex mutex_;
    std::condition_variable expired_cond_;
};
#endif
 
////////////////////test.cpp
#include<iostream>
#include<string>
#include<memory>
#include"Timer.hpp"
using namespace std;
void EchoFunc(std::string&& s){
    std::cout << "test : " << s << endl;
}
 
int main(){
    Timer t;
    //周期性执行定时任务
    t.StartTimer(1000, std::bind(EchoFunc,"hello world!"));
    std::this_thread::sleep_for(std::chrono::seconds(4));
    std::cout << "try to expire timer!" << std::endl;
    t.Expire();
 
    //周期性执行定时任务
    t.StartTimer(1000, std::bind(EchoFunc,  "hello c++11!"));
    std::this_thread::sleep_for(std::chrono::seconds(4));
    std::cout << "try to expire timer!" << std::endl;
    t.Expire();
 
    std::this_thread::sleep_for(std::chrono::seconds(2));
 
    //只执行一次定时任务
    //同步
    t.SyncWait(1000, EchoFunc, "hello world!");
    //异步
    t.AsyncWait(1000, EchoFunc, "hello c++11!");
 
    std::this_thread::sleep_for(std::chrono::seconds(2));
 
    return 0;
}

 

posted @   农民伯伯-Coding  阅读(32157)  评论(13)    收藏  举报
点击右上角即可分享
微信分享提示