Linux下C++定时器类Timer

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、说明

优点:使用简单,可以new出多个定时器

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

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

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Linux下C++定时器类Timer

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/212456

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午1:16
下一篇 2023年2月13日 上午1:17

相关推荐