Chinaunix首页 | 论坛 | 博客
  • 博客访问: 169011
  • 博文数量: 30
  • 博客积分: 296
  • 博客等级: 二等列兵
  • 技术积分: 407
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-16 21:37
个人简介

a

文章分类

全部博文(30)

文章存档

2016年(1)

2015年(8)

2014年(1)

2013年(11)

2012年(6)

2011年(1)

2010年(2)

分类: C/C++

2012-11-02 22:28:48

apue的第十章的习题10.5 仅使用一个计时器(alarm或较高精度的setitimer),构造一组函数,使得进程可以设置任一数目的计时器。

设计下面两个函数
int settimer(int seconds, void (*proc)(int));
int canceltimer(int id);

settimer的返回值是计时器的id(>=0),出错时返回-1.

设计下面这个构造体,
struct timer_t 
{
char isused;           // 是否有效
int seconds;           // 剩余秒数
void (*proc)(int);     // 超时调用函数指针
};

实现简单起见,用下面的数组表示多个定时器。
#define TIMERS_MAX 100
struct timer_t timers[TIMERS_MAX];

int curtimer_id;   // 当前的定时器ID

具体看代码吧,有考虑不到的情况,请多多指教。

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <signal.h>
  5. #include <unistd.h>

  6. int opentimer();
  7. void closetimer();
  8. int settimer(int seconds, void (*proc)(int));
  9. int canceltimer(int id);

  10. struct timer_t
  11. {
  12.     char isused;
  13.     int seconds;
  14.     void (*proc)(int);
  15. };

  16. #define TIMERS_MAX 100

  17. struct timer_t timers[TIMERS_MAX];
  18. int curtimer_id;
  19. void (*old_sig_proc)(int);
  20. sigset_t old_sigset;

  21. static int getid()
  22. {
  23.     int id = -1;

  24.     for (id = 0; id < TIMERS_MAX; id++)
  25.     {
  26.         if (timers[id].isused == 0)
  27.         {
  28.             break;
  29.         }
  30.     }

  31.     return id;
  32. }

  33. static int getnexttimer(int cur_id)
  34. {
  35.     int id;
  36.     int surplus_seconds = 0;

  37.     if (cur_id < 0)
  38.     {
  39.         for (id = 0; id < TIMERS_MAX; id++)    
  40.         {
  41.             if (timers[id].isused == 1)
  42.             {
  43.                 cur_id = id;
  44.                 break;
  45.             }
  46.         }
  47.     }
  48.     if (cur_id < 0)
  49.     {
  50.         return cur_id;
  51.     }
  52.     surplus_seconds = timers[cur_id].seconds;
  53.     for (id = 0; id < TIMERS_MAX; id++)            
  54.     {
  55.         if (timers[id].isused == 1 && surplus_seconds > timers[id].seconds)
  56.         {
  57.             surplus_seconds = timers[id].seconds;
  58.             cur_id = id;
  59.         }
  60.     }

  61.     return cur_id;
  62. }

  63. static void resetseconds(int over_seconds)
  64. {
  65.     int id = 0;

  66.     for (id = 0; id < TIMERS_MAX; id++)
  67.     {
  68.         if (timers[id].isused == 1)
  69.         {
  70.             timers[id].seconds -= over_seconds;
  71.         }
  72.     }

  73.     return;
  74. }

  75. static void alarm_proc(int signo)
  76. {
  77.     void (*cur_proc)(int);
  78.     int cur_id;

  79.     resetseconds(timers[curtimer_id].seconds);
  80.     timers[curtimer_id].isused = 0;

  81.     cur_proc = timers[curtimer_id].proc;
  82.     cur_id = curtimer_id;

  83.     curtimer_id = getnexttimer(-1);

  84.     if (signal(SIGALRM, alarm_proc) == SIG_ERR)
  85.     {
  86.         exit(-1);
  87.     }
  88.     alarm(timers[curtimer_id].seconds);

  89.     cur_proc(cur_id);
  90. }

  91. int opentimer()
  92. {
  93.     sigset_t new_sigset;

  94.     curtimer_id = -1;
  95.     memset(timers, 0, sizeof(timers));
  96.     // cancel previous alarm
  97.     alarm(0);

  98.     old_sig_proc = signal(SIGALRM, NULL);

  99.     // UNBLOCK SIGALRM
  100.     sigemptyset(&new_sigset);
  101.     sigaddset(&new_sigset, SIGALRM);

  102.     if (sigprocmask(SIG_UNBLOCK, &new_sigset, &old_sigset) < 0)
  103.     {
  104.         return -1;
  105.     }

  106.     return 0;
  107. }

  108. void closetimer()
  109. {
  110.     alarm(0);
  111.     curtimer_id = -1;
  112.     memset(timers, 0, sizeof(timers));

  113.     if (sigprocmask(SIG_SETMASK, &old_sigset, NULL) < 0)
  114.     {
  115.         exit(1);
  116.     }
  117. }

  118. int settimer(int seconds, void (*proc)(int))
  119. {
  120.     int id = -1;
  121.     int surplus_seconds = 0;
  122.     int over_seconds = 0;
  123.     void (*retfunc)(int);

  124.     id = getid();
  125.     if (id < 0)
  126.     {
  127.         return id;
  128.     }

  129.     timers[id].seconds = seconds;
  130.     timers[id].proc = proc;
  131.     timers[id].isused = 1;

  132.     surplus_seconds = alarm(0);
  133.     if (surplus_seconds > 0)
  134.     {
  135.         over_seconds = timers[curtimer_id].seconds - surplus_seconds;
  136.         resetseconds(over_seconds);
  137.     }
  138.     curtimer_id = getnexttimer(id);
  139.     if (signal(SIGALRM, alarm_proc) == SIG_ERR)
  140.     {
  141.         return -1;
  142.     }
  143.     alarm(timers[curtimer_id].seconds);

  144.     return id;
  145. }

  146. int canceltimer(int cancel_id)
  147. {
  148.     int surplus_seconds = 0;
  149.     int over_seconds;

  150.     if (timers[cancel_id].isused == 0)
  151.     {
  152.         return 0;
  153.     }
  154.     if (cancel_id != curtimer_id)
  155.     {
  156.         timers[cancel_id].isused = 0;
  157.         timers[cancel_id].seconds = 0;
  158.         timers[cancel_id].proc = NULL;
  159.         return 0;
  160.     }

  161.     surplus_seconds = alarm(0);
  162.     over_seconds = timers[curtimer_id].seconds - surplus_seconds;
  163.     resetseconds(over_seconds);

  164.     timers[cancel_id].isused = 0;
  165.     timers[cancel_id].seconds = 0;
  166.     timers[cancel_id].proc = NULL;

  167.     curtimer_id = getnexttimer(-1);
  168.     if (signal(SIGALRM, alarm_proc) == SIG_ERR)
  169.     {
  170.         return -1;
  171.     }
  172.     alarm(timers[curtimer_id].seconds);

  173.     return 0;
  174. }

  175. void proc1(int id)
  176. {
  177.     printf("proc1 id:%d\n", id);
  178.     //settimer(5, proc1);
  179.     return;
  180. }

  181. void proc2(int id)
  182. {
  183.     printf("proc2 id:%d\n", id);
  184.     return;
  185. }

  186. void proc3(int id)
  187. {
  188.     printf("proc3 id:%d\n", id);
  189.     return;
  190. }

  191. int main(int argc, char *argv[ ])
  192. {
  193.     int id1, id2, id3;

  194.     id1 = settimer(10, proc1);
  195.     id2 = settimer(5, proc2);
  196.     id3 = settimer(8, proc3);
  197.     canceltimer(id3);
  198.     id3 = settimer(15, proc3);

  199.     while (1)
  200.         pause();
  201. }

阅读(2806) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~