00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include "pnotify.h"
00025 #include "pnotify-internal.h"
00026 #include "queue.h"
00027 #include "thread.h"
00028
00029
00030 struct pn_timer {
00031
00033 int remaining;
00034
00036 struct pn_watch *watch;
00037
00039 LIST_ENTRY(pn_timer) entries;
00040 };
00041
00042
00044 LIST_HEAD(, pn_timer) TIMER;
00045
00047 size_t TIMER_INTERVAL = 1;
00048
00050 pthread_mutex_t TIMER_MUTEX = PTHREAD_MUTEX_INITIALIZER;
00051
00053 static void
00054 timer_enable()
00055 {
00056 struct itimerval itv;
00057
00058 itv.it_value.tv_sec = TIMER_INTERVAL;
00059 itv.it_value.tv_usec = 0;
00060 itv.it_interval.tv_sec = TIMER_INTERVAL;
00061 itv.it_interval.tv_usec = 0;
00062
00063 if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
00064 err(1, "setitimer(2)");
00065 }
00066
00067
00069 static void
00070 timer_disable()
00071 {
00072 struct itimerval itv;
00073
00074 memset(&itv, 0, sizeof(itv));
00075
00076 if (setitimer(ITIMER_REAL, &itv, NULL) != 0)
00077 err(1, "setitimer(2)");
00078 }
00079
00080
00081 int
00082 pn_add_timer(struct pn_watch *watch)
00083 {
00084 struct pn_timer *timer;
00085
00086
00087 if ((timer = calloc(1, sizeof(*timer))) == NULL) {
00088 warn("malloc(3)");
00089 return -1;
00090 }
00091 timer->remaining = watch->ident.interval;
00092 timer->watch = watch;
00093
00094 pthread_mutex_lock(&TIMER_MUTEX);
00095
00096
00097 if (LIST_EMPTY(&TIMER))
00098 timer_enable();
00099
00100
00101 LIST_INSERT_HEAD(&TIMER, timer, entries);
00102
00103 pthread_mutex_unlock(&TIMER_MUTEX);
00104
00105 return 0;
00106 }
00107
00108
00109 int
00110 pn_rm_timer(struct pn_watch *watch)
00111 {
00112 struct pn_timer *timer, *tmp;
00113
00114 pthread_mutex_lock(&TIMER_MUTEX);
00115
00116
00117 if (LIST_EMPTY(&TIMER))
00118 timer_disable();
00119
00120
00121 LIST_FOREACH_SAFE(timer, &TIMER, entries, tmp) {
00122 if (timer->watch == watch) {
00123 LIST_REMOVE(timer, entries);
00124 break;
00125 }
00126 }
00127
00128 pthread_mutex_unlock(&TIMER_MUTEX);
00129
00130 return 0;
00131 }
00132
00133
00134 void
00135 pn_timer_init(void)
00136 {
00137 LIST_INIT(&TIMER);
00138 }
00139
00140 void *
00141 pn_timer_loop(void * unused)
00142 {
00143 struct pnotify_event *evt;
00144 struct pn_timer *timer;
00145 sigset_t signal_set;
00146 int signum;
00147
00148
00149 evt = unused;
00150
00151
00152 for (;;) {
00153
00154
00155 sigemptyset(&signal_set);
00156 sigaddset(&signal_set, SIGALRM);
00157 sigwait(&signal_set, &signum);
00158
00159
00160 pthread_mutex_lock(&TIMER_MUTEX);
00161 LIST_FOREACH(timer, &TIMER, entries) {
00162
00163
00164 if (TIMER_INTERVAL > timer->remaining) {
00165
00166
00167 if ((evt = calloc(1, sizeof(*evt))) == NULL)
00168 err(1, "calloc(3)");
00169 evt->watch = timer->watch;
00170 evt->mask = PN_TIMEOUT;
00171
00172
00173 pn_event_add(timer->watch->ctx, evt);
00174
00175
00176 timer->remaining = timer->watch->ident.interval;
00177 }
00178
00179
00180 else {
00181 timer->remaining -= TIMER_INTERVAL;
00182 }
00183 }
00184 pthread_mutex_unlock(&TIMER_MUTEX);
00185 }
00186
00187 return NULL;
00188 }