当前位置:网站首页>C language implementation timer
C language implementation timer
2022-06-27 05:18:00 【Frame phase】
C Language implementation timer demo, Support windows and Linux Cross platform use ;
windows Use child threads pthread_cond_timedwait Conditional variable implementation ;
linux Use timerfd_create coordination epoll_wait Realization ,timerfd yes Linux Provides a timer interface for the user program . This interface is based on file descriptors , Timeout notification via readable event of file descriptor , So it can be used for select/poll Application scenarios of .
CSTimer.h
#ifndef SRC_UTIL_SRC_CTIMER_H_
#define SRC_UTIL_SRC_CTIMER_H_
#include <pthread.h>
#include <stdint.h>
#ifdef _WIN32
#define Using_Phtread 1
#else
#define Using_Phtread 0
#endif
typedef struct CSTimer{
int32_t taskId;
int32_t timerfd;
int32_t efd;
int32_t isStart;
int32_t isloop;
int32_t waitState;
int32_t waitTime;
pthread_t threadId;
#if Using_Phtread
pthread_mutex_t t_lock;
pthread_cond_t t_cond_mess;
#endif
void (*doTask)(int32_t taskId,void* user);
void* user;
}CSTimer;
#ifdef __cplusplus
extern "C"{
#endif
void create_timer(CSTimer* timer,void* user,int32_t taskId,int32_t waitTime);
void destroy_timer(CSTimer* timer);
void timer_start(CSTimer* timer);
void timer_stop(CSTimer* timer);
#ifdef __cplusplus
}
#endif
#endif
CSTimer.c
#include "CSTimer.h"
#include <stdio.h>
#include <string.h>
#if !Using_Phtread
#include <sys/time.h>
#include <sys/timerfd.h>
#include <sys/epoll.h>
#endif
#include <time.h>
#include <fcntl.h>
void create_timer(CSTimer *timer, void *user, int32_t taskId,int32_t waitTime)
{
if (timer == NULL)
return;
timer->isloop = 0;
timer->isStart = 0;
timer->waitState = 0;
timer->waitTime = waitTime;
#if Using_Phtread
pthread_mutex_init(&timer->t_lock,NULL);
pthread_cond_init(&timer->t_cond_mess,NULL);
#else
/** timerfd_create Create a new timer object , And returns the file descriptor that references the timer * clockid Parameter specifies which type of clock to use (clock) To implement the timer (timer),CLOCK_REALTIME: System real time ,CLOCK_MONOTONIC: Start timing from the moment the system starts , Not affected by the change of system time by users, etc * flags:TFD_NONBLOCK: Non-blocking mode ,TFD_CLOEXEC: When a program is executed exec Function time cost fd Will be automatically shut down by the system , Means not to deliver */
timer->timerfd = timerfd_create(CLOCK_REALTIME, 0);
#endif
timer->efd = -1;
timer->user = user;
timer->doTask = NULL;
timer->taskId = taskId;
}
void destroy_timer(CSTimer *timer) {
if (timer == NULL)
return;
}
void* run_timer_thread(void *obj) {
CSTimer *timer = (CSTimer*) obj;
timer->isStart = 1;
timer->isloop = 1;
/*****************windows**********************/
#if Using_Phtread
struct timespec outtime;
struct timeval now;
pthread_mutex_lock(&timer->t_lock);
while (timer->isloop) {
gettimeofday(&now, NULL);
long nsec = now.tv_usec * 1000 + (timer->waitTime % 1000) * 1000000;
outtime.tv_sec=now.tv_sec + nsec / 1000000000 + timer->waitTime / 1000;
outtime.tv_nsec=nsec % 1000000000;
timer->waitState=1;
pthread_cond_timedwait(&timer->t_cond_mess, &timer->t_lock,&outtime);
timer->waitState=0;
if(timer->doTask) timer->doTask(timer->taskId, timer->user);
}
pthread_mutex_unlock(&timer->t_lock);
#else
/*****************linux**********************/
/** struct itimerspec Specify the initial expiration time and expiration interval of the timer , Contains two timespec Structure ( One unit second , One nanosecond ) * Parameters it_interval, Specify the time period after the initial expiration of the repeating timer * Parameters it_value, Specify the initial expiration time of the timer */
struct itimerspec itimer;
itimer.it_value.tv_sec = timer->waitTime / 1000;
itimer.it_value.tv_nsec = (timer->waitTime % 1000) * 1000 * 1000;
itimer.it_interval.tv_sec = timer->waitTime / 1000;
itimer.it_interval.tv_nsec = (timer->waitTime % 1000) * 1000 * 1000;
/** timerfd_settime Used to set a new timeout , And start timing * Parameters ufd, yes timerfd_create Returned file handle * Parameters flags, by 1 Represents the set absolute time ; by 0 Represents relative time * Parameters utmr, Set the time required * Parameters otmr, Set the timeout before this time for the timer * Return value ,0 success , Other failures */
int ret = timerfd_settime(timer->timerfd, /*TFD_TIMER_ABSTIME*/0, &itimer, NULL);
if (ret == -1) {
printf("err:timerfd_settime\n");
}
int opts;
opts = fcntl(timer->timerfd, F_GETFL);// Get the flag of the file opening method , The meaning of flag value is the same as open Call consistency
if (opts < 0) {
printf("err:fcntl(sock,GETFL)\n");
_exit(1);
}
opts = opts | O_NONBLOCK;
//F_SETFL, Set the file status id , The third parameter 0 For blocking ,O_NONBLOCK Non blocking , return -1 It means failure
if (fcntl(timer->timerfd, F_SETFL, opts) < 0) {
printf("err:fcntl(sock,SETFL,opts)\n");
_exit(1);
}
/** epoll_create Create a epoll example ( Create a monitor descriptor epoll Handle descriptor for ) * Parameters max_size, Identify the maximum number of listeners * Return value , new epoll File descriptor for instance , Failure to return -1 */
timer->efd = epoll_create(1);
struct epoll_event tev;
tev.events = EPOLLIN | EPOLLET;// Set the event of the descriptor
tev.data.fd = timer->timerfd;// Set the value of the file descriptor to be monitored
/** epoll_ctl operation epoll Function ( here , Add timer descriptor to epoll In the detection queue , The event type that the function registers to listen to is ev Medium events) * Parameters epfd, Operation of the epoll File descriptor for instance * Parameters op,EPOLL_CTL_ADD: In the file descriptor epfd Cited epoll The object file descriptor is registered on the instance fd, And link events and internal files to fd * Parameters fd, File descriptors that require operation listening * Parameters epoll_event, Structure , Events that need to be monitored */
epoll_ctl(timer->efd, EPOLL_CTL_ADD, timer->timerfd, &tev);
struct epoll_event ev[1];
while (timer->isloop) {
/** epoll_wait Waiting for the event to happen , Wait epoll On the file descriptor I / O event * Parameters epfd, Operation of the epoll File descriptor for instance * Parameters events, The collection used to get events from the kernel * Parameters maxevents, Tell the kernel this events How big is the , This maxevents Value of cannot be greater than create epoll_create() At the time of the size * Parameters timeout, It's a timeout ( millisecond ,0 Will return immediately ,-1 Will block indefinitely ). * Return value , Returns the number of events to be processed , Such as return 0 Indicates that time has expired */
int nev = epoll_wait(timer->efd, ev, 1, 200);// Waiting for the event to happen , And save the detected information to ev In this structure
if (nev > 0 && (ev[0].events & EPOLLIN)) // A file character readable event was detected
{
if(ev[0].data.fd == timer->timerfd)// The value of the detected file descriptor is equal to the value of the detected file descriptor
{
uint64_t res;
int bytes = read(timer->timerfd, &res, sizeof(res));
if (timer->doTask)
timer->doTask(timer->taskId, timer->user);
}
}
}
#endif
timer->isStart = 0;
return NULL;
}
void timer_start(CSTimer *timer) {
if (timer == NULL)
return;
if (pthread_create(&timer->threadId, 0, run_timer_thread, timer)) {
printf("Thread::start could not start thread\n");
}
}
void timer_stop(CSTimer *timer) {
if (timer == NULL)
return;
if (timer->isStart) {
timer->isloop = 0;
#if Using_Phtread
if(timer->waitState){
pthread_mutex_lock(&timer->t_lock);
pthread_cond_signal(&timer->t_cond_mess);
pthread_mutex_unlock(&timer->t_lock);
}
#else
if (timer->isStart) {
struct epoll_event tev;
tev.events = EPOLLIN | EPOLLET;
tev.data.fd = timer->timerfd;
epoll_ctl(timer->efd, EPOLL_CTL_DEL, timer->timerfd, &tev);// Describe the timer file from epoll Delete... From the listening list
close(timer->efd);
timer->efd = -1;
}
close(timer->timerfd);
timer->timerfd = -1;
#endif
while (timer->isStart)
usleep(1000);
}
}
Use QT test :
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QDebug>
#include <QDateTime>
void g_doTask(int32_t taskId, void *user)
{
if (user == NULL)
return;
MainWindow *mw = (MainWindow*) user;
mw->doWork();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
create_timer(&mCSTimer,this,1,5000);
mCSTimer.doTask = g_doTask;
timer_start(&mCSTimer);
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<"tart"<<QDateTime::currentDateTime().toString("hh:mm:ss");
}
MainWindow::~MainWindow()
{
timer_stop(&mCSTimer);
destroy_timer(&mCSTimer);
delete ui;
}
void MainWindow::doWork()
{
qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<QDateTime::currentDateTime().toString("hh:mm:ss");
}
Printout
[ ../mainwindow.cpp ] 25 MainWindow tart "17:22:53"
[ ../mainwindow.cpp ] 38 doWork "17:22:58"
[ ../mainwindow.cpp ] 38 doWork "17:23:03"
[ ../mainwindow.cpp ] 38 doWork "17:23:08"
[ ../mainwindow.cpp ] 38 doWork "17:23:13"
[ ../mainwindow.cpp ] 38 doWork "17:23:18"
边栏推荐
- Microservice system design -- microservice monitoring and system resource monitoring design
- 微服务系统设计——统一鉴权服务设计
- Cognition - how to fill in 2022 college entrance examination volunteers
- 014 C language foundation: C string
- Neo4j community conflicts with neo4j desktop
- 018 basics of C language: C file reading and writing
- Microservice system design -- distributed lock service design
- jq怎么获取元素的id名
- Almost because of json Stringify lost his bonus
- DAST black box vulnerability scanner part 6: operation (final)
猜你喜欢
随机推荐
Penetration test - file upload / download / include
Edge在IE模式下加载网页 - Edge设置IE兼容性
Unity point light disappears
007 C语言基础:C运算符
019 basics of C language: C preprocessing
Microservice system design -- distributed cache service design
Epics record reference 5 -- array analog input recordarray analog input (AAI)
洛谷P4683 [IOI2008] Type Printer 题解
Mechanical transcoding journal [17] template, STL introduction
Neo4j community conflicts with neo4j desktop
论文解读(LG2AR)《Learning Graph Augmentations to Learn Graph Representations》
021 basics of C language: recursion, variable parameters
How JQ gets the reciprocal elements
导航【机器学习】
Redis high availability cluster (sentry, cluster)
微服务系统设计——统一鉴权服务设计
微服务系统设计——消息缓存服务设计
OpenCV的轮廓检测和阈值处理综合运用
竣达技术丨多品牌精密空调集中监控方案
【B站UP DR_CAN学习笔记】Kalman滤波2









