1. 大致功能介绍

  • 实现任务列表,定时器会间隔一段时间遍历列表发现要执行的任务
  • 任务列表中的所有任务并行执行
  • 每个任务都可以有自己的定时器,并且可以选择是否要重复执行
  • 定义方便的任务函数实现接口
  • 定时器可以由用户自定义何时启动和停止
  • 提供等待功能,保证任务列表中的所有任务执行完成
  • 提供任务列表的传参功能

2. API库介绍

void setTick(int val);

设置定时间的间隔时间tick,若设置tick为1000,且任务的定时器时间为1000,则任务会在1秒后执行,默认tick为1秒,最小tick时间为1us。

void addTimerTask(TimerTask task, int val, int autoreset, void *arg);

向任务列表注册一个任务,并指定其定时时间val,以及是否要重复执行autoreset,并可以指定参数的地址。

task需要按照头文件提供的宏来编写,例如:

TASK_START(test2, arg)

	//body
Arg *temp = (Arg*)arg;
temp->ret = temp->a + temp->b;
printf("This is a test2\n"); TASK_END

TASK_START(name, arg)是任务头,name是任务名,arg是参数地址,TASK_END是任务结尾。任务体内可编写正常的c语言代码,并使用参数arg指针。

autoreset有两个可选项:AUTORESET(重复执行),NORESET(执行一次)。

若没有参数,可将arg参数设置为NULL。

void TimerWait();

用于等待任务列表中所有任务执行完毕。

void TimerStop();

用于停止定时器。

void StartTimer();

用于启动定时器。

3. 一个例子

#include <stdio.h>
#include "timer.h" typedef struct Argument{
int a;
int b;
int ret;
}Arg; //任务1,打印语句
TASK_START(test1, arg)
printf("This is a test1\n");
TASK_END //任务2,计算arg中两个数的和,打印语句
TASK_START(test2, arg) Arg *temp = (Arg*)arg;
temp->ret = temp->a + temp->b;
printf("This is a test2\n"); TASK_END //任务3,打印语句
TASK_START(test3, arg)
printf("This is a test3\n");
TASK_END void main(){ Arg arg; //设置tick 为 500ms
setTick(500 * 1000); //添加任务1到任务列表,设置定时器时间为2.5s,重复执行,无参数
addTimerTask(test1, 5, AUTORESET, NULL);
arg.a = 2; arg.b = 3;
//添加任务2到任务列表,设置定时器时间为0.5s,不重复执行,参数为arg
addTimerTask(test2, 1, NORESET, &arg);
//添加任务3到任务列表,设置定时器时间为1s,重复执行,无参数
addTimerTask(test3, 2, AUTORESET, NULL); //启动定时器
StartTimer();
printf("Timer is started\n");
//程序等待5秒
sleep(5);
//停止定时器
TimerStop();
//等待所有任务执行完毕
TimerWait();
//打印任务二的计算结果
printf("%d\n", arg.ret); }

运行结果:

4. 库文件源码

timer.h:

#ifndef TIMER_H
#define TIMER_H #include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h> #define AUTORESET 1
#define NORESET 0 #define TASK_START(name, arg) void* name(void *arg){
#define TASK_END return NULL;} typedef void* (*TimerTask)(void* arg); struct TaskItem{ TimerTask task;
int init_counter;
int counter;
pthread_t th;
void *arg;
void *ret;
int flag;
int autoreset; struct TaskItem *next; }; void setTick(int val); void* EventLoop(void* arg); void addTimerTask(TimerTask task, int val, int autoreset, void *arg); void TimerWait(); void TimerStop(); void StartTimer(); #endif //TIMER_H

timer.cpp

#include "timer.h"

#define STOPFLAG 0
#define RUNFLAG 1 static int tick = 1000 * 1000;
static struct TaskItem head = {
.next = NULL,
};
static pthread_t loop_thread;
static int flag = STOPFLAG;
static int tasknum = 0; void setTick(int val){
tick = val;
} void* EventLoop(void* arg){ struct TaskItem *task = head.next;
struct TaskItem *pretask = &head; while(flag == RUNFLAG && tasknum > 0){ while(task != NULL){
if(task->counter == 0){ // it is time for doing task
if(task->flag == STOPFLAG){ // task is not created
if(0 != pthread_create(&(task->th), NULL, task->task, task->arg)){ // do a task
printf("Failed to create user's task");
}
else{
task->flag = RUNFLAG;
}
}
else{
if(0 != pthread_kill(task->th, 0)){ // current task is completed
if(task->autoreset == AUTORESET){ // repeat execute
task->counter = task->init_counter;
task->flag = STOPFLAG;
}
else{ // delete a task
pretask->next = task->next;
free(task);
task = pretask->next;
tasknum--;
continue;
}
}
}
}
else{
task->counter--;
}
pretask = pretask->next;
task = task->next;
} usleep(tick); // sleep a tick
task = head.next;
pretask = &head; } flag = STOPFLAG; } void addTimerTask(TimerTask task, int val, int autoreset, void *arg){
struct TaskItem *node; node = (struct TaskItem*)malloc(sizeof(struct TaskItem));
node->next = head.next;
head.next = node; node->arg = arg;
node->counter = val;
node->init_counter = val;
node->task = task;
node->flag = STOPFLAG;
node->autoreset = autoreset; tasknum++; } void TimerWait(){ pthread_join(loop_thread, NULL); } void TimerStop(){
flag = STOPFLAG;
} void StartTimer(){ flag = RUNFLAG;
if(0 != pthread_create(&loop_thread, NULL, EventLoop, NULL)){
printf("Failed to create loop task.\n");
} }

注意事项

  • 编译要加 -l pthread选项
  • 库实现在Linux环境,如果是windows需要修改线程创建函数,休眠函数以及相应的头文件。
  • 如有问题及建议可留言,另外创作不易,还望一键三连,多多支持博主,谢谢各位啦~~

C语言实现的多线程定时器的更多相关文章

  1. C语言中的多线程编程

    很久很久以前,我对C语言的了解并不是很多,我最早听说多线程编程是用Java,其实C语言也有多线程编程,而且更为简单.方便.强大.下面就让我们简单领略一下Unix C语言环境下的多线程编程吧! 下面先看 ...

  2. 多线程-定时器Timer

    2019-04-1218:03:32 package 多线程.定时器Timer_重要; import java.util.Timer; import java.util.TimerTask; publ ...

  3. JAVA在语言级支持多线程

    进程:任务 任务并发执行是一个宏观概念,微观上是串行的. 进程的调度是有OS负责的(有的系统为独占式,有的系统为共享式,根据重要性,进程有优先级). 由OS将时间分为若干个时间片. JAVA在语言级支 ...

  4. swift多线程定时器

    swift多线程定时器的使用 func countDown(_ timeOut:Int,view: UIView){ var timeout = timeOut let queue:DispatchQ ...

  5. pyqt5 多线程+定时器+读取本地图片

    前言 一个程序界面有多个button 按钮时,单击一个按钮,若此按钮对应的信号正在执行,且还未执行完毕: 此时再次单击另外一个按钮,就会出现假死状态. 这个时候我们就需要使用 多线程去解决 多线程+定 ...

  6. PyQt5中Web操作与多线程定时器

    1.装载外部网页页面'''用web浏览器控件QWebEngineView控件显示网页PyQt5和Web的交互技术 同时使用python和Web开发程序,混合开发 Python+JavaScript+H ...

  7. java多线程--定时器Timer的使用

    定时的功能我们在手机上见得比较多,比如定时清理垃圾,闹钟,等等.定时功能在java中主要使用的就是Timer对象,他在内部使用的就是多线程的技术. Time类主要负责完成定时计划任务的功能,就是在指定 ...

  8. 多线程&定时器Timer&同步&线程通信&ThreadLocal

    1.多线程 线程状态分为:新建状态.就绪状态.运行状态.阻塞状态.死亡状态 对象等待池的阻塞状态:运行状态执行了wait方法 对向锁池的阻塞状态:试图获得某个同步锁,已经被其他线程占用,就会放到对象的 ...

  9. C语言编程(多线程)

    C语言中多线程编程包括的文件:#include<pthread.h>(linux环境下) pthread_t //线程函数返回类型 pthread_mutrex_t //互斥锁类型 int ...

随机推荐

  1. 老猿学5G随笔:RAN、RAT以及anchor移动性锚点的概念

    最近在学习UPF的功能时,有这样一句话"用户平面功能(UPF)包括以下功能. 用于RAT内/ RAT间移动性的锚点(适用时)",这句话不理解,后来看到了<关于移动锚点的理解! ...

  2. 第11.22节 Python 中re模块的字符串分割器:split函数

    一. 引言 在<第11.2节 Python 正则表达式支持函数概览>介绍了re模块的主要函数,在<第11.3节 Python正则表达式搜索支持函数search.match.fullm ...

  3. PyQt学习随笔:Model和View之间的数据互动过程

    在<PyQt学习随笔:Qt中tem Views(Model-Based)和Item Widgets(Item-Based)控件的用途和关系>中介绍了,Model用于存储数据,View用于展 ...

  4. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的按钮改变缺省文字的方法

    在Qt Designer中可以预先定义标准按钮,相关支持的标准按钮请见<PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的StandardButton ...

  5. 开源脉冲神经网络深度学习框架——惊蛰(SpikingJelly)

    开源脉冲神经网络深度学习框架--惊蛰(SpikingJelly) 背景 近年来神经形态计算芯片发展迅速,大量高校企业团队跟进,这样的芯片运行SNN的能效比与速度都超越了传统的通用计算设备.相应的,神经 ...

  6. WordCount个人项目

    1.GitHub地址:https://github.com/lyh27/WordCount 2.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测 ...

  7. 「IOI2017」接线 的另类做法

    看到这题,我的第一反应是:这就是一个费用流模型?用模拟费用流的方法? 这应该是可以的,但是我忘记了怎么模拟费用流了IOI不可能考模拟费用流.于是我就想了另外一个方法. 首先我们考虑模拟费用流的模型如下 ...

  8. P4267 [USACO18FEB]Taming the Herd

    说实话感觉不是一道蓝题--感觉挺水的,不过为了水题解,水题就够了(其实是觉得思考的过程比较典型,记录一下) 题解 刚开始看这道题感觉上没什么思路,但是我们可以先考虑用 \(O(n)\) 的时间去枚举发 ...

  9. solidity 合约单元测试报错 org.fisco.bcos.web3j.protocol.exceptions.TransactionException: Transaction has failed with status: 0x16. Gas used: 1163650. (not-enough gas?)

    org.fisco.bcos.web3j.protocol.exceptions.TransactionException: Transaction has failed with status: 0 ...

  10. MISC-吹着贝斯扫二维码

    题目 [安洵杯 2019]吹着贝斯扫二维码 解压附件,有36个文件和一个压缩包,压缩包带密码和备注 分析 文件类型 随便打开一个不明文件,是jpg图片啊(FF D8 FF) 改一个试试,有一个小块二维 ...