ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.6
Committed: Tue Dec 2 21:49:46 2003 UTC (20 years, 5 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.5: +5 -5 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.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 pcg 1.4 template<class watcher>
34     void io_manager::reg (watcher *w, simplevec<watcher *> &queue)
35     {
36     if (find (queue.begin (), queue.end (), w) == queue.end ())
37     queue.push_back (w);
38     }
39    
40     template<class watcher>
41     void io_manager::unreg (watcher *w, simplevec<watcher *> &queue)
42     {
43     queue.erase (find (queue.begin (), queue.end (), w));
44     }
45    
46     #if IOM_IO
47     io_watcher::~io_watcher ()
48     {
49     if (iom_valid)
50     iom.unreg (this);
51     }
52    
53     void io_manager::reg (io_watcher *w)
54     {
55     reg (w, iow);
56     }
57    
58     void io_manager::unreg (io_watcher *w)
59     {
60     unreg (w, iow);
61     }
62    
63     #endif
64    
65     #if IOM_TIME
66 pcg 1.1 void time_watcher::trigger ()
67     {
68     call (*this);
69    
70     iom.reg (this);
71     }
72    
73     time_watcher::~time_watcher ()
74     {
75     if (iom_valid)
76     iom.unreg (this);
77 pcg 1.3
78     at = TSTAMP_CANCEL;
79 pcg 1.1 }
80    
81 pcg 1.4 void io_manager::reg (time_watcher *w)
82 pcg 1.1 {
83 pcg 1.4 reg (w, tw);
84 pcg 1.1 }
85    
86 pcg 1.4 void io_manager::unreg (time_watcher *w)
87 pcg 1.1 {
88 pcg 1.4 unreg (w, tw);
89 pcg 1.1 }
90 pcg 1.4 #endif
91 pcg 1.1
92 pcg 1.4 #if IOM_CHECK
93     check_watcher::~check_watcher ()
94 pcg 1.1 {
95 pcg 1.4 if (iom_valid)
96     iom.unreg (this);
97 pcg 1.1 }
98    
99 pcg 1.4 void io_manager::reg (check_watcher *w)
100 pcg 1.1 {
101 pcg 1.4 reg (w, cw);
102 pcg 1.1 }
103    
104 pcg 1.4 void io_manager::unreg (check_watcher *w)
105 pcg 1.1 {
106 pcg 1.4 unreg (w, cw);
107 pcg 1.1 }
108 pcg 1.4 #endif
109 pcg 1.1
110 pcg 1.4 #if IOM_TIME
111 pcg 1.1 inline void set_now (void)
112     {
113     struct timeval tv;
114    
115     gettimeofday (&tv, 0);
116    
117     NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
118 pcg 1.4 #endif
119 pcg 1.1 }
120    
121     void io_manager::loop ()
122     {
123 pcg 1.4 #if IOM_TIME
124 pcg 1.1 set_now ();
125 pcg 1.4 #endif
126 pcg 1.1
127     for (;;)
128     {
129 pcg 1.5 struct timeval *to = 0;
130    
131 pcg 1.4 #if IOM_TIME
132 pcg 1.5 struct timeval tval;
133 pcg 1.1 time_watcher *w;
134    
135 pcg 1.5 for (;tw.size ();)
136 pcg 1.1 {
137     w = tw[0];
138    
139 pcg 1.4 for (time_watcher **i = tw.begin (); i < tw.end (); ++i)
140 pcg 1.1 if ((*i)->at < w->at)
141     w = *i;
142    
143     if (w->at > NOW)
144 pcg 1.5 {
145     double diff = w->at - NOW;
146     tval.tv_sec = (int)diff;
147     tval.tv_usec = (int)((diff - tval.tv_sec) * 1000000);
148     to = &tval;
149     break;
150     }
151     else if (w->at >= 0)
152     w->call (*w);
153     else
154 pcg 1.3 unreg (w);
155 pcg 1.1 }
156 pcg 1.6 #endif
157    
158     #if IOM_CHECK
159     for (int i = 0; i < cw.size (); ++i)
160     cw[i]->call (*cw[i]);
161 pcg 1.4 #endif
162 pcg 1.1
163 pcg 1.4 #if IOM_IO
164 pcg 1.1 fd_set rfd, wfd;
165    
166     FD_ZERO (&rfd);
167     FD_ZERO (&wfd);
168    
169     int fds = 0;
170    
171     for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
172 pcg 1.2 {
173     if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
174     if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
175 pcg 1.1
176 pcg 1.5 if ((*w)->fd >= fds) fds = (*w)->fd + 1;
177 pcg 1.2 }
178 pcg 1.1
179 pcg 1.5 if (!to && !fds)
180     break; // no events
181    
182     fds = select (fds, &rfd, &wfd, 0, to);
183 pcg 1.4 # if IOM_TIME
184 pcg 1.1 set_now ();
185 pcg 1.4 # endif
186 pcg 1.1
187     if (fds > 0)
188 pcg 1.4 for (int i = 0; i < iow.size (); ++i)
189 pcg 1.1 {
190 pcg 1.4 io_watcher *w = iow[i];
191 pcg 1.1
192 pcg 1.4 short revents = w->events;
193    
194     if (!FD_ISSET (w->fd, &rfd)) revents &= ~EVENT_READ;
195     if (!FD_ISSET (w->fd, &wfd)) revents &= ~EVENT_WRITE;
196 pcg 1.1
197     if (revents)
198 pcg 1.4 w->call (*w, revents);
199 pcg 1.1 }
200 pcg 1.4 #elif IOM_TIME
201 pcg 1.5 if (!to)
202     break;
203    
204 pcg 1.4 select (0, 0, 0, 0, &to);
205     set_now ();
206 pcg 1.5 #else
207     break;
208 pcg 1.4 #endif
209 pcg 1.5 }
210 pcg 1.1 }
211    
212     io_manager::io_manager ()
213     {
214 pcg 1.5 #if IOM_TIME
215 pcg 1.1 set_now ();
216 pcg 1.5 #endif
217 pcg 1.1
218     iom_valid = true;
219     }
220    
221     io_manager::~io_manager ()
222     {
223     iom_valid = false;
224     }
225