alarm clock design

Question: If there is only one timer, how to set multiple alarm clocks without using global variables, environment variables, etc. to pass parameters

Solution: Expand the processing function interface of the timer signal, encapsulate a structure, store the timing time sec, timing mode: mod, timing variable count, timeout behavior func(), parameter arg of the behavior function, in order to facilitate the deletion of an alarm node later, Therefore, a unique identifier is needed, so the address of each node is used as the Id, and it is designed as a doubly circular linked list in order to facilitate search and deletion.

Process: The main function adds the alarm node to the linked list, the timer is set to trigger a timeout signal every 1s, and the signal linked list is traversed in the signal processing function to check whether the count and sec are equal at this time, and if they are equal, the timeout behavior is executed. Then judge the mode. If it is loop, reset the count to 0. If it is ONCE, delete the node. Finally activate the alarm again alarm(1).

Code example:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

#define       LOOP       0x0001
#define       ONCE       0x0002
#define       TIME_ERR   -1

typedef  long   TIME_ID;

typedef struct node{
    int   sec;   //定时值
    int   count; //计数器
    int   mode;  //LOOP/ONCE
    void  (*func)(void *);//超时行为
    void  *arg;  //func调用参数

    TIME_ID  id;

    struct node  *prev,*next;
}Timer_t;
static   Timer_t  *head;
////////////////////////////////////////////////////////
void sigFunc(int signo);
int  initTimer(void);
TIME_ID  addTimer(int sec,int mode,void (*func)(void *),void *arg);
void deleteTimer(TIME_ID  id);
void destoryTimer(void);

/////////////////////////////////////////////////////////
void sayHello(void *arg);
void show(void *arg);
void printVal(void *arg);


int main(void)
{
    int ret;
    int val=5566;

    ret=initTimer();
    if(ret!=0)
    {
        fprintf(stderr,"init timer failed.\n");
        return 1;
    }
    //
    TIME_ID  ids[3];
    ids[0]=addTimer(3,LOOP,sayHello,"king");
    if(ids[0]==TIME_ERR)
    {
        fprintf(stderr,"add sayhello timer failed\n");
    }
    ids[1]=addTimer(5,ONCE,show,NULL);
    //if error
    ids[2]=addTimer(10,LOOP,printVal,&val);
    //if error

    printf("\033[31mEnter Del SayHello Timer\033[0m\n");
    getchar();
    deleteTimer(ids[0]);


    
    getchar();
    destoryTimer();
    return 0;
}
int initTimer(void)
{

    head=malloc(sizeof(Timer_t));
    if(head==NULL) return -2;

    head->next=head;
    head->prev=head;

    if(signal(SIGALRM,sigFunc)==SIG_ERR)
       return -1;

     alarm(1);//Start the system Timer
     return 0;
}
/*
 *Check regularly whether the task node has timed out
*/
void sigFunc(int signo)
{
     Timer_t  *t,*next;
     
     for(t=head->next;t!=head;t=next)
     {
         next=t->next;
         //
         t->count=t->count+1;//计时
         if(t->count==t->sec)//超时 执行行为
         {
             t->func(t->arg);
             //检查类型
             if(t->mode==LOOP)
             {
                  t->count=0;
             }
             else
             {
                  t->next->prev=t->prev;
                  t->prev->next=t->next;
                  free(t);
             }
         }
     }
     alarm(1);
}
//追加任务节点
TIME_ID addTimer(int sec,int mode,void (*func)(void *),void *arg)
{
     Timer_t  *one;
     one=malloc(sizeof(Timer_t));
     if(one==NULL)   return TIME_ERR;

     one->sec  =sec;
     one->count=0;
     one->mode =mode;
     one->func =func;
     one->arg  =arg;
     one->id   =(TIME_ID)one;

     //
     one->next=head;
     one->prev=head->prev;
     one->next->prev=one;
     one->prev->next=one;
     return one->id;
}

void deleteTimer(TIME_ID  id)
{
     Timer_t  *t,*next;
     for(t=head->next;t!=head;t=next)
     {
         next=t->next;
         if(t->id==id)
         {
            t->next->prev=t->prev;
            t->prev->next=t->next;
            free(t);
         }
     }

}
void destoryTimer(void)
{
     Timer_t  *t,*next;
     alarm(0);
     for(t=head->next;t!=head;t=next)
     {
         next=t->next;
         free(t);
     }
     free(head);
     signal(SIGALRM,SIG_DFL);
}



/////////////////////////////////////////////////////
void sayHello(void *arg)
{
      printf("Hello %s\n",(char *)arg);
}
void show(void *arg)
{
      printf("============show========\n");
}
void printVal(void *arg)
{
      printf("<<<<<val:%d>>>>>>\n",*(int *)arg);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324856107&siteId=291194637