ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.4
Committed: Wed Nov 26 10:42:34 2003 UTC (20 years, 6 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.3: +78 -21 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.4 #if IOM_CHECK
130     for (int i = 0; i < cw.size (); ++i)
131     cw[i]->call (*cw[i]);
132     #endif
133    
134     #if IOM_TIME
135 pcg 1.1 time_watcher *w;
136    
137     for (;;)
138     {
139     w = tw[0];
140    
141 pcg 1.4 for (time_watcher **i = tw.begin (); i < tw.end (); ++i)
142 pcg 1.1 if ((*i)->at < w->at)
143     w = *i;
144    
145     if (w->at > NOW)
146     break;
147    
148     // call it
149     w->call (*w);
150    
151 pcg 1.3 if (w->at < 0)
152     unreg (w);
153 pcg 1.1 }
154    
155 pcg 1.4 double diff = w->at - NOW;
156 pcg 1.1 struct timeval to;
157     to.tv_sec = (int)diff;
158     to.tv_usec = (int)((diff - to.tv_sec) * 1000000);
159 pcg 1.4 #endif
160 pcg 1.1
161 pcg 1.4 #if IOM_IO
162 pcg 1.1 fd_set rfd, wfd;
163    
164     FD_ZERO (&rfd);
165     FD_ZERO (&wfd);
166    
167     int fds = 0;
168    
169     for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
170 pcg 1.2 {
171     if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
172     if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
173 pcg 1.1
174 pcg 1.2 if ((*w)->fd > fds) fds = (*w)->fd;
175     }
176 pcg 1.1
177 pcg 1.4 # if IOM_TIME
178 pcg 1.1 fds = select (fds + 1, &rfd, &wfd, 0, &to);
179     set_now ();
180 pcg 1.4 # else
181     fds = select (fds + 1, &rfd, &wfd, 0, 0);
182     # endif
183 pcg 1.1
184     if (fds > 0)
185 pcg 1.4 for (int i = 0; i < iow.size (); ++i)
186 pcg 1.1 {
187 pcg 1.4 io_watcher *w = iow[i];
188 pcg 1.1
189 pcg 1.4 short revents = w->events;
190    
191     if (!FD_ISSET (w->fd, &rfd)) revents &= ~EVENT_READ;
192     if (!FD_ISSET (w->fd, &wfd)) revents &= ~EVENT_WRITE;
193 pcg 1.1
194     if (revents)
195 pcg 1.4 w->call (*w, revents);
196 pcg 1.1 }
197     }
198 pcg 1.4 #elif IOM_TIME
199     select (0, 0, 0, 0, &to);
200     set_now ();
201     #endif
202 pcg 1.1 }
203    
204     void io_manager::idle_cb (time_watcher &w)
205     {
206     w.at = NOW + 1000000000;
207     }
208    
209     io_manager::io_manager ()
210     {
211     set_now ();
212    
213     iom_valid = true;
214    
215 pcg 1.4 #if IOM_TIME
216 pcg 1.1 idle = new time_watcher (this, &io_manager::idle_cb);
217     idle->start (0);
218 pcg 1.4 #endif
219 pcg 1.1 }
220    
221     io_manager::~io_manager ()
222     {
223     iom_valid = false;
224     }
225