本文摘自    https://www.cnblogs.com/embedded-linux/p/9093990.html

应用层使用timer可以启动多个timer(每个timer管理一个目标时间),也可启用一个timer来管理多个目标时间。

多个timer时每个timer占用一部分空间,且存在多个timer同时到期的先后顺序问题(未多考虑,是否有问题待确定),可采用单个timer管理程序所有定时事件,即如何实现序列化的timer。

涉及到链表(记录多个目标时间的到期时间),信号处理函数(在SIG_ALAM函数中处理timer事件,并启动下一个timer时间点)。

#include

#include

#include

#include

#include

#include

#include

#include "list.h"

#define TIMERID_FIRST 100

typedef void (*stimer_func)(void *arg);

struct signal_timer{

struct list_head list_timer;

int id;

struct timeval itv;

struct timeval atv;

stimer_func stimer_handler;

void *arg;

};

int g_id;

struct list_head g_signal_list;

void alarm_handler(int sig);

int timer_init(void);

void timer_destroy(void);

// Return: id >0, in case of success; -1 in case of error.

int timer_add(long sec, long usec, void (*stimer_func)(void *arg), void *arg);

void timer_del(int id, int is_free);

static long long diff_time(struct timeval *t1, struct timeval *t2)

{

long long t1_usec = (t1->tv_sec * 1000 * 1000 + t1->tv_usec);

long long t2_usec = (t2->tv_sec * 1000 * 1000 + t2->tv_usec);

return (t1_usec - t2_usec);

}

static int max_time(struct timeval *t1, struct timeval *t2)

{

if(t1->tv_sec < t2->tv_sec){

return -1;

} else if(t1->tv_sec > t2->tv_sec){

return 1;

} else {

if(t1->tv_usec < t2->tv_usec){

return -1;

} else if(t1->tv_usec > t2->tv_usec){

return 1;

} else {

return 0;

}

}

}

#define min_time(t1, t2) (((t1).tv_sec < (t2).tv_sec) || \

(((t1).tv_sec == (t2).tv_sec) && \

((t1).tv_usec < (t2).tv_usec)))

#define MAX_USEC 999999

#define TV_MINUS(t1, t2, target) if((t1).tv_usec >= (t2).tv_usec){ \

(target).tv_sec = (t1).tv_sec - (t2).tv_sec;\

(target).tv_usec = (t1).tv_usec - (t2).tv_usec;\

} else { \

(target).tv_sec = (t1).tv_sec - (t2).tv_sec - 1;\

(target).tv_usec = (t1).tv_usec + (MAX_USEC - (t2).tv_usec);\

}

void alarm_handler(int sig)

{

struct timespec ts;

struct timeval tv;

struct timeval tv_min, *ptv_min;

struct itimerval it;

struct signal_timer *pstimer = NULL, *next= NULL;

int ret = 0;

if(list_empty(&g_signal_list))

return ;

// pstimer = list_first_entry(&g_signal_list, struct signal_timer, list_timer);

// ptv_min = &(pstimer->atv);

ptv_min = &tv_min;

clock_gettime(CLOCK_MONOTONIC_RAW, &ts);

tv.tv_sec = ts.tv_sec;

tv.tv_usec = ts.tv_nsec / 1000;

// printf("now time: %ld:%ld\n", tv.tv_sec, tv.tv_usec);

tv_min = tv;

tv_min.tv_sec += 1000; //default 1000s once

// two methods: sequence the timer list in case of more timers,

// not sequence in case of fewer timers.

list_for_each_entry_safe(pstimer, next, &g_signal_list, list_timer){

// printf("timerid:%d, aim time: %ld:%ld\n", pstimer->id, pstimer->atv.tv_sec, pstimer->atv.tv_usec);

if(max_time(&pstimer->atv, &tv) <= 0){

if(pstimer->stimer_handler != NULL){

pstimer->stimer_handler(pstimer->arg);

}

// only operation once, when overflow more times.

do{

pstimer->atv.tv_sec += pstimer->itv.tv_sec;

pstimer->atv.tv_usec += pstimer->itv.tv_usec;

} while(max_time(&pstimer->atv, &tv) < 0);

// } else {

// break;

}

// get next itimer

if(min_time(pstimer->atv, *ptv_min)){

ptv_min = &(pstimer->atv);

}

}

memset(&it, 0, sizeof(it));

// it.it_value.tv_sec = ptv_min->tv_sec - tv.tv_sec;

// it.it_value.tv_usec = ptv_min->tv_usec - tv.tv_usec;

TV_MINUS(*ptv_min, tv, it.it_value);

ret = setitimer(ITIMER_REAL, &it, NULL);

if(ret < 0){

perror("setitimer");

}

printf("process SIGALRM, next time is %ld:%ld\n", it.it_value.tv_sec, it.it_value.tv_usec);

}

int timer_add(long sec, long usec, void (*stimer_func)(void *arg), void *arg)

{

struct signal_timer *pstimer = (struct signal_timer*)malloc(sizeof(struct signal_timer));

struct timespec ts;

memset(pstimer, 0, sizeof(*pstimer));

pstimer->id = g_id++;

pstimer->itv.tv_sec = sec;

pstimer->itv.tv_usec = usec;

pstimer->stimer_handler = stimer_func;

if(arg){

pstimer->arg = arg;

}else {

pstimer->arg = pstimer;

}

list_add(&(pstimer->list_timer), &g_signal_list);

clock_gettime(CLOCK_MONOTONIC_RAW, &ts);

pstimer->atv.tv_sec += ts.tv_sec;

pstimer->atv.tv_usec += ts.tv_nsec / 1000;

return pstimer->id;

}

void timer_del(int id, int is_free)

{

struct signal_timer *pstimer = NULL;

list_for_each_entry(pstimer, &g_signal_list, list_timer){

if(pstimer->id == id){

list_del(&(pstimer->list_timer));

printf("----delete timerid is %d\n", pstimer->id);

if(is_free){

free(pstimer);

}

break;

}

}

}

int timer_init(void)

{

INIT_LIST_HEAD(&g_signal_list);

struct sigaction act;

int ret = 0;

// memset(&act, 0, sizeof(act));

sigemptyset(&act.sa_mask);

act.sa_handler = alarm_handler;

act.sa_flags = 0;

ret = sigaction(SIGALRM, &act, NULL);

if(ret < 0){

perror("sigaction");

return -1;

}

g_id = TIMERID_FIRST ;

return 0;

}

void timer_destroy(void)

{

struct signal_timer *pstimer = NULL;

while(! list_empty((&g_signal_list)->next)){

list_del((&g_signal_list)->next);

pstimer = container_of((&g_signal_list)->next, struct signal_timer, list_timer);

free(pstimer);

}

}

void timer_printf(void *arg)

{

if(arg){

struct signal_timer *pstimer = (struct signal_timer*)arg;

printf("timerid:%d, aim time: %ld:%ld\n", pstimer->id, pstimer->atv.tv_sec, pstimer->atv.tv_usec);

} else {

printf("timerid is %d\n", g_id);

}

}

int main(int argc, char **argv)

{

int tid1 = 0, tid2 = 0, tid3 = 0;

int i = 0;

signal(SIGPIPE, SIG_IGN);

timer_init();

tid1 = timer_add(2, 0, timer_printf, NULL);

tid2 = timer_add(3, 0, timer_printf, NULL);

tid3 = timer_add(5, 0, timer_printf, NULL);

alarm(1);

while(1){

sleep(1);

printf("sleep 1s\n");

i++;

if(i%3 == 0) timer_del(tid1, true);

if(i%7 == 0) timer_del(tid2, true);

if(i%9 == 0) timer_del(tid3, true);

}

timer_destroy();

return 0;

}

运行:

timerid:102, aim time: 468486:907381

timerid:101, aim time: 468486:907380

timerid:100, aim time: 468486:907380

process SIGALRM, next time is 0:999678

sleep 1s

timerid:100, aim time: 468488:907380

process SIGALRM, next time is 0:998577

sleep 1s

timerid:101, aim time: 468489:907380

process SIGALRM, next time is 0:999371

sleep 1s

----delete timerid is 100

process SIGALRM, next time is 0:999003

sleep 1s

timerid:102, aim time: 468491:907381

process SIGALRM, next time is 0:998901

sleep 1s

timerid:101, aim time: 468492:907380

process SIGALRM, next time is 2:998319

sleep 1s

sleep 1s

----delete timerid is 101

sleep 1s

process SIGALRM, next time is 0:999768

sleep 1s

----delete timerid is 102

sleep 1s

sleep 1s

sleep 1s

sleep 1s

java timer 序列化_编程达人 应用层timer_如何序列化timer相关推荐

  1. java timertask 初始化_定时器实现方式之TimerTask、Timer

    在未来某个指定的时间点或者经过一段时间延迟后执行某个事件,这时候就需要用到定时器了.定时器的实现方式有很多种,今天总结最简单的实现方式.java 1.3引入了定时器框架,用于在定时器上下文中控制线程的 ...

  2. vc 控制台添加托盘显示_编程达人

    看到火哥给他的程序加上了系统托盘,我的没有很是不爽.于是花了几分钟找了些资料,给自己的也加上了系统托盘.现在将我的实现步骤分享一下. 先来解释下什么是系统托盘:其实准确的说法应该是任务栏通知区域.系统 ...

  3. java 面试 概率论_编程培训-115个Java面试题和答案B.pdf

    编程培训-115个Java面试题和答案B.pdf "玩转"Java系列 1 题目115个Java面试题和答案终极(下) 第一篇讨论了面向对象编程和它的特点,关于Java和它的功能的 ...

  4. c和java哪个好学_编程入门学习c++和Java哪个比较好

    编程入门学习c++和Java哪个比较好 发布时间:2020-04-25 16:54:41 来源:亿速云 阅读:231 作者:栢白 编程入门学习c++和Java哪个比较好?如今这些都是小白比较关心的,如 ...

  5. java webservice 线程_编程实践笔记{Java 线程 并发处理 Webservice}

    1,保证线程安全的三种方法: a,不要跨线程访问共享变量 b,使共享变量是final类型的 c,将共享变量的操作加上同步 2,一开始就将类设计成线程安全的, 比在后期重新修复它,更容易. 3, 编写多 ...

  6. java请求注释_求达人给java代码【注释】!!请求尽量详细,万分感谢!!

    (1)定义一个接口Inf,含有常量π和一个实现计算功能的方法calculate(),再分别定义一个面积类area和一个周长类circumference,各自按计算圆面积和圆周长具体实现接口中的方法,并 ...

  7. java 电梯算法_编程之美之小飞的电梯调度算法(多种解法)---Java语言

    1.题目情景 我们假设都是从一楼上电梯的,而至于讯电梯停在其中的某一层.即所有的乘客都从一楼上电梯,到达某层之后,电梯停下来,所有乘客再从这里爬楼梯到自己的目的层.在一楼的时候,每个乘客选择自己的目的 ...

  8. delphi java jni 互通_编程应用实例:Java通过JNI与Delphi交互

    来源: 赛迪网 作者: 若水 2008-05-14/18:11 前一段时间,我用java开发一个安装程序,适用于tomcat mysql构建的web环境.在开发的过程中遇到与写注册表,注册系统服务等问 ...

  9. Java国际化教程_编程入门自学教程_菜鸟教程-免费教程分享

    教程简介 Java国际化入门教程 - 从简单的步骤了解Java国际化从基本到高级概念,包括概述,环境设置,区域设置,区域设置详细信息,显示语言,ResourceBundle,NumberFormat, ...

最新文章

  1. 6 redhat 查看rtc时间_RTC 月度小报 9 月 | WebRTC M77、RTC大会即将开幕、实时码流加速...
  2. Linux shell编程学习笔记-----第十六章
  3. jquery.dataTables.min.js:62 Uncaught TypeError: Cannot read property ‘style‘ of undefined原因
  4. 应邀ITGeGe在线教育社区嵌入式基础开发讲师
  5. day08.4-samba共享网盘服务
  6. .o文件 linux生成,vmlinux.o 生成
  7. 比较两个字符数组是否相等_Java比较两个数组是否相等(equals())
  8. 232.栈实现队列(力扣leetcode) 博主可答疑该问题
  9. PADS2007教程(二)——PCB封装
  10. PBRT的scene.pbrt使用方法
  11. 基于SpringBoot+SpringSecurity+JWT+RSA加密算法签名 Auth权限认证搭建教程
  12. Java char类型介绍
  13. 搜狐财报:年度盈利,长跑依旧
  14. 记一个vue v-if引起的图片加载导致样式跳动问题
  15. 打印1000年到2000年之间的闰年
  16. java符号三角形问题_实验四 回溯算法和分支限界法 符号三角形问题
  17. 创新突破,索爱S5耳机实现空间音频和动态头部跟踪
  18. 台式机和笔记本属于什么计算机,pc机属于什么型计算机
  19. GDOI2017游记
  20. ajax中Uncaught (in promise) TypeError: Failed to execute ‘setRequestHeader‘ on ‘XMLHttpRequest‘: Stri

热门文章

  1. 使用kubeadm安装kubernetes1.12.2版本脚本
  2. 二叉树 | 根据前序、后序生成中序
  3. json字符串、json对象、数组之间的转换
  4. 如何在工作中更好的学习
  5. 火狐firefox插件配合scrapy,注意tbody会导致empty
  6. JAVA多线程与并发学习总结
  7. Cesium官方教程6--相机
  8. Postgresql - MATERIALIZED VIEW
  9. powderdesinger显示中英文表名
  10. (转)淘淘商城系列——内容分类管理