首页 > 编程语言 > 详细

Linux下C++定时器类Timer

时间:2021-07-23 11:26:17      阅读:42      评论:0      收藏:0      [点我收藏+]

Linux下C++定时器类Timer


前段时间在Linux上做了一个协议转换器,用的是C++。因为需要定时发送报文,所以找了许多Linux下定时器的实现方法,但基本都不太好用,一堆下划线也看得我一个头两个大。那怎么办?自己写一个。


1、思路

我比较喜欢简单的、面向对象的东西,所以肯定是要封成一个类,这样用的时候直接new出来就可以了,很方便。

这个定时器类的原理就是创建一个线程,在这个线程中去sleep,经过指定时间后触发回调,这样就达到定时器的效果。实现如下:


2、代码

.h

#ifndef TIMER_H
#define TIMER_H

#include <stdio.h>
#include <unistd.h>
#include <functional>
#include <thread>
#include <pthread>
#include <iostream>

class Timer {
private:
    unsigned seconds = 0;
    
    bool isAlive = false;
    
public:
    Timer(unsigned seconds);
    
    ~Timer();
    
    void start(std::function<void ()> handle);
    
    void recycle(std::function<void ()> handle);
    
    void stop();
};

#endif

.cpp

#include "Timer.h"

Timer::Timer(unsigned seconds) {
    this->seconds = seconds;
}

Timer::~Timer() {
    
}

void Timer::start(std::function<void ()> handle) {
    if (!this->isAlive) {
        this->isAlive = true;
        
        auto timeThread = [=] {
            for (int i = 0; i< (this->seconds * 1000); i++) {
                if (this->isAlive) {
                    usleep(1000);
                } else {
                    return;
                }
            }
            
            if (this->isAlive) {
                handle();
            }
            
            this->stop();
            return;
        };
        
        std::thread t(timeThread);
        t.detach();
    }
}

void Timer::recycle(std::function<void ()> handle) {
    if (!this->isAlive) {
        this->isAlive = true;

        auto timeThread = [=] {
            while (this->isAlive) {
                for (int i = 0; i < (this->seconds * 1000); i++) {
                    if (this->isAlive) {
                        usleep(1000);
                    } else {
                        return;
                    }
                }

                if (this->isAlive) {
                    handle();
                }
            }
        };
            
        std::thread t(timeThread);
        t.detach();
    }
}

void Timer::stop() {
    this->isAlive = false;
}

Test.h

#ifndef TIMER_TEST_H
#define TIMER_TEST_H

class TimerTest {
private:
    Timer* t;
    
    // 定义一个回调,注意是静态的
    static void onTimeout();

public:
    TimerTest();
    
    ~TimerTest();
    
    void testStart();
    
    void testRecycle();
    
    void testStop();
};

#endif

Test.cpp

#include "TimerTest.h"

TimerTest::TimerTest() {
    this->t = nullptr;
}

TimerTest::~TimerTest() {
    delete this->t;
    this->t = nullptr;
}

void onTimeout() {
    std::cout << "timer run" << std::endl;
}

void TimerTest::testStart() {
    if (this->t == nullptr) {
        this->t = new Timer(10); // new一个10秒延时的定时器出来
    }
    this->t->start(onTimeout); // 传入回调,10秒后执行回调一次,任务结束
}

void TimerTest::testRecycle() {
    if (this->t == nullptr) {
        this->t = new Timer(10);
    }
    this->t->recycle(onTimeout); // 传入回调,循环定时,每10秒执行一次回调
}

void TimerTest::testStop() {
    if (this->t == nullptr) {
        this->t = new Timer(10);
    }   
    this->t->start(onTimeout);
    this->t->stop(); // 停掉前面的start
    
    this->t->recycle(onTimeout);
    this->t->stop(); // 停掉前面的recycle
}

3、回调中访问非静态成员或方法

因为定时回调是静态的,所以正常来说在静态方法中只用访问到静态方法或成员。但是又肯定会有需要在回调中调用非静态成员或方法的情况出现,这个时候可以人为地定义一个静态指针,使它在所属类实例化的时候指向对象自身(有些类似于单例模式)。代码如下:

.h

// 例如我们需要在onTimeout回调中调用Test类中的非静态成员或方法
// 我们可以在Test类中定义一个指向Test类的静态指针,并在构造方法中给它赋值this使它指向对象本身
// 这样我们就可以通过在onTimeout中使用这个静态指针来访问Test类中的非静态成员或方法

#ifndef TIMER_TEST_H
#define TIMER_TEST_H

class TimerTest {
private:
    Timer* t;
    
    // 定义一个回调,注意是静态的
    static void onTimeout();
    
    // 现在有一个非静态成员
    std::string hi = "hello";
    
    // 还有一个非静态方法
    void sayHi();
    
    // 那么我们定义一个静态指针
    static TimerTest* self;

public:
    TimerTest();
    
    ~TimerTest();
    
    void testStart();
    
    void testRecycle();
    
    void testStop();
};

#endif

.cpp

// 我们要在回调中访问hi和sayHi()

// 初始化静态指针
TimerTest* TimerTest::self = nullptr;

// 给它this
TimerTest::TimerTest() {
    self = this;
}

//回调中访问
void TimerTest::onTimeout() {
    std::cout << self->hi << std::endl; // 访问非静态成员
    self->sayHi(); // 访问非静态方法
}

void TimerTest::sayHi() {
    std::cout << this->hi << std::endl;
}

4、说明

优点:使用简单

缺点:精度不足,只适用于精度要求不高的场合

Linux下C++定时器类Timer

原文:https://www.cnblogs.com/super970216/p/15047705.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!