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.38 by root, Thu Oct 25 10:44:14 2007 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#ifndef IOM_LIBEVENT
55#if IOM_IO
56static io_manager_vec<io_watcher> iow;
57#endif
58#if IOM_TIME
59static io_manager_vec<time_watcher> tw;
60#endif
61#endif
62
63#if IOM_CHECK 54#if IOM_CHECK
64static io_manager_vec<check_watcher> cw; 55static io_manager_vec<check_watcher> cw;
65#endif 56#endif
66#if IOM_IDLE 57#if IOM_IDLE
67static io_manager_vec<idle_watcher> iw; 58static io_manager_vec<idle_watcher> iw;
81 72
82#if IOM_CHILD 73#if IOM_CHILD
83static io_manager_vec<child_watcher> pw; 74static io_manager_vec<child_watcher> pw;
84#endif 75#endif
85 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
86// this is a dummy time watcher to ensure that the first 107// this is a dummy time watcher to ensure that the first
87// time watcher is _always_ valid, this gets rid of a lot 108// time watcher is _always_ valid, this gets rid of a lot
88// of null-pointer-checks 109// of null-pointer-checks
89// (must come _before_ iom is being defined) 110// (must come _before_ iom is being defined)
90static struct tw0 : time_watcher 111static struct tw0 : time_watcher
99 120
100 tw0 () 121 tw0 ()
101 : time_watcher (this, &tw0::cb) 122 : time_watcher (this, &tw0::cb)
102 { } 123 { }
103} tw0; 124} tw0;
125#endif
104 126
105tstamp NOW; 127tstamp NOW;
106 128
107#if IOM_CHILD 129#if IOM_CHILD
108// sig_watcher for child signal(s) 130// sig_watcher for child signal(s)
133 : sig_watcher (this, &sw0::cb) 155 : sig_watcher (this, &sw0::cb)
134 { } 156 { }
135} sw0; 157} sw0;
136#endif 158#endif
137 159
138#if IOM_TIME
139tstamp io_manager::now ()
140{
141 struct timeval tv;
142
143 gettimeofday (&tv, 0);
144 return (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000.;
145}
146
147void io_manager::set_now ()
148{
149 NOW = now ();
150}
151#endif
152
153static bool iom_valid; 160static bool iom_valid;
154 161
155// used for initialisation only 162// used for initialisation only
156static struct init { 163static struct init {
157 init () 164 init ()
158 { 165 {
159#ifdef IOM_PREINIT 166 #ifdef IOM_PREINIT
160 { IOM_PREINIT } 167 { IOM_PREINIT }
161#endif 168 #endif
169
162#ifdef IOM_LIBEVENT 170 #ifdef IOM_LIBEVENT
163 event_init (); 171 event_init ();
164#endif 172 #endif
165 iom_valid = true; 173 iom_valid = true;
166 174
167#if IOM_SIG 175 #if IOM_SIG
168 sigemptyset (&sigs); 176 sigemptyset (&sigs);
169 177
170 if (pipe (sigpipe)) 178 if (pipe (sigpipe))
171 { 179 {
172 perror ("io_manager: unable to create signal pipe, aborting."); 180 perror ("io_manager: unable to create signal pipe, aborting.");
173 abort (); 181 abort ();
174 } 182 }
175 183
176 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);
177 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);
178#endif 186 #endif
179 187
180#if IOM_CHILD 188 #if IOM_CHILD
181 sw0.start (SIGCHLD); 189 sw0.start (SIGCHLD);
182#endif 190 #endif
183 191
184#if IOM_TIME 192 #if IOM_TIME
185 io_manager::set_now (); 193 io_manager::set_now ();
186 194
195 #ifndef IOM_LIBEVENT
187 tw0.start (TSTAMP_MAX); 196 tw0.start (TSTAMP_MAX);
197 #endif
188#endif 198 #endif
189 199
190#ifdef IOM_POSTINIT 200 #ifdef IOM_POSTINIT
191 { IOM_POSTINIT } 201 { IOM_POSTINIT }
192#endif 202 #endif
193 } 203 }
194 204
195 ~init () 205 ~init ()
196 { 206 {
197 iom_valid = false; 207 iom_valid = false;
235 w.active = 0; 245 w.active = 0;
236 } 246 }
237} 247}
238 248
239#if IOM_TIME 249#if IOM_TIME
240# ifdef IOM_LIBEVENT 250 #ifdef IOM_LIBEVENT
241 void iom_time_c_callback (int fd, short events, void *data) 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
258 void time_watcher::start ()
259 {
260 stop ();
261 evtimer_set (&ev, iom_time_c_callback, (void *)this);
262 struct timeval tv;
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
269 void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
270 void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
271 #endif
272
273 void time_watcher::trigger ()
242 { 274 {
243 time_watcher *w = static_cast<time_watcher *>(data);
244 w->call (*w); 275 call (*this);
276 start ();
245 } 277 }
246# else
247 void io_manager::reg (time_watcher &w) { io_manager::reg (w, tw); }
248 void io_manager::unreg (time_watcher &w) { io_manager::unreg (w, tw); }
249# endif
250
251void time_watcher::trigger ()
252{
253 call (*this);
254 start ();
255}
256#endif 278#endif
257 279
258#if IOM_IO 280#if IOM_IO
259# ifdef IOM_LIBEVENT 281 #ifdef IOM_LIBEVENT
260 void iom_io_c_callback (int fd, short events, void *data) 282 void iom_io_c_callback (int fd, short events, void *data)
261 { 283 {
284 if (need_set_now) io_manager::set_now ();
262 io_watcher *w = static_cast<io_watcher *>(data); 285 io_watcher *w = static_cast<io_watcher *>(data);
263 w->call (*w, events); 286 w->call (*w, events);
264 } 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 }
265# else 297 #else
266 void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); } 298 void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
267 void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); } 299 void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
268# endif 300 #endif
269#endif 301#endif
270 302
271#if IOM_CHECK 303#if IOM_CHECK
272void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); } 304void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); }
273void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); } 305void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); }
406 tval.TV_FRAC = 0; 438 tval.TV_FRAC = 0;
407 to = &tval; 439 to = &tval;
408 } 440 }
409 else 441 else
410#endif 442#endif
411#ifndef IOM_LIBEVENT
412 { 443 {
444 #ifndef IOM_LIBEVENT
413 #if IOM_TIME 445 #if IOM_TIME
414 // find earliest active watcher 446 // find earliest active watcher
415 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
416 448
417 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 (); )
424 tval.tv_sec = (int)diff; 456 tval.tv_sec = (int)diff;
425 tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT); 457 tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
426 to = &tval; 458 to = &tval;
427 } 459 }
428 #endif 460 #endif
461 #endif
429 } 462 }
430 463
464 #ifndef IOM_LIBEVENT
431#if IOM_IO || IOM_SIG 465 #if IOM_IO || IOM_SIG
432 fd_set rfd, wfd; 466 fd_set rfd, wfd;
433 467
434 FD_ZERO (&rfd); 468 FD_ZERO (&rfd);
435 FD_ZERO (&wfd); 469 FD_ZERO (&wfd);
436 470
437 int fds = 0; 471 int fds = 0;
438 472
439 #if IOM_IO 473 #if IOM_IO
440 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 (); )
441 if (*i)
442 {
443 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
444 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
445
446 if ((*i)->fd >= fds) fds = (*i)->fd + 1;
447 }
448 #endif
449
450 if (!to && !fds) //TODO: also check idle_watchers and check_watchers?
451 break; // no events
452
453 #if IOM_SIG
454 FD_SET (sigpipe[0], &rfd);
455 if (sigpipe[0] >= fds) fds = sigpipe[0] + 1;
456 #endif
457
458 #if IOM_SIG
459 // there is no race, as we use a pipe for signals, so select
460 // will return if a signal is caught.
461 sigprocmask (SIG_UNBLOCK, &sigs, NULL);
462 #endif
463 fds = select (fds, &rfd, &wfd, NULL, to);
464 #if IOM_SIG
465 sigprocmask (SIG_BLOCK, &sigs, NULL);
466 #endif
467
468#else
469 if (to)
470 event_loop (EVLOOP_NONBLOCK);
471 else
472 event_loop (EVLOOP_ONCE);
473#endif
474
475 #if IOM_TIME
476 {
477 // update time, try to compensate for gross non-monotonic time changes
478 tstamp diff = NOW;
479 set_now ();
480 diff = NOW - diff;
481
482 if (diff < 0)
483 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
484 if (*i) 475 if (*i)
485 (*i)->at += diff;
486 }
487 #endif
488
489#ifndef IOM_LIBEVENT
490 if (fds > 0)
491 {
492 #if IOM_SIG
493 if (FD_ISSET (sigpipe[0], &rfd))
494 {
495 char ch;
496
497 while (read (sigpipe[0], &ch, 1) > 0)
498 ;
499
500 for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
501 if (*svp && (*svp)->pending)
502 {
503 sig_vec &sv = **svp;
504 for (int i = sv.size (); i--; )
505 if (!sv[i])
506 sv.erase_unordered (i);
507 else
508 sv[i]->call (*sv[i]);
509
510 sv.pending = false;
511 }
512 }
513 #endif
514
515 #if IOM_IO
516 for (int i = iow.size (); i--; )
517 if (!iow[i])
518 iow.erase_unordered (i);
519 else
520 { 476 {
521 io_watcher &w = *iow[i]; 477 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
522 short revents = w.events; 478 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
523 479
524 if (!FD_ISSET (w.fd, &rfd)) revents &= ~EVENT_READ; 480 if ((*i)->fd >= fds) fds = (*i)->fd + 1;
525 if (!FD_ISSET (w.fd, &wfd)) revents &= ~EVENT_WRITE;
526
527 if (revents)
528 w.call (w, revents);
529 } 481 }
530 #endif 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
509 {
510 // update time, try to compensate for gross non-monotonic time changes
511 tstamp diff = NOW;
512 set_now ();
513 diff = NOW - diff;
514
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;
531 } 519 }
520 #endif
521
522 if (fds > 0)
523 {
524 #if IOM_SIG
525 if (FD_ISSET (sigpipe[0], &rfd))
526 {
527 char ch;
528
529 while (read (sigpipe[0], &ch, 1) > 0)
530 ;
531
532 for (vector<sig_vec *>::iterator svp = sw.end (); svp-- > sw.begin (); )
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
552 {
553 io_watcher &w = *iow[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
559 if (revents)
560 w.call (w, revents);
561 }
562 #endif
563 }
532 else if (fds < 0 && errno != EINTR) 564 else if (fds < 0 && errno != EINTR)
533 { 565 {
534 perror ("io_manager: fatal error while waiting for I/O or time event, aborting."); 566 perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
535 abort (); 567 abort ();
536 } 568 }
537#else
538 if (0)
539 ;
540#endif
541#if IOM_IDLE 569#if IOM_IDLE
542 else 570 else
543 for (int i = iw.size (); i--; ) 571 for (int i = iw.size (); i--; )
544 if (!iw[i]) 572 if (!iw[i])
545 iw.erase_unordered (i); 573 iw.erase_unordered (i);
546 else 574 else
547 iw[i]->call (*iw[i]); 575 iw[i]->call (*iw[i]);
548#endif 576#endif
549 577
550#elif IOM_TIME 578 #else
579 need_set_now = true;
580
551 if (!to) 581 if (to)
552 break; 582 event_loop (EVLOOP_NONBLOCK);
583 else
584 event_loop (EVLOOP_ONCE);
553 585
554 select (0, 0, 0, 0, to); 586 if (need_set_now) set_now ();
555 set_now (); 587 #endif
556 break; 588 //TODO: IOM_IDLE
557#endif
558 } 589 }
559} 590}
560 591

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines