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.16 by pcg, Fri Apr 2 14:30:06 2004 UTC vs.
Revision 1.39 by root, Thu Oct 25 12:42:00 2007 UTC

1/* 1/*
2 iom.C -- generic I/O multiplexor 2 iom.C -- generic I/O multiplexer
3 Copyright (C) 2003, 2004 Marc Lehmann <pcg@goof.com> 3 Copyright (C) 2003-2006 Marc Lehmann <gvpe@schmorp.de>
4 4
5 This file is part of GVPE.
6
5 This program is free software; you can redistribute it and/or modify 7 GVPE is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by 8 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or 9 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version. 10 (at your option) any later version.
9 11
10 This program is distributed in the hope that it will be useful, 12 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details. 15 GNU General Public License for more details.
14 16
15 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software 18 along with gvpe; if not, write to the Free Software
17 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/ 20*/
21
22#include "iom.h"
19 23
20#include <cstdio> 24#include <cstdio>
21#include <cstdlib> 25#include <cstdlib>
22#include <cerrno> 26#include <cerrno>
27#include <cassert>
23 28
29#include <sys/types.h>
24#include <sys/time.h> 30#include <sys/time.h>
25
26#include <assert.h>
27 31
28#if 1 // older unices need these includes for select (2) 32#if 1 // older unices need these includes for select (2)
29# include <unistd.h> 33# include <unistd.h>
34# include <time.h>
35#endif
36
37#if IOM_CHILD
30# include <sys/types.h> 38# include <sys/wait.h>
39#endif
40
41#if IOM_SIG
42# include <csignal>
43# include <fcntl.h>
31#endif 44#endif
32 45
33// if the BSDs would at least be marginally POSIX-compatible.. *sigh* 46// if the BSDs would at least be marginally POSIX-compatible.. *sigh*
34// until that happens, sys/select.h must come last 47// until that happens, sys/select.h must come last
35#include <sys/select.h> 48#include <sys/select.h>
36 49
37// for IOM_SIG 50#define TIMEVAL timeval
38#include <signal.h> 51#define TV_FRAC tv_usec
52#define TV_MULT 1000000L
39 53
40#include "iom.h" 54#if IOM_CHECK
55static io_manager_vec<check_watcher> cw;
56#endif
57#if IOM_IDLE
58static io_manager_vec<idle_watcher> iw;
59#endif
41 60
42// TSTAMP_MAX must still fit into a positive struct timeval 61#if IOM_SIG
43#define TSTAMP_MAX (double)(1UL<<31) 62static int sigpipe[2]; // signal signalling pipe
63static sigset_t sigs;
64struct sig_vec : io_manager_vec<sig_watcher> {
65 int pending;
66 sig_vec ()
67 : pending (false)
68 { }
69};
70static vector<sig_vec *> sw;
71#endif
44 72
73#if IOM_CHILD
74static io_manager_vec<child_watcher> pw;
75#endif
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
45// this is a dummy time watcher to ensure that the first 107// this is a dummy time watcher to ensure that the first
46// time watcher is _always_ valid, this gets rid of a lot 108// time watcher is _always_ valid, this gets rid of a lot
47// of null-pointer-checks 109// of null-pointer-checks
48// (must come _before_ iom is being defined) 110// (must come _before_ iom is being defined)
49static struct tw0 : time_watcher 111static struct tw0 : time_watcher
112{
113 void cb (time_watcher &w)
50 { 114 {
51 void cb (time_watcher &w)
52 {
53 // should never get called 115 // should never get called
54 // reached end-of-time, or tstamp has a bogus definition, 116 // reached end-of-time, or tstamp has a bogus definition,
55 // or compiler initilization order broken, or somethine else :) 117 // or compiler initialisation order broken, or something else :)
118 abort ();
119 }
120
121 tw0 ()
122 : time_watcher (this, &tw0::cb)
123 { }
124} tw0;
125#endif
126
127tstamp NOW;
128
129#if IOM_CHILD
130// sig_watcher for child signal(s)
131static struct sw0 : sig_watcher
132{
133 void cb (sig_watcher &w)
134 {
135 // SIGCHLD, call corresponding watchera
136 pid_t pid;
137 int status;
138
139 while ((pid = waitpid (-1, &status, WNOHANG)) > 0)
140 for (int i = pw.size (); i--; )
141 {
142 child_watcher *w = pw[i];
143
144 if (!w)
145 pw.erase_unordered (i);
146 else if (w->pid == pid)
147 {
148 io_manager::unreg (*w);
149 w->call (*w, status);
150 }
151 }
152 }
153
154 sw0 ()
155 : sig_watcher (this, &sw0::cb)
156 { }
157} sw0;
158#endif
159
160static bool iom_valid;
161
162// used for initialisation only
163static struct init {
164 init ()
165 {
166 #ifdef IOM_PREINIT
167 { IOM_PREINIT }
168 #endif
169
170 #ifdef IOM_LIBEVENT
171 event_init ();
172 #endif
173 iom_valid = true;
174
175 #if IOM_SIG
176 sigemptyset (&sigs);
177
178 if (pipe (sigpipe))
179 {
180 perror ("io_manager: unable to create signal pipe, aborting.");
181 abort ();
182 }
183
184 fcntl (sigpipe[0], F_SETFL, O_NONBLOCK); fcntl (sigpipe[0], F_SETFD, FD_CLOEXEC);
185 fcntl (sigpipe[1], F_SETFL, O_NONBLOCK); fcntl (sigpipe[1], F_SETFD, FD_CLOEXEC);
186 #endif
187
188 #if IOM_CHILD
189 sw0.start (SIGCHLD);
190 #endif
191
192 #if IOM_TIME
193 io_manager::set_now ();
194
195 #ifndef IOM_LIBEVENT
196 tw0.start (TSTAMP_MAX);
197 #endif
198 #endif
199
200 #ifdef IOM_POSTINIT
201 { IOM_POSTINIT }
202 #endif
203 }
204
205 ~init ()
206 {
207 iom_valid = false;
208 }
209
210 static void required ();
211} init;
212
213void
214init::required ()
215{
216 if (!iom_valid)
217 {
218 write (2, "io_manager: early registration attempt, aborting.\n",
219 sizeof ("io_manager: early registration attempt, aborting.\n") - 1);
56 abort (); 220 abort ();
57 } 221 }
58 222}
59 tw0 ()
60 : time_watcher (this, &tw0::cb)
61 { }
62 } tw0;
63
64tstamp NOW;
65static bool iom_valid;
66io_manager iom;
67 223
68template<class watcher> 224template<class watcher>
69void io_manager::reg (watcher *w, io_manager_vec<watcher> &queue) 225void io_manager::reg (watcher &w, io_manager_vec<watcher> &queue)
70{ 226{
71 if (!iom_valid) 227 init::required ();
72 abort ();
73 228
74 if (!w->active) 229 if (!w.active)
75 { 230 {
76#if IOM_CHECK
77 queue.activity = true;
78#endif
79 queue.push_back (w); 231 queue.push_back (&w);
80 w->active = queue.size (); 232 w.active = queue.size ();
81 } 233 }
82} 234}
83 235
84template<class watcher> 236template<class watcher>
85void io_manager::unreg (watcher *w, io_manager_vec<watcher> &queue) 237void io_manager::unreg (watcher &w, io_manager_vec<watcher> &queue)
86{ 238{
87 if (!iom_valid) 239 if (!iom_valid)
88 return; 240 return;
89 241
90 if (w->active) 242 if (w.active)
91 { 243 {
92 queue [w->active - 1] = 0; 244 queue [w.active - 1] = 0;
93 w->active = 0; 245 w.active = 0;
94 } 246 }
95} 247}
96 248
97#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
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
98void time_watcher::trigger () 273 void time_watcher::trigger ()
99{ 274 {
100 call (*this); 275 call (*this);
101 276 start ();
102 iom.reg (this); 277 }
103}
104
105void io_manager::reg (time_watcher *w) { reg (w, tw); }
106void io_manager::unreg (time_watcher *w) { unreg (w, tw); }
107#endif 278#endif
108 279
109#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
110void io_manager::reg (io_watcher *w) { reg (w, iow); } 298 void io_manager::reg (io_watcher &w) { io_manager::reg (w, iow); }
111void io_manager::unreg (io_watcher *w) { unreg (w, iow); } 299 void io_manager::unreg (io_watcher &w) { io_manager::unreg (w, iow); }
300 #endif
112#endif 301#endif
113 302
114#if IOM_CHECK 303#if IOM_CHECK
115void io_manager::reg (check_watcher *w) { reg (w, cw); } 304void io_manager::reg (check_watcher &w) { io_manager::reg (w, cw); }
116void io_manager::unreg (check_watcher *w) { unreg (w, cw); } 305void io_manager::unreg (check_watcher &w) { io_manager::unreg (w, cw); }
117#endif 306#endif
118 307
119#if IOM_IDLE 308#if IOM_IDLE
120void io_manager::reg (idle_watcher *w) { reg (w, iw); } 309void io_manager::reg (idle_watcher &w) { io_manager::reg (w, iw); }
121void io_manager::unreg (idle_watcher *w) { unreg (w, iw); } 310void io_manager::unreg (idle_watcher &w) { io_manager::unreg (w, iw); }
122#endif
123
124#if IOM_TIME
125inline void set_now (void)
126{
127 struct timeval tv;
128
129 gettimeofday (&tv, 0);
130
131 NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
132}
133#endif 311#endif
134 312
135#if IOM_SIG 313#if IOM_SIG
136// race conditions galore 314static void
137 315sighandler (int signum)
138void io_manager::sighandler (int signum)
139{ 316{
140 assert (0 < signum && signum <= iom.sw.size ()); 317 sw [signum - 1]->pending = true;
141 318
142 sig_vec &sv = *iom.sw [signum - 1]; 319 // we use a pipe for signal notifications, as most current
143 320 // OSes (Linux...) do not implement pselect correctly. ugh.
144 for (int i = sv.size (); i--; ) 321 char ch = signum; // actual content not used
145 if (!sv[i]) 322 write (sigpipe[1], &ch, 1);
146 sv.erase_unordered (i);
147 else
148 sv[i]->call (*sv[i]);
149} 323}
150 324
151void io_manager::reg (sig_watcher *w) 325void io_manager::reg (sig_watcher &w)
152{ 326{
327 init::required ();
328
153 assert (0 < w->signum); 329 assert (0 < w.signum);
154 330
155 sw.reserve (w->signum); 331 sw.reserve (w.signum);
156 332
333 while (sw.size () < w.signum) // pathetic
334 sw.push_back (0);
335
157 sig_vec *&sv = sw [w->signum - 1]; 336 sig_vec *&sv = sw[w.signum - 1];
158 337
159 if (!sv) 338 if (!sv)
160 { 339 {
161 sv = new sig_vec; 340 sv = new sig_vec;
162 341
342 sigaddset (&sigs, w.signum);
343 sigprocmask (SIG_BLOCK, &sigs, NULL);
344
163 struct sigaction sa; 345 struct sigaction sa;
164 sa.sa_handler = io_manager::sighandler; 346 sa.sa_handler = sighandler;
165 sigfillset (&sa.sa_mask); 347 sigfillset (&sa.sa_mask);
166 sa.sa_flags = 0; 348 sa.sa_flags = SA_RESTART;
167 349
168 if (sigaction (w->signum, &sa, 0)) 350 if (sigaction (w.signum, &sa, 0))
169 { 351 {
170 perror ("Error while installing signal handler"); 352 perror ("io_manager: error while installing signal handler, ignoring.");
171 abort (); 353 abort ();
172 } 354 }
173 }
174 355
175 reg (w, *sv); 356 }
176}
177 357
358 io_manager::reg (w, *sv);
359}
360
178void io_manager::unreg (sig_watcher *w) 361void io_manager::unreg (sig_watcher &w)
179{ 362{
363 if (!w.active || !iom_valid)
364 return;
365
180 assert (0 < w->signum && w->signum <= sw.size ()); 366 assert (0 < w.signum && w.signum <= sw.size ());
181 367
182 unreg (w, *sw [w->signum - 1]); 368 io_manager::unreg (w, *sw[w.signum - 1]);
183} 369}
184 370
185void sig_watcher::start (int signum) 371void sig_watcher::start (int signum)
186{ 372{
187 stop (); 373 stop ();
188 this->signum = signum; 374 this->signum = signum;
189 iom.reg (this); 375 io_manager::reg (*this);
190} 376}
191#endif 377#endif
192 378
379#if IOM_CHILD
380void io_manager::reg (child_watcher &w) { io_manager::reg (w, pw); }
381void io_manager::unreg (child_watcher &w) { io_manager::unreg (w, pw); }
382#endif
383
193void io_manager::loop () 384void io_manager::loop ()
194{ 385{
386 init::required ();
387
195#if IOM_TIME 388 #if IOM_TIME
196 set_now (); 389 set_now ();
197#endif 390 #endif
198 391
199 for (;;) 392 for (;;)
200 { 393 {
394 #ifndef IOM_LIBEVENT
395 #if IOM_TIME
396 // call pending time watchers
397 {
398 bool activity;
399
400 do
401 {
402 activity = false;
403
404 for (int i = tw.size (); i--; )
405 if (!tw[i])
406 tw.erase_unordered (i);
407 else if (tw[i]->at <= NOW)
408 {
409 time_watcher &w = *tw[i];
410
411 unreg (w);
412 w.call (w);
413
414 activity = true;
415 }
416 }
417 while (activity);
418 }
419 #endif
420 #endif
421
422 #if IOM_CHECK
423 // call all check watchers
424 for (int i = cw.size (); i--; )
425 if (!cw[i])
426 cw.erase_unordered (i);
427 else
428 cw[i]->call (*cw[i]);
429 #endif
430
201 struct timeval *to = 0; 431 struct TIMEVAL *to = 0;
202 struct timeval tval; 432 struct TIMEVAL tval;
203 433
204#if IOM_IDLE 434#if IOM_IDLE
205 if (iw.size ()) 435 if (iw.size ())
206 { 436 {
207 tval.tv_sec = 0; 437 tval.tv_sec = 0;
208 tval.tv_usec = 0; 438 tval.TV_FRAC = 0;
209 to = &tval; 439 to = &tval;
210 } 440 }
211 else 441 else
212#endif 442#endif
213
214 { 443 {
215#if IOM_TIME 444 #ifndef IOM_LIBEVENT
216 time_watcher *next; 445 #if IOM_TIME
446 // find earliest active watcher
447 time_watcher *next = tw[0]; // the first time-watcher must exist at ALL times
217 448
218 for (;;) 449 for (io_manager_vec<time_watcher>::const_iterator i = tw.end (); i-- > tw.begin (); )
450 if (*i && (*i)->at < next->at)
451 next = *i;
452
453 if (next->at > NOW && next != tw[0])
219 { 454 {
220 next = tw[0]; // the first time-watcher must exist at ALL times 455 double diff = next->at - NOW;
456 tval.tv_sec = (int)diff;
457 tval.TV_FRAC = (int) ((diff - tval.tv_sec) * TV_MULT);
458 to = &tval;
459 }
460 #endif
461 #endif
462 }
221 463
222 for (int i = tw.size (); i--; ) 464 #ifndef IOM_LIBEVENT
465 #if IOM_IO || IOM_SIG
466 fd_set rfd, wfd;
467
468 FD_ZERO (&rfd);
469 FD_ZERO (&wfd);
470
471 int fds = 0;
472
473 #if IOM_IO
474 for (io_manager_vec<io_watcher>::const_iterator i = iow.end (); i-- > iow.begin (); )
223 if (!tw[i]) 475 if (*i)
224 tw.erase_unordered (i);
225 else if (tw[i]->at < next->at)
226 next = tw[i];
227
228 if (next->at > NOW)
229 { 476 {
230 if (next != tw[0]) 477 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
231 { 478 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
232 double diff = next->at - NOW; 479
233 tval.tv_sec = (int)diff; 480 if ((*i)->fd >= fds) fds = (*i)->fd + 1;
234 tval.tv_usec = (int) ((diff - tval.tv_sec) * 1000000);
235 to = &tval;
236 }
237 break;
238 } 481 }
239 else 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;
519 }
520 #endif
521
522 if (fds > 0)
523 {
524 #if IOM_SIG
525 if (FD_ISSET (sigpipe[0], &rfd))
240 { 526 {
241 unreg (next); 527 char ch;
242 next->call (*next); 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 }
243 } 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
244 } 563 }
245#endif 564 else if (fds < 0 && errno != EINTR)
246 565 {
566 perror ("io_manager: fatal error while waiting for I/O or time event, aborting.");
567 abort ();
247 } 568 }
248 569#if IOM_IDLE
249#if IOM_CHECK
250 tw.activity = false;
251
252 for (int i = cw.size (); i--; )
253 if (!cw[i])
254 cw.erase_unordered (i);
255 else 570 else
256 cw[i]->call (*cw[i]);
257
258 if (tw.activity)
259 {
260 tval.tv_sec = 0;
261 tval.tv_usec = 0;
262 to = &tval;
263 }
264#endif
265
266#if IOM_IO
267 fd_set rfd, wfd;
268
269 FD_ZERO (&rfd);
270 FD_ZERO (&wfd);
271
272 int fds = 0;
273
274 for (io_manager_vec<io_watcher>::iterator i = iow.end (); i-- > iow.begin (); )
275 if (*i)
276 {
277 if ((*i)->events & EVENT_READ ) FD_SET ((*i)->fd, &rfd);
278 if ((*i)->events & EVENT_WRITE) FD_SET ((*i)->fd, &wfd);
279
280 if ((*i)->fd >= fds) fds = (*i)->fd + 1;
281 }
282
283 if (!to && !fds) //TODO: also check idle_watchers and check_watchers
284 break; // no events
285
286 fds = select (fds, &rfd, &wfd, NULL, to);
287# if IOM_TIME
288 set_now ();
289# endif
290
291 if (fds > 0)
292 for (int i = iow.size (); i--; )
293 if (!iow[i])
294 iow.erase_unordered (i);
295 else
296 {
297 short revents = iow[i]->events;
298
299 if (!FD_ISSET (iow[i]->fd, &rfd)) revents &= ~EVENT_READ;
300 if (!FD_ISSET (iow[i]->fd, &wfd)) revents &= ~EVENT_WRITE;
301
302 if (revents)
303 iow[i]->call (*iow[i], revents);
304 }
305 else if (fds < 0 && errno != EINTR)
306 {
307 perror ("Error while waiting for I/O or time event");
308 abort ();
309 }
310#if IOM_IDLE
311 else
312 for (int i = iw.size (); i--; ) 571 for (int i = iw.size (); i--; )
313 if (!iw[i]) 572 if (!iw[i])
314 iw.erase_unordered (i); 573 iw.erase_unordered (i);
315 else 574 else
316 iw[i]->call (*iw[i]); 575 iw[i]->call (*iw[i]);
317#endif 576#endif
318 577
319#elif IOM_TIME 578 #else
579 need_set_now = true;
580
320 if (!to) 581 if (to)
321 break; 582 event_loop (EVLOOP_NONBLOCK);
583 else
584 event_loop (EVLOOP_ONCE);
322 585
323 select (0, 0, 0, 0, &to); 586 if (need_set_now) set_now ();
324 set_now (); 587 #endif
325#else 588 //TODO: IOM_IDLE
326 break;
327#endif
328
329 } 589 }
330} 590}
331 591
332io_manager::io_manager ()
333{
334 iom_valid = true;
335
336#if IOM_TIME
337 set_now ();
338
339 tw0.start (TSTAMP_MAX);
340#endif
341}
342
343io_manager::~io_manager ()
344{
345 iom_valid = false;
346}
347

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines