code
header
/*
* 依赖系统实现的定时器
*/
#pragma once
#include <stdint.h>
#include <mutex>
#include <stdio.h>
#include <string.h>
namespace lxz {
// 异步事件型 抽象定时器类
class CAbstractTimer {
public:
virtual ~CAbstractTimer() {}
/*
\brief 启动定时器;若这个定时器正在运行,再次调用则是重新以interval为周期启动
\param interval定时周期
\retval 0:成功;-1:失败
*/
virtual int32_t start(long interval) = 0;
/*
\brief 停止定时器
\retval 0:成功;-1:失败
*/
virtual int32_t stop(void) = 0;
/*
\brief 读取定时器到期次数,读取完成后,内部定时器到期次数清零
\param timeout读取延时时间,单位ms;建议为0,非阻塞方式读取
\retval 定时器到期次数
*/
virtual uint64_t read_events(int32_t timeout) = 0;
};
}
#ifdef __linux__ // 仅适用于linux系统
#include <sys/timerfd.h>
#include <poll.h>
#include <errno.h>
#include <unistd.h>
namespace lxz {
class timer : public CAbstractTimer {
public:
timer();
~timer();
timer(const timer& that) = delete;
timer& operator=(const timer& that) = delete;
int32_t start(long interval) override;
int32_t stop(void) override;
uint64_t read_events(int32_t timeout) override;
protected:
private:
int m_fd;
long m_interval;
std::mutex m_mutex;
};
}
#endif // __linux__
#if ((defined WIN32) || (defined _WIN32) || (defined _WIN64)) // windows平台定时器
#include <Windows.h>
//BOOL CreateTimerQueueTimer(&timer, timerQueue, (WAITORTIMERCALLBACKFUNC)cb, &arg, 0, 1000, WT_EXECUTEDEFAULT);
//BOOL ChangeTimerQueueTimer(HANDLE hTimerQueue, HANDLE hTimer, ULONG dwDueTimer, ULONG dwPeriod);
//BOOL DeleteTimerQueueTimer(HANDLE hTimerQueue,HANDLE hTimer, HANDLE hCompletionEvent);
namespace new3s {
class timer : public CAbstractTimer {
public:
timer();
~timer();
timer(const timer& that) = delete;
timer& operator=(const timer& that) = delete;
int32_t start(long interval) override;
int32_t stop(void) override;
uint64_t read_events(int32_t timeout) override;
protected:
private:
// 定时器到期回调函数
friend static void WINAPI cb(PVOID param, BOOLEAN TimerOrWaitFired) {
if (!param) {
return;
}
lxz::timer* me = (lxz::timer*)param;
std::unique_lock<std::mutex> lock(me->m_mutexCnt);
me->m_eventsCnt++;
}
HANDLE m_timerQueue = nullptr; // 定时器队列,nullptr表示使用默认定时器队列,否则请通过CreateTimerQueue创建
HANDLE m_timer;
long m_interval; // 定时周期
uint64_t m_eventsCnt; // 定时器到期次数
std::mutex m_mutexCnt; // 保护m_eventsCnt
};
}
#endif // WIN32 || _WIN32 || _WIN64
source
#include <ttu_timer.h>
#include <chrono>
#include <thread>
namespace lxz {
#ifdef __linux__
timer::timer() {
m_fd = -1;
m_interval = -1;
}
timer::~timer() {
(void)stop();
}
int32_t timer::start(long interval) {
std::unique_lock<std::mutex> lock(m_mutex);
if (interval <= 0) {
return -1;
}
int ret = -1;
if (m_fd < 0) {
ret = timerfd_create(CLOCK_REALTIME, 0);
if (ret == -1) {
return -1;
}
m_fd = ret;
}
struct itimerspec tim;
struct timespec now;
ret = clock_gettime(CLOCK_REALTIME, &now);
if (ret == -1) {
close(m_fd);
m_fd = -1;
return -1;
}
tim.it_interval.tv_sec = interval;
tim.it_interval.tv_nsec = 0;
tim.it_value.tv_nsec = now.tv_nsec;
tim.it_value.tv_sec = now.tv_sec;
ret = timerfd_settime(m_fd, TFD_TIMER_ABSTIME, &tim, nullptr);
if (ret == -1) {
close(m_fd);
m_fd = -1;
return -1;
}
m_interval = interval;
return 0;
}
int32_t timer::stop(void) {
std::unique_lock<std::mutex> lock(m_mutex);
if (m_fd > 0) {
close(m_fd);
m_fd = -1;
}
return 0;
}
uint64_t timer::read_events(int32_t timeout) {
std::unique_lock<std::mutex> lock(m_mutex);
struct pollfd fds;
uint64_t cnt = 0;
ssize_t n = 0;
fds.fd = m_fd;
fds.events = POLLIN;
fds.revents = 0;
int ret = -1;
ret = poll(&fds, 1, timeout); // timeout ms
if (ret == -1) {
// fprintf(stderr, "poll error,%s\n", strerror(errno));
// continue;
return 0;
}
if (ret == 0) {
// fprintf(stdout, "poll return no event\n");
// continue;
return 0;
}
if ((ret == 1) && (fds.revents == POLLIN)) {
// fprintf(stdout, "poll return read event\n");
n = read(fds.fd, &cnt, sizeof(uint64_t));
if (n < 0) {
// fprintf(stderr, "read error,%s\n", strerror(errno));
// continue;
return 0;
}
if (n != sizeof(uint64_t)) {
// fprintf(stdout, "read return not uint64_t\n");
return 0;
}
return cnt;
}
return 0;
}
#endif // __linux__
#if ((defined WIN32) || (defined _WIN32) || (defined _WIN64))
timer::timer() {
m_timer = nullptr;
m_interval = -1;
m_eventsCnt = 0;
}
timer::~timer() {
(void)stop();
if (m_timer) {
(void)WaitForSingleObject(m_timer, 0);
}
if (m_timerQueue) {
(void)WaitForSingleObject(m_timerQueue, 0);
}
}
int32_t timer::start(long interval) {
std::unique_lock<std::mutex> lock(timer::m_mutexCnt);
BOOL ret = FALSE;
// 未创建过定时器时 初次调用start就是创建
if (!m_timer) {
ret = CreateTimerQueueTimer(&m_timer, // 待创建的定时器
m_timerQueue, // 要附加到的定时器队列,为NULL表示默认队列
(WAITORTIMERCALLBACKFUNC)cb, // 到期回调函数
this, // 回调函数的参数
0, // 启动延时,0表示即刻启动
(DWORD)interval, // 定时周期
WT_EXECUTEDEFAULT); // 默认参数
if (!ret) {
//fprintf_s(stderr, "CreateTimerQueueTimer failed\n");
return -1;
}
m_eventsCnt = 0;
m_interval = interval;
return 0;
}
// 已创建定时器时 再次调用start就是修改
else {
ret = ChangeTimerQueueTimer(m_timerQueue, m_timer, 0, interval);
if (!ret) {
//fprintf_s(stderr, "ChangeTimerQueueTimer failed\n");
return -1;
}
m_eventsCnt = 0;
m_interval = interval;
return 0;
}
return -1;
}
int32_t timer::stop(void) {
std::unique_lock<std::mutex> lock(timer::m_mutexCnt);
m_eventsCnt = 0;
(void)DeleteTimerQueueTimer(m_timerQueue, m_timer, NULL); // 立即删除
(void)WaitForSingleObject(m_timer, 0);
m_timer = nullptr;
return 0;
}
uint64_t timer::read_events(int32_t timeout) {
std::unique_lock<std::mutex> lock(timer::m_mutexCnt);
std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
uint64_t ret = m_eventsCnt;
m_eventsCnt = 0;
return ret;
}
#endif // WIN32 || _WIN32 || _WIN64
}