zoukankan      html  css  js  c++  java
  • Linux下的定时器类实现(select定时+线程)

         更好的计时器类实现:LINUX RTC机制实现计时器类(原创)

          很多时候需要在LINUX下用到定时器,但像setitimer()和alarm()这样的定时器有时会和sleep()函数发生冲突,这样就给编程带来了很大的困难。
        写了一个定时器的类,使用select进行精确定时。而且可以在系统中创建不限数量的定时器,且互不干扰。类的内部采用线程实现。即线程+select。代码如下:

    CTimer.h:
    /*
    * CTimer.h
    *
    * Created on: 2009-7-13
    *      Author: DEAN
    */

    //////////////////////////////////////////////////////////////////////////
    // This class provide a timer to finish some works.
    // Call SetTimer() to set the timer_interval. Call StartTimer()
    // to enable it and call StopTimer() to stop it.
    // The work you want to do should be written on OnTimer
    // function.
    //////////////////////////////////////////////////////////////////////////

    #ifndef CTIMER_H_
    #define CTIMER_H_

    #include <pthread.h>
    #include <sys/time.h>

    class CTimer
    {
    private:
        pthread_t thread_timer;
        long m_second, m_microsecond;
        static void *OnTimer_stub(void *p)
        {
            (static_cast<CTimer*>(p))->thread_proc();
        }
        void thread_proc();
        void OnTimer();
    public:
        CTimer();
        CTimer(long second, long microsecond);
        virtual ~CTimer();
        void SetTimer(long second,long microsecond);
        void StartTimer();
        void StopTimer();
    };
    #endif /* CTIMER_H_ */

    CTimer.cpp:
    /*
    * CTimer.cpp
    *
    * Created on: 2009-7-13
    *      Author: DEAN
    */

    #include "CTimer.h"
    #include <iostream>
    #include <sys/select.h>
    #include <time.h>
    #include <pthread.h>

    using namespace std;
    //////////////////////////public methods//////////////////////////
    CTimer::CTimer():
        m_second(0), m_microsecond(0)
    {
    }

    CTimer::CTimer(long second, long microsecond) :
        m_second(second), m_microsecond(microsecond)
    {
    }

    CTimer::~CTimer()
    {
    }

    void CTimer::SetTimer(long second, long microsecond)
    {
        m_second = second;
        m_microsecond = microsecond;
    }

    void CTimer::StartTimer()
    {
        pthread_create(&thread_timer, NULL, OnTimer_stub, this);
    }

    void CTimer::StopTimer()
    {
        pthread_cancel(thread_timer);
        pthread_join(thread_timer, NULL); //wait the thread stopped
    }

    //////////////////////////private methods//////////////////////////
    void CTimer::thread_proc()
    {
        while (true)
        {
            OnTimer();
            pthread_testcancel();
            struct timeval tempval;
            tempval.tv_sec = m_second;
            tempval.tv_usec = m_microsecond;
            select(0, NULL, NULL, NULL, &tempval);
        }
    }

    void CTimer::OnTimer()
    {
        cout<<"Timer once..."<<endl;
    }

    示例代码main.cpp:
    /*
    * main.cpp
    *
    * Created on: 2009-7-19
    *      Author: DEAN
    */

    #include <iostream>
    #include "CTimer.h"

    using namespace std;

    int main()
    {
        CTimer t1(1,0),t2(1,0);    //构造函数,设两个定时器,以1秒为触发时间。参数1是秒,参数2是微秒。
        t1.StartTimer();
        t2.StartTimer();
        sleep(10);
        return 0;
    }

        使用的话其实很简单,只要写一下OnTimer()函数的内容就行了,定时器会在每个定时器触发时调用此函数。里面用到的一个点是使用类的成员函数作为线程体的执行函数,需要进行一下静态类型转换。在上面已标出:
        static void *OnTimer_stub(void *p)
        {
            (static_cast<CTimer*>(p))->thread_proc();
        }
        有了这个类以后,使用定时器就方便多了:-)

    ///LINUX RTC机制实现计时器类(原创) ///////////

    在LINUX中经常要使用计时器,而在LINUX环境下使用计时器不像WINDOWS环境下那样一个SETTIMER()方便,主要有三种方式:使用SLEEP/USLEEP+单独线程;SETITMER加处理信号SIGALRM,或者是RTC机制。这里我讲到的是使用RTC机制实现计时器类。这种方法最为优越,它与传统意义上的SLEEP和SIGALRM信号是分离的,它的运行不受SLEEP的影响,而像SETITMER等都会受到SLEEP的影响,因为它们使用的是同一时钟。
        以前用select实现的计时器类(http://hi.baidu.com/susdisk/blog/item/03f70d35e8e2e182a61e1288.html)其实并不是真正的计时器,它是一个循环,只是在处理完一次ONTIMER()事件后停下了一秒,然后再接着一次ONTIMER(),这其实并不是真正的计时器。真正的计时器应该是不管是否在处理ONTIMER()事件,它都会触发。
        RTC(real-time clock)。现在可以使用LINUX下的RTC机制来编写计时器类,这个类是完全意义上的计时器,经过测试,也基本不占用cpu时间,因为它采用的是底层的硬件时钟,rtc的文档中说的很明白,它与系统时钟最大的区别在于即使它在机器耗能非常低的情况下,也会触发此时钟信号。它也与SLEEP、SETITIMER等函数是完全独立的,就是说,使用这个计时器类,你依然可以使用各种SLEEP函数等,互不影响,这一点我觉得是最重要的。

  • 相关阅读:
    Leetcode 171. Excel Sheet Column Number
    Leetcode 206 Reverse Linked List
    Leetcode 147. Insertion Sort List
    小明一家人过桥
    Leetcode 125. Valid Palindrome
    Leetcode 237. Delete Node in a Linked List
    Leetcode 167 Two Sum II
    张老师的生日
    Leetcode 27. Remove Element
    Leetcode 283. Move Zeroes
  • 原文地址:https://www.cnblogs.com/bigben0123/p/3225699.html
Copyright © 2011-2022 走看看