ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.5
Committed: Sat Nov 29 18:42:07 2003 UTC (20 years, 5 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.4: +27 -27 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 pcg 1.5 struct timeval *to = 0;
135    
136 pcg 1.4 #if IOM_TIME
137 pcg 1.5 struct timeval tval;
138 pcg 1.1 time_watcher *w;
139    
140 pcg 1.5 for (;tw.size ();)
141 pcg 1.1 {
142     w = tw[0];
143    
144 pcg 1.4 for (time_watcher **i = tw.begin (); i < tw.end (); ++i)
145 pcg 1.1 if ((*i)->at < w->at)
146     w = *i;
147    
148     if (w->at > NOW)
149 pcg 1.5 {
150     double diff = w->at - NOW;
151     tval.tv_sec = (int)diff;
152     tval.tv_usec = (int)((diff - tval.tv_sec) * 1000000);
153     to = &tval;
154     break;
155     }
156     else if (w->at >= 0)
157     w->call (*w);
158     else
159 pcg 1.3 unreg (w);
160 pcg 1.1 }
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