1. 程式人生 > 其它 >c語言製作定時器庫

c語言製作定時器庫

技術標籤:演算法C定時器自定義

c語言製作定時器庫


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需要修改執行緒建立函式,休眠函式以及相應的標頭檔案。
  • 如有問題及建議可留言,另外創作不易,還望一鍵三連,多多支援博主,謝謝各位啦~~