前段时间在Linux上做了一个协议转换器,用的是C++。因为需要定时发送报文,所以找了许多Linux下定时器的实现方法,但基本都不太好用,一堆下划线也看得我一个头两个大。那怎么办?自己写一个。
我比较喜欢简单的、面向对象的东西,所以肯定是要封成一个类,这样用的时候直接new出来就可以了,很方便。
这个定时器类的原理就是创建一个线程,在这个线程中去sleep,经过指定时间后触发回调,这样就达到定时器的效果。实现如下:
.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
}
因为定时回调是静态的,所以正常来说在静态方法中只用访问到静态方法或成员。但是又肯定会有需要在回调中调用非静态成员或方法的情况出现,这个时候可以人为地定义一个静态指针,使它在所属类实例化的时候指向对象自身(有些类似于单例模式)。代码如下:
.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;
}
优点:使用简单
缺点:精度不足,只适用于精度要求不高的场合
原文:https://www.cnblogs.com/super970216/p/15047705.html