APUE Exercises 10.5 pp381
来源:互联网 发布:麟龙选股软件 编辑:程序博客网 时间:2024/05/22 07:46
Question: Using only a single timer (either alarm or the higher-precision setitimer), provide a set of functions that allows a process to set any number of timers.
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <assert.h>#include <time.h>typedef void Func(int);struct __timer{ void *next; unsigned int sec; unsigned int intersec; int id; Func *sigactor;};typedef struct alarm *Timer;struct alarm{ union{ struct { Timer next; unsigned int sec; }; struct __timer __inner; }; };typedef struct list *Header;struct list{ Timer head;};Func* sig_alarm_fun;struct list linkedlist;Header hdr_ptr = &linkedlist;Timer mallocTimer(int id, Func *actor,unsigned int sec, unsigned int interval){ Timer ret = (Timer)malloc(sizeof(struct alarm)); assert(ret); ret->__inner.id = id; ret->__inner.sigactor = actor; ret->__inner.intersec = interval; ret->sec = sec; return ret;}Timer findTimerPrev(Header h, int id){ assert(h); if(h->head == NULL) return NULL; Timer t = h->head; Timer prev = NULL; while(t) { if(t->__inner.id == id){ if(prev == NULL) return (Timer)-1; else return prev; } prev = t; t = t->next; } return NULL;}void delTimer(Header h, Timer t){ assert(h); assert(t); Timer prevtodel = findTimerPrev(h, t->__inner.id); unsigned int base = 0; if(prevtodel) { if(prevtodel == (Timer)-1){ unsigned int res = (h->head)->sec; if(res != 0) { base = res; } else { kill(getpid(),SIGALRM); return; } h->head = (h->head)->next; Timer tmp = (h->head); while(tmp){ tmp->sec += base; tmp = tmp->next; } return; } else { base = (prevtodel->next)->sec; prevtodel->next = (prevtodel->next)->next; Timer tmp = (prevtodel->next); while(tmp){ tmp->sec += base; tmp = tmp->next; } return; } } return;}int appendTimer(Header h, Timer t){ assert(h); assert(t); delTimer(h, t); if(h->head == NULL) { h->head = t; return 0; } Timer tmp = h->head; Timer prev = NULL; unsigned int prevbase = 0; unsigned int base = 0; while(tmp) { prevbase = base; base += tmp->sec; if(t->sec < base){ break; } else{ prev = tmp; tmp = tmp->next; } } if(prev == NULL) { (h->head)->sec -= t->sec; t->next = h->head; h->head = t; return 0; } if(tmp == NULL) t->sec -=base; else t->sec -=prevbase; prev->next = t; t->next = tmp; if(tmp) tmp->sec -= t->sec; return 0;}Func* popTimer(Header h){ assert(h); if(h->head == NULL) return (Func *)-1; Func *ret = (h->head)->__inner.sigactor; Timer todel = h->head; h->head = (h->head)->next; if(todel->__inner.intersec > 0) { todel->sec = todel->__inner.intersec; appendTimer(h, todel); } return ret;}void printList(Header h){ assert(h); if(h->head == NULL) return; Timer tmp = h->head; while(tmp) { printf("timer[%d] = %u saved %u\n", tmp->__inner.id, tmp->sec, tmp->__inner.intersec); tmp = tmp->next; }}static void sig_alarm_internal(int signo){ void funcWrapper(int signo, Func *func); if(hdr_ptr->head == NULL) return; Func *recv; if((recv = popTimer(hdr_ptr)) == (Func *)-1){ funcWrapper(SIGALRM, recv); } else { if(hdr_ptr->head){ ((hdr_ptr->head)->sec > 0?alarm((hdr_ptr->head)->sec):kill(getpid(), SIGALRM)); } funcWrapper(SIGALRM, recv); }}unsigned int Alarm(Header h, Timer mtimer){ sigset_t mask; sigset_t old; sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_BLOCK, &mask, &old); unsigned int res = 0; Timer t; if((t = findTimerPrev(h, mtimer->__inner.id)) == NULL) goto LL; t = h->head; while(t) { res += t->sec; if(t->__inner.id == mtimer->__inner.id) break; t = t->next; }LL: if(mtimer->sec == 0) { delTimer(h, mtimer); sigprocmask(SIG_SETMASK, &old, NULL); return res; } appendTimer(h, mtimer); if(mtimer->__inner.id == (h->head)->__inner.id) ((h->head)->sec > 0?alarm((h->head)->sec):kill(getpid(), SIGALRM)); sigprocmask(SIG_SETMASK, &old, NULL); return res;}static void init(){ struct sigaction act; act.sa_handler = sig_alarm_internal; act.sa_flags = SA_RESTART|SA_NODEFER; sigemptyset(&act.sa_mask); sigaction(SIGALRM, &act, NULL);}void funcWrapper(int signo, Func *func){ sigset_t mask; sigset_t old; sigemptyset(&mask); sigaddset(&mask, SIGALRM); sigprocmask(SIG_UNBLOCK, &mask, &old); func(signo); sigprocmask(SIG_SETMASK, &old, NULL);}//test//volatile clock_t new1, new2, new3, old1, old2, old3;void signal_forfun(signo){ new1 = clock(); printf("fun! %.4f seconds\n", ((double)(new1 - old1)/CLOCKS_PER_SEC)); old1 = new1;}void signal_forhello(signo){ new3 = clock(); printf("hello! %.4f seconds\n", ((double)(new3 - old3)/CLOCKS_PER_SEC)); old3 = new3;}void signal_forhi(signo){ new2 = clock(); printf("hi! %.4f seconds\n", ((double)(new2 - old2)/CLOCKS_PER_SEC)); old2 = new2;}intmain(void){ new1 =new2 =new3 = old1 =old2 = old3=clock(); init(); int i; Alarm(hdr_ptr,mallocTimer(1, signal_forhi, 1, 1)); Alarm(hdr_ptr,mallocTimer(2, signal_forfun, 1, 2)); Alarm(hdr_ptr,mallocTimer(3, signal_forhello, 1, 3)); while(1){}; exit(0); }
0 0
- APUE Exercises 10.5 pp381
- APUE exercises 14.8 pp532
- APUE exercises 10.6 pp 381
- Exercises
- apue习题10.5
- apue
- APUE
- apue
- APUE
- APUE
- 练习(Exercises)
- training exercises
- Exercises 2.2
- Exercises 3.3
- Exercises 4.1
- Python exercises
- LISP Exercises
- Several exercises
- Android应用开发获取手机电池电量的简单方法
- byte char string 转换
- 调优之网络调优-网卡绑定
- GeoMesa介绍
- 【Linux】双系统:从ubuntu 下访问windows的磁盘
- APUE Exercises 10.5 pp381
- 调优之CPU调优
- Makefile
- Plugin with id 'android-apt' not found.
- 【2017/5/2】oracle之sql(四)
- HashMap源码阅读与解析
- 图像识别及处理相关数据集介绍
- 2.8.5_虚线的绘制
- Action、Category、Data、Extras知识详解