完成了anytimer

This commit is contained in:
lzy
2024-05-27 17:53:01 +08:00
parent 38ae87f0d6
commit 5598552b22
4 changed files with 230 additions and 3 deletions

View File

@@ -146,7 +146,6 @@ pthread_kill(pthread_self(), SIGINT); // 多线程等价
* *
* @eg: 使用单一计时器,构造一组函数,实现任意数量的定时器 * @eg: 使用单一计时器,构造一组函数,实现任意数量的定时器
* 用到 alarm 或 setitimer * 用到 alarm 或 setitimer
* TODO
* *
* 返回值成功返回0失败返回非零 * 返回值成功返回0失败返回非零
*/ */

View File

@@ -0,0 +1,202 @@
/********************************************************************
* @file anytimer.c
* @brief
* 单一定时器实现任意数量的定时器。
* @author lzy (lllzzzyyy@buaa.edu.cn)
* @url https://lzyyyyyy.fun
*
* @date 2024-05-27
*
********************************************************************/
#include "anytimer.h"
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
typedef enum stat
{
RUNNING,
DONE,
CANCELLED
} eStat;
typedef struct at_job
{
int sec;
at_jobfunc_t *jobp;
void *arg;
eStat flag;
} at_job_t;
static at_job_t *jobs[JOB_MAX];
static int inited = 0;
static struct sigaction sa, alrm_sa_save;
static int find_id( )
{
int i;
for (i = 0; i < JOB_MAX; i++)
{
if (NULL == jobs[i])
return i;
}
return -ENOSPC;
}
static void alrm_action(int sig, siginfo_t *infop, void *ucontext)
{
int i;
//* 判断信号来源
if (SI_KERNEL != infop->si_code)
return;
for (i = 0; i < JOB_MAX; i++)
{
if (jobs[i] != NULL)
{
jobs[i]->sec -= 1;
if (0 == jobs[i]->sec)
{
jobs[i]->jobp(jobs[i]->arg);
jobs[i]->flag = DONE;
}
}
}
}
static void unload_module( )
{
int i;
struct itimerval itv;
sigaction(SIGALRM, &alrm_sa_save, NULL);
if (errno != 0)
{
perror("sigaction");
exit(1);
}
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
if (errno != 0)
{
perror("setitimer");
exit(1);
}
for (i = 0; i < JOB_MAX; i++)
{
if (NULL != jobs[i])
free(jobs[i]);
}
}
static void load_module( )
{
struct sigaction sa;
struct itimerval itv;
sa.sa_sigaction = alrm_action;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO; // 表示使用sigaction三参数的形式
sigaction(SIGALRM, &sa, &alrm_sa_save);
if (errno != 0)
{
perror("sigaction");
exit(1);
}
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, NULL);
if (errno != 0)
{
perror("setitimer");
exit(1);
}
atexit(unload_module); //!!! atexit()
}
int at_addjob(int sec, at_jobfunc_t *jobp, void *arg)
{
if (sec < 0 || jobp == NULL)
return -EINVAL;
if (!inited)
{
load_module( );
inited = 1;
}
at_job_t *job;
int id;
job = malloc(sizeof(*job));
if (NULL == job)
return -ENOMEM;
job->sec = sec;
job->jobp = jobp;
job->arg = arg;
job->flag = RUNNING;
id = find_id( );
if (id < 0)
return -ENOSPC;
jobs[id] = job;
return id;
}
int at_canceljob(int id)
{
if (id < 0 || id >= JOB_MAX)
return -EINVAL;
at_job_t *job = jobs[id];
if (job == NULL)
return -EINVAL;
if (job->flag == DONE)
return -EBUSY;
if (job->flag == CANCELLED)
return -ECANCELED;
jobs[id]->flag = CANCELLED;
return 0;
}
int at_waitjob(int id)
{
if (id < 0 || id >= JOB_MAX)
return -EINVAL;
at_job_t *job = jobs[id];
if (job == NULL)
return -EINVAL;
if (job->flag == RUNNING)
return -EINVAL;
free(job);
jobs[id] = NULL;
return 0;
}

View File

@@ -1,3 +1,14 @@
/********************************************************************
* @file anytimer.h
* @brief
* 单一计时器实现任意数量定时器
* @author lzy (lllzzzyyy@buaa.edu.cn)
* @url https://lzyyyyyy.fun
*
* @date 2024-05-27
*
********************************************************************/
#ifndef __ANYTIMER__H__ #ifndef __ANYTIMER__H__
#define __ANYTIMER__H__ #define __ANYTIMER__H__
@@ -40,7 +51,6 @@ int at_canceljob(int id);
********************************************************************/ ********************************************************************/
int at_waitjob(int id); int at_waitjob(int id);
int at_pausejob(int id); int at_pausejob(int id);
int at_resumejob(int id); int at_resumejob(int id);

View File

@@ -2,6 +2,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/time.h>
#include <unistd.h> #include <unistd.h>
static void f1(void *p) static void f1(void *p)
@@ -11,7 +12,7 @@ static void f1(void *p)
static void f2(void *p) static void f2(void *p)
{ {
printf("f1():%s\n", (char *)p); printf("f2():%s\n", (char *)p);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
@@ -27,8 +28,23 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
job1 = at_addjob(2, f2, "bbb");
if (job1 < 0)
{
fprintf(stderr, "at_addjob() failed!:%s\n", strerror(-job1));
exit(1);
}
job1 = at_addjob(7, f1, "ccc");
if (job1 < 0)
{
fprintf(stderr, "at_addjob() failed!:%s\n", strerror(-job1));
exit(1);
}
puts("End!"); puts("End!");
while (1) while (1)
{ {
write(1, ".", 1); write(1, ".", 1);