IT编程 > 开发语言 > C/C++

C语言实现多线程定时器实例讲解

572人参与2021-01-03

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");
 }
}

注意事项

到此这篇关于c语言实现多线程定时器实例讲解的文章就介绍到这了,更多相关c语言如何实现多线程定时器内容请搜索移动技术网以前的文章或继续浏览下面的相关文章希望大家以后多多支持移动技术网!

您对本文有任何疑问!!点此进行留言回复

推荐阅读

猜你喜欢

c/c++ 基本线程管理 join detach

10-08

接口测试

01-19

C++:构造函数,析构函数详解

09-01

c/c++ 网络编程 UDP 用if_nameindex和ioctl取得主机网络信息

10-15

STM8L独立看门狗IWDG

08-13

洛谷P1008三连击题解

09-01

Qt插件热加载-QPluginLoader实现

05-09

Hackerrank GCD Product(莫比乌斯反演)

01-05

热门评论