ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
(Generate patch)

Comparing rxvt-unicode/src/iom.C (file contents):
Revision 1.35 by root, Sat Jan 21 14:25:05 2006 UTC vs.
Revision 1.39 by root, Thu Oct 25 12:42:00 2007 UTC

49 49
50#define TIMEVAL timeval 50#define TIMEVAL timeval
51#define TV_FRAC tv_usec 51#define TV_FRAC tv_usec
52#define TV_MULT 1000000L 52#define TV_MULT 1000000L
53 53
54#if IOM_IO
55static io_manager_vec<io_watcher> iow;
56#endif
57#if IOM_CHECK 54#if IOM_CHECK
58static io_manager_vec<check_watcher> cw; 55static io_manager_vec<check_watcher> cw;
59#endif 56#endif
60#if IOM_TIME
61static io_manager_vec<time_watcher> tw;
62#endif
63#if IOM_IDLE 57#if IOM_IDLE
64static io_manager_vec<idle_watcher> iw; 58static io_manager_vec<idle_watcher> iw;
65#endif 59#endif
60
66#if IOM_SIG 61#if IOM_SIG
67static int sigpipe[2]; // signal signalling pipe 62static int sigpipe[2]; // signal signalling pipe
68static sigset_t sigs; 63static sigset_t sigs;
69struct sig_vec : io_manager_vec<sig_watcher> { 64struct sig_vec : io_manager_vec<sig_watcher> {
70 int pending; 65 int pending;
72 : pending (false) 67 : pending (false)
73 { } 68 { }
74}; 69};
75static vector<sig_vec *> sw; 70static vector<sig_vec *> sw;
76#endif 71#endif
72
77#if IOM_CHILD 73#if IOM_CHILD
78static io_manager_vec<child_watcher> pw; 74static io_manager_vec<child_watcher> pw;
79#endif 75#endif
80 76
77#ifdef IOM_LIBEVENT
78static bool need_set_now; // need to set_now in callback
79#else
80 #if IOM_IO
81 static io_manager_vec<io_watcher> iow;
82 #endif
83 #if IOM_TIME
84 static io_manager_vec<time_watcher> tw;
85 #endif
86#endif
87
88#if IOM_TIME
89tstamp io_manager::now ()
90{
91 struct timeval tv;
92
93 gettimeofday (&tv, 0);
94 return (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
95}
96
97void io_manager::set_now ()
98{
99 NOW = now ();
100 #ifdef IOM_LIBEVENT
101 need_set_now = false;
102 #endif
103}
104#endif
105
106#ifndef IOM_LIBEVENT
81// this is a dummy time watcher to ensure that the first 107// this is a dummy time watcher to ensure that the first
82// time watcher is _always_ valid, this gets rid of a lot 108// time watcher is _always_ valid, this gets rid of a lot
83// of null-pointer-checks 109// of null-pointer-checks
84// (must come _before_ iom is being defined) 110// (must come _before_ iom is being defined)
85static struct tw0 : time_watcher 111static struct tw0 : time_watcher
94 120
95 tw0 () 121 tw0 ()
96 : time_watcher (this, &tw0::cb) 122 : time_watcher (this, &tw0::cb)
97 { } 123 { }
98} tw0; 124} tw0;
125#endif
99 126
100tstamp NOW; 127tstamp NOW;
101 128
102#if IOM_CHILD 129#if IOM_CHILD
103// sig_watcher for child signal(s) 130// sig_watcher for child signal(s)
120 { 147 {
121 io_manager::unreg (*w); 148 io_manager::unreg (*w);
122 w->call (*w, status); 149 w->call (*w, status);
123 } 150 }
124 } 151 }
125
126 } 152 }
127 153
128 sw0 () 154 sw0 ()
129 : sig_watcher (this, &sw0::cb) 155 : sig_watcher (this, &sw0::cb)
130 { } 156 { }
131} sw0; 157} sw0;
132#endif 158#endif
133 159
134#if IOM_TIME
135tstamp io_manager::now ()
136{
137 struct timeval tv;
138
139 gettimeofday (&tv, 0);
140 return (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
141}
142
143void io_manager::set_now ()
144{
145 NOW = now ();
146}
147#endif
148
149static bool iom_valid; 160static bool iom_valid;
150 161
151// used for initialisation only 162// used for initialisation only
152static struct init { 163static struct init {
153 init () 164 init ()
154 { 165 {
166 #ifdef IOM_PREINIT
167 { IOM_PREINIT }
168 #endif
169
170 #ifdef IOM_LIBEVENT
171 event_init ();
172 #endif
155 iom_valid = true; 173 iom_valid = true;
156 174
157#if IOM_SIG 175 #if IOM_SIG
158 sigemptyset (&sigs); 176 sigemptyset (&sigs);
159 177
160 if (pipe (sigpipe)) 178 if (pipe (sigpipe))
161 { 179 {
162 perror ("io_manager: unable to create signal pipe, aborting."); 180 perror ("io_manager: unable to create signal pipe, aborting.");
163 abort (); 181 abort ();
164 } 182 }
165 183
166 fcntl (sigpipe[0], F_SETFL, O_NONBLOCK); fcntl (sigpipe[0], F_SETFD, FD_CLOEXEC); 184 fcntl (sigpipe[0], F_SETFL, O_NONBLOCK); fcntl (sigpipe[0], F_SETFD, FD_CLOEXEC);
167 fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC); 185 fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC);
168#endif 186 #endif
169 187
170#if IOM_CHILD 188 #if IOM_CHILD
171 sw0.start (SIGCHLD); 189 sw0.start (SIGCHLD);
172#endif 190 #endif
173 191
174#if IOM_TIME 192 #if IOM_TIME
175 io_manager::set_now (); 193 io_manager::set_now ();
176 194
195 #ifndef IOM_LIBEVENT
177 tw0.start (TSTAMP_MAX); 196 tw0.start (TSTAMP_MAX);
197 #endif
178#endif 198 #endif
199
200 #ifdef IOM_POSTINIT
201 { IOM_POSTINIT }
202 #endif
179 } 203 }
180 204
181 ~init () 205 ~init ()
182 { 206 {
183 iom_valid = false; 207 iom_valid = false;
221 w.active = 0; 245 w.active = 0;
222 } 246 }
223} 247}
224 248
225#if IOM_TIME 249#if IOM_TIME
250 #ifdef IOM_LIBEVENT
251 void iom_time_c_callback (int fd, short events, void *data)
252 {
253 if (need_set_now) io_manager::set_now ();
254 time_watcher *w = static_cast<time_watcher *>(data);
255 w->call (*w);
256 }
257
226void time_watcher::trigger () 258 void time_watcher::start ()
227{ 259 {
228 call (*this); 260 stop ();
229 io_manager::reg (*this); 261 evtimer_set (&ev, iom_time_c_callback, (void *)this);
230} 262 struct timeval tv;
231 263 tv.tv_sec = (long)at;
264 tv.tv_usec = (long)((at - (tstamp)tv.tv_sec) * 1000000.);
265 evtimer_add (&ev, &tv);
266 active = 1;
267 }
268 #else
232void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); } 269 void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
233void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); } 270 void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
271 #endif
272
273 void time_watcher::trigger ()
274 {
275 call (*this);
276 start ();
277 }
234#endif 278#endif
235 279
236#if IOM_IO 280#if IOM_IO
281 #ifdef IOM_LIBEVENT
282 void iom_io_c_callback (int fd, short events, void *data)
283 {
284 if (need_set_now) io_manager::set_now ();
285 io_watcher *w = static_cast<io_watcher *>(data);
286 w->call (*w, events);
287 }
288
289 void io_watcher::set (int fd_, short events_)
290 {
291 if (active) event_del (&ev);
292 fd = fd_;
293 events = events_;
294 event_set (&ev, fd_, events_ | EV_PERSIST, iom_io_c_callback, (void *)this);
295 if (active) event_add (&ev, 0);
296 }
297 #else
237void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); } 298 void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
238void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); } 299 void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
300 #endif
239#endif 301#endif
240 302
241#if IOM_CHECK 303#if IOM_CHECK
242void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); } 304void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); }
243void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); } 305void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); }
321 383
322void io_manager::loop () 384void io_manager::loop ()
323{ 385{
324 init::required (); 386 init::required ();
325 387
326#if IOM_TIME 388 #if IOM_TIME
327 set_now (); 389 set_now ();
328#endif 390 #endif
329 391
330 for (;;) 392 for (;;)
331 { 393 {
332 394 #ifndef IOM_LIBEVENT
333#if IOM_TIME 395 #if IOM_TIME
334 // call pending time watchers 396 // call pending time watchers
335 { 397 {
336 bool activity; 398 bool activity;
337 399
338 do 400 do
339 { 401 {
340 activity = false; 402 activity = false;
341 403
342 for (int i = tw.size (); i--; ) 404 for (int i = tw.size (); i--; )
343 if (!tw[i]) 405 if (!tw[i])
344 tw.erase_unordered (i); 406 tw.erase_unordered (i);
345 else if (tw[i]->at <= NOW) 407 else if (tw[i]->at <= NOW)
346 { 408 {
347 time_watcher &w = *tw[i]; 409 time_watcher &w = *tw[i];
410
411 unreg (w);
412 w.call (w);
413
414 activity = true;
348 415 }
349 unreg (w);
350 w.call (w);
351
352 activity = true;
353 }
354 } 416 }
355 while (activity); 417 while (activity);
356 } 418 }
357#endif 419 #endif
420 #endif
358 421
359#if IOM_CHECK 422 #if IOM_CHECK
360 // call all check watchers 423 // call all check watchers
361 for (int i = cw.size (); i--; ) 424 for (int i = cw.size (); i--; )
362 if (!cw[i]) 425 if (!cw[i])
363 cw.erase_unordered (i); 426 cw.erase_unordered (i);
364 else 427 else
365 cw[i]->call (*cw[i]); 428 cw[i]->call (*cw[i]);
366#endif 429 #endif
367 430
368 struct TIMEVAL *to = 0; 431 struct TIMEVAL *to = 0;
369 struct TIMEVAL tval; 432 struct TIMEVAL tval;
370 433
371#if IOM_IDLE 434#if IOM_IDLE
376 to = &tval; 439 to = &tval;
377 } 440 }
378 else 441 else
379#endif 442#endif
380 { 443 {
381#if IOM_TIME 444 #ifndef IOM_LIBEVENT
445 #if IOM_TIME
382 // find earliest active watcher 446 // find earliest active watcher
383 time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times 447 time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times
384 448
385 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); ) 449 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
386 if (*i && (*i)->at < next->at) 450 if (*i && (*i)->at < next->at)
387 next = *i; 451 next = *i;
388 452
389 if (next->at > NOW && next != tw[0]) 453 if (next->at > NOW && next != tw[0])
390 { 454 {
391 double diff = next->at - NOW; 455 double diff = next->at - NOW;
392 tval.tv_sec = (int)diff; 456 tval.tv_sec = (int)diff;
393 tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT); 457 tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
394 to = &tval; 458 to = &tval;
395 } 459 }
460 #endif
461 #endif
396 } 462 }
397#endif
398 463
464 #ifndef IOM_LIBEVENT
399#if IOM_IO || IOM_SIG 465 #if IOM_IO || IOM_SIG
400 fd_set rfd, wfd; 466 fd_set rfd, wfd;
401 467
402 FD_ZERO (&rfd); 468 FD_ZERO (&rfd);
403 FD_ZERO (&wfd); 469 FD_ZERO (&wfd);
404 470
405 int fds = 0; 471 int fds = 0;
406 472
407# if IOM_IO 473 #if IOM_IO
408 for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); ) 474 for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
409 if (*i) 475 if (*i)
476 {
477 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
478 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
479
480 if ((*i)->fd >= fds) fds = (*i)->fd + 1;
481 }
482 #endif
483
484 if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
485 break; // no events
486
487 #if IOM_SIG
488 FD_SET (sigpipe[0], &rfd);
489 if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
490 #endif
491
492 #if IOM_SIG
493 // there is no race, as we use a pipe for signals, so select
494 // will return if a signal is caught.
495 sigprocmask (SIG_UNBLOCK, &sigs, NULL);
496 #endif
497 fds = select (fds, &rfd, &wfd, NULL, to);
498 #if IOM_SIG
499 sigprocmask (SIG_BLOCK, &sigs, NULL);
500 #endif
501 #elif IOM_TIME
502 if (!to)
503 break;
504
505 select (0, 0, 0, 0, to);
506 #endif
507
508 #if IOM_TIME
410 { 509 {
411 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd); 510 // update time, try to compensate for gross non-monotonic time changes
412 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd); 511 tstamp diff = NOW;
512 set_now ();
513 diff = NOW - diff;
413 514
414 if ((*i)->fd >= fds) fds = (*i)->fd + 1; 515 if (diff < 0)
516 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
517 if (*i)
518 (*i)->at += diff;
415 } 519 }
416# endif 520 #endif
417 521
418 if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
419 break; // no events
420
421# if IOM_SIG
422 FD_SET (sigpipe[0], &rfd);
423 if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
424# endif
425
426# if IOM_SIG
427 // there is no race, as we use a pipe for signals, so select
428 // will return if a signal is caught.
429 sigprocmask (SIG_UNBLOCK, &sigs, NULL);
430# endif
431 fds = select (fds, &rfd, &wfd, NULL, to);
432# if IOM_SIG
433 sigprocmask (SIG_BLOCK, &sigs, NULL);
434# endif
435
436# if IOM_TIME
437 {
438 // update time, try to compensate for gross non-monotonic time changes
439 tstamp diff = NOW;
440 set_now ();
441 diff = NOW - diff;
442
443 if (diff < 0)
444 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
445 if (*i)
446 (*i)->at += diff;
447 }
448# endif
449
450 if (fds > 0) 522 if (fds > 0)
451 { 523 {
452# if IOM_SIG 524 #if IOM_SIG
453 if (FD_ISSET (sigpipe[0], &rfd)) 525 if (FD_ISSET (sigpipe[0], &rfd))
454 { 526 {
455 char ch; 527 char ch;
456 528
457 while (read (sigpipe[0], &ch, 1) > 0) 529 while (read (sigpipe[0], &ch, 1) > 0)
458 ; 530 ;
459 531
460 for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); ) 532 for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
461 if (*svp && (*svp)->pending) 533 if (*svp && (*svp)->pending)
534 {
535 sig_vec &sv = **svp;
536 for (int i = sv.size (); i--; )
537 if (!sv[i])
538 sv.erase_unordered (i);
539 else
540 sv[i]->call (*sv[i]);
541
542 sv.pending = false;
543 }
544 }
545 #endif
546
547 #if IOM_IO
548 for (int i = iow.size (); i--; )
549 if (!iow[i])
550 iow.erase_unordered (i);
551 else
462 { 552 {
463 sig_vec &sv = **svp; 553 io_watcher &w = *iow[i];
464 for (int i = sv.size (); i--; ) 554 short revents = w.events;
555
556 if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
557 if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
558
465 if (!sv[i]) 559 if (revents)
466 sv.erase_unordered (i); 560 w.call (w, revents);
467 else
468 sv[i]->call (*sv[i]);
469
470 sv.pending = false;
471 } 561 }
562 #endif
472 } 563 }
473# endif 564 else if (fds < 0 && errno != EINTR)
474 565 {
566 perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
567 abort ();
568 }
475# if IOM_IO 569#if IOM_IDLE
570 else
476 for (int i = iow.size (); i--; ) 571 for (int i = iw.size (); i--; )
477 if (!iow[i]) 572 if (!iw[i])
478 iow.erase_unordered (i); 573 iw.erase_unordered (i);
479 else 574 else
480 {
481 io_watcher &w = *iow[i];
482 short revents = w.events;
483
484 if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ;
485 if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
486
487 if (revents)
488 w.call (w, revents);
489 }
490#endif
491 }
492 else if (fds < 0 && errno != EINTR)
493 {
494 perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
495 abort ();
496 }
497#if IOM_IDLE
498 else
499 for (int i = iw.size (); i--; )
500 if (!iw[i])
501 iw.erase_unordered (i);
502 else
503 iw[i]->call (*iw[i]); 575 iw[i]->call (*iw[i]);
504#endif 576#endif
505 577
506#elif IOM_TIME 578 #else
579 need_set_now = true;
580
507 if (!to) 581 if (to)
508 break; 582 event_loop (EVLOOP_NONBLOCK);
583 else
584 event_loop (EVLOOP_ONCE);
509 585
510 select (0, 0, 0, 0, &to); 586 if (need_set_now) set_now ();
511 set_now (); 587 #endif
512#else 588 //TODO: IOM_IDLE
513 break;
514#endif
515 } 589 }
516} 590}
517 591

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines