Top
C++11标准stl库的timer_C/C++代码_BlackFeather'S Blog
忙忙碌碌,更新不及时诶。

C++11标准stl库的timer

C/C++代码 blackfeather 2502


timer定时器,多线程,回调为阻塞模式。支持参数绑定,非常好使。


用法:

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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//////////////////////////////////////////////////////////////////////////
//以下是测试代码
namespace timertester
{
 
    class timertestclass
    {
    public:
        timertestclass(){};
        ~timertestclass(){};
        void testfn()
        {
            printf("timer callback is class func.\n");
            FTimerEvent mTimer(3000, &timertestclass::threadfn, this);
 
            for (int i = 0; i < 5; i++)
            {
                printf("press any key to ...\n");
                getchar();
                mTimer.SetTimerEvent();
            }
 
            printf("stop timer \n");
            mTimer.StopTimer();
        }
        void threadf(int i)
        {
            printf("test f i:%d\n", i);
        }
        void threadfn()
        {
            printf("test fn d\n");
        }
        void threadfn2()
        {
            printf("test fn2222 \n");
        }
    };
 
 
    static void testfn1(timertestclass *cls)
    {
        cls->threadfn();
    }
    static void testpf()
    {
        printf("test printf \n");
        printf("callback ret. \n");
    }
    static void prt(int& i)
    {
        printf("print %d\n", i);
    }
    static void timertest()
    {
        int t = 0;
        FTimerEvent timerstdref(1000, prt, std::ref(t));
        for (int i = 0; i < 10; i++)
        {
            t = i;
            Sleep(1000);
        }
        timerstdref.StopTimer();
 
        {
            printf("timer 0 manual to set\n");
            //如果定时为0,则每次为手动触发
            FTimerEvent timerman(0, [](){
                printf("timerman in.\n");
                Sleep(5000);
                printf("timerman out.\n");
            });
            timerman.SetTimerEvent();
            timerman.SetTimerEvent();
            timerman.StopTimer();
        }
 
        printf("stop timer in callback\n");
        FTimerEvent timer4;
        timer4.InitTimer(1000, [](FTimerEvent *pTimer){ printf("exit timer\n"); pTimer->StopTimer(); }, &timer4);
        Sleep(3000);
        timer4.StopTimer();
 
        printf("set timer in callback\n");
        FTimerEvent timer5;
        timer5.InitTimer(2000, [](FTimerEvent *pTimer){
            static bool set = false;
            printf("timer in\n");
            if (!set)
            {
                printf("set timer\n");
                pTimer->SetTimerEvent();
                set = true;
            }
            printf("timer out\n");
        }, &timer5);
        Sleep(10000);
        timer5.StopTimer();
 
        timertestclass test1;
        test1.testfn();
 
        int x = 0;
        FTimerEvent timerref(1000, [&x]()
        {
            printf("x: %d \n", x);
        });
        for (int i = 0; i < 10; i++)
        {
            x = i;
            Sleep(1000);
        }
        timerref.StopTimer();
 
        FTimerEvent timerx(1000, [&test1]()
        {
            test1.threadfn2();
        });
        Sleep(10000);
        timerx.StopTimer();
 
        FTimerEvent timer0(1000, testpf);
        Sleep(10000);
        timer0.StopTimer();
 
        FTimerEvent timer1(1000, testfn1, &test1);
        Sleep(10000);
        timer1.StopTimer();
 
        FTimerEvent timer2(1000, [](){ printf("lambada no param \n"); });
        Sleep(10000);
        timer2.StopTimer();
 
        int param = 0;
        FTimerEvent timer3(1000, [](int *p){ printf("lambada with param: %d \n", *p); }, &param);
        Sleep(10000);
        timer3.StopTimer();
 
         
    }
}




Timer.h

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
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once
 
#include <thread>
#include <functional>
#include <chrono>
#include <future>
#include <mutex>
#include <atomic>
#include <condition_variable>
 
class FTimerEvent
{
private:
    std::mutex m_mtx;
    std::condition_variable m_Condition;
 
    std::future<int> m_loopTask;
    std::thread::id m_loopThreadID;
 
    //回调函数
    std::function<void()> m_funCallback;
    //退出标记
    bool m_bExit;
 
    std::atomic<int> m_nManual;
 
    void _InitTimer(uint32_t nTimeout)
    {
        m_nManual = 0;
 
        m_loopTask = std::async(std::launch::async, [this, nTimeout]()->int{
 
            printf("timer thread start...\n");
 
            //保存线程ID
            m_loopThreadID = std::this_thread::get_id();
             
            while (!m_bExit || m_nManual)
            {
                //wait for timeout
                std::unique_lock<std::mutex> lock(m_mtx);
                //bool waitret = false;
                if (nTimeout)
                    m_Condition.wait_for(lock, std::chrono::milliseconds(nTimeout), [this](){return (m_nManual != 0); });
                else
                    m_Condition.wait(lock, [this](){return (m_nManual != 0); });
 
                if (m_bExit && m_nManual == 0)
                    return 0;
 
                if (m_nManual)
                    m_nManual--;
 
                //callback
                //printf("timer call back ... \n");
                m_funCallback();
            }
 
            printf("timer thread exit.\n");
 
            return 0;
        });
 
    }
 
public:
 
    //禁止拷贝和移动
    FTimerEvent(const FTimerEvent&) = delete;
    FTimerEvent& operator=(const FTimerEvent&) = delete;
 
    //默认的构造函数
    FTimerEvent(){ m_bExit = false; };
 
    //带参数的构造函数
    template<class F, class... Args>
    FTimerEvent(uint32_t dwTimeout, F&& f, Args&&... args)
    {
        m_bExit = false;
 
        m_funCallback = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        _InitTimer(dwTimeout);
    }
 
    //如果使用默认构造函数定义的示例 可以手动初始化 不允许重复调用
    template<class F, class... Args>
    bool InitTimer(uint32_t dwTimeout, F&& f, Args&&... args)
    {
        assert(m_funCallback == nullptr);
        if (m_funCallback != nullptr)
            return false;
 
        m_funCallback = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        _InitTimer(dwTimeout);
 
        return true;
    }
 
    ~FTimerEvent(void)
    {
        StopTimer();
 
        printf("Timer has Stopped.  \n");
    }
 
    //阻塞事件,会等所有的回调都完成后再退出
    //如果在回调内部调用,会立即返回
    void StopTimer()
    {
        if (!m_bExit)
            printf("Stop Timer \n");
 
        //stop flag
        m_bExit = true;
 
        //通知一下阻塞事件
        if (std::this_thread::get_id() != m_loopThreadID)
        {
            m_Condition.notify_one();
             
            //等待线程退出
            try
            {
                m_loopTask.get();
            }
            catch (...){}
        }
    }
 
 
    //触发一次事件 异步返回
    //必然触发的回调,哪怕调用了StopTimer也会把Set过的次数都回调一遍再退出
    void SetTimerEvent()
    {
        m_nManual++;
        m_Condition.notify_one();
    }
 
};


评论列表:

发表评论:

验证码