ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.1
Committed: Mon Nov 24 17:28:08 2003 UTC (20 years, 6 months ago) by pcg
Content type: text/plain
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 iom.C -- generic I/O multiplexor
3 Copyright (C) 2003 Marc Lehmann <pcg@goof.com>
4
5 This program is free software; you can redistribute it and/or modify
6 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
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "../config.h"
21
22 #include <cstdio>
23
24 #include <sys/select.h>
25 #include <sys/time.h>
26
27 #include "iom.h"
28
29 tstamp NOW;
30 bool iom_valid;
31 io_manager iom;
32
33 void time_watcher::trigger ()
34 {
35 call (*this);
36
37 iom.reg (this);
38 }
39
40 time_watcher::~time_watcher ()
41 {
42 if (iom_valid)
43 iom.unreg (this);
44 }
45
46 io_watcher::~io_watcher ()
47 {
48 if (iom_valid)
49 iom.unreg (this);
50 }
51
52 void io_manager::reg (io_watcher *w)
53 {
54 if (find (iow.begin (), iow.end (), w) == iow.end ())
55 iow.push_back (w);
56 }
57
58 void io_manager::unreg (io_watcher *w)
59 {
60 iow.erase (find (iow.begin (), iow.end (), w));
61 }
62
63 void io_manager::reg (time_watcher *w)
64 {
65 if (find (tw.begin (), tw.end (), w) == tw.end ())
66 tw.push_back (w);
67 }
68
69 void io_manager::unreg (time_watcher *w)
70 {
71 tw.erase (find (tw.begin (), tw.end (), w));
72 }
73
74 inline void set_now (void)
75 {
76 struct timeval tv;
77
78 gettimeofday (&tv, 0);
79
80 NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
81 }
82
83 void io_manager::loop ()
84 {
85 set_now ();
86
87 for (;;)
88 {
89 time_watcher *w;
90
91 for (;;)
92 {
93 w = tw[0];
94
95 for (time_watcher **i = tw.begin (); i != tw.end (); ++i)
96 if ((*i)->at < w->at)
97 w = *i;
98
99 if (w->at > NOW)
100 break;
101
102 // call it
103 w->call (*w);
104
105 // re-add it if necessary
106 if (w->at >= 0)
107 reg (w);
108 }
109
110 struct timeval to;
111 double diff = w->at - NOW;
112 to.tv_sec = (int)diff;
113 to.tv_usec = (int)((diff - to.tv_sec) * 1000000);
114
115 fd_set rfd, wfd;
116
117 FD_ZERO (&rfd);
118 FD_ZERO (&wfd);
119
120 int fds = 0;
121
122 for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
123 {
124 if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
125 if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
126
127 if ((*w)->fd > fds) fds = (*w)->fd;
128 }
129
130 fds = select (fds + 1, &rfd, &wfd, 0, &to);
131
132 set_now ();
133
134 if (fds > 0)
135 for (io_watcher **w = iow.begin (); w < iow.end (); w++)
136 {
137 short revents = (*w)->events;
138
139 if (!FD_ISSET ((*w)->fd, &rfd)) revents &= ~EVENT_READ;
140 if (!FD_ISSET ((*w)->fd, &wfd)) revents &= ~EVENT_WRITE;
141
142 if (revents)
143 (*w)->call (**w, revents);
144 }
145 }
146 }
147
148 void io_manager::idle_cb (time_watcher &w)
149 {
150 w.at = NOW + 1000000000;
151 }
152
153 io_manager::io_manager ()
154 {
155 set_now ();
156
157 iom_valid = true;
158
159 idle = new time_watcher (this, &io_manager::idle_cb);
160 idle->start (0);
161 }
162
163 io_manager::~io_manager ()
164 {
165 iom_valid = false;
166 }
167