ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/iom.C
Revision: 1.11
Committed: Sat Apr 5 02:32:40 2003 UTC (21 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: VPE_0_9, VPE_1_0
Changes since 1.10: +43 -21 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2     iom.C -- I/O multiplexor
3    
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8    
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     GNU General Public License for more details.
13    
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17     */
18    
19     #include "config.h"
20    
21     #include <sys/time.h>
22    
23     #include <algorithm>
24     #include <functional>
25    
26 pcg 1.11 #include "gettext.h"
27    
28 pcg 1.1 #include "slog.h"
29     #include "iom.h"
30    
31 pcg 1.10 tstamp NOW;
32     bool iom_valid;
33     io_manager iom;
34    
35 pcg 1.9 inline bool earliest_first (const time_watcher *a, const time_watcher *b)
36 pcg 1.1 {
37     return a->at > b->at;
38     }
39    
40 pcg 1.2 void time_watcher::set (tstamp when)
41 pcg 1.1 {
42     at = when;
43 pcg 1.6
44     if (registered)
45     iom.reschedule_time_watchers ();
46 pcg 1.1 }
47    
48 pcg 1.4 void time_watcher::trigger ()
49     {
50 pcg 1.9 call (*this);
51 pcg 1.6
52     if (registered)
53     iom.reschedule_time_watchers ();
54     else
55     iom.reg (this);
56 pcg 1.4 }
57    
58 pcg 1.11 time_watcher::~time_watcher ()
59 pcg 1.4 {
60 pcg 1.11 if (iom_valid)
61     iom.unreg (this);
62 pcg 1.4 }
63    
64 pcg 1.11 void io_watcher::set(int fd_, short events_)
65 pcg 1.10 {
66 pcg 1.11 fd = fd_;
67     events = events_;
68    
69     if (registered)
70     {
71     iom.unreg (this);
72     iom.reg (this);
73     }
74 pcg 1.10 }
75    
76     io_watcher::~io_watcher ()
77     {
78     if (iom_valid)
79     iom.unreg (this);
80     }
81    
82 pcg 1.9 void io_manager::reg (io_watcher *w)
83 pcg 1.1 {
84 pcg 1.11 if (!w->registered)
85     {
86     w->registered = true;
87    
88     pollfd pfd;
89 pcg 1.1
90 pcg 1.11 pfd.fd = w->fd;
91     pfd.events = w->events;
92 pcg 1.10
93 pcg 1.11 pfs.push_back (pfd);
94     iow.push_back (w);
95     }
96 pcg 1.1 }
97    
98 pcg 1.7 void io_manager::unreg (io_watcher *w)
99 pcg 1.1 {
100 pcg 1.11 if (w->registered)
101 pcg 1.10 {
102 pcg 1.11 w->registered = false;
103    
104 pcg 1.10 unsigned int sz = iow.size ();
105     unsigned int i = find (iow.begin (), iow.end (), w) - iow.begin ();
106    
107     assert (i != sz);
108 pcg 1.1
109     if (sz == 1)
110     {
111     pfs.clear ();
112     iow.clear ();
113     }
114     else if (i == sz - 1)
115     {
116     iow.pop_back ();
117     pfs.pop_back ();
118     }
119     else
120     {
121     iow[i] = iow[sz - 1]; iow.pop_back ();
122     pfs[i] = pfs[sz - 1]; pfs.pop_back ();
123     }
124     }
125     }
126    
127 pcg 1.6 void io_manager::reschedule_time_watchers ()
128     {
129 pcg 1.9 make_heap (tw.begin (), tw.end (), earliest_first);
130 pcg 1.6 }
131    
132 pcg 1.1 void io_manager::reg (time_watcher *w)
133     {
134 pcg 1.11 if (!w->registered)
135     {
136     w->registered = true;
137 pcg 1.7
138 pcg 1.11 tw.push_back (w);
139     push_heap (tw.begin (), tw.end (), earliest_first);
140     }
141 pcg 1.1 }
142    
143 pcg 1.7 void io_manager::unreg (time_watcher *w)
144 pcg 1.1 {
145 pcg 1.7 if (w->registered)
146     {
147 pcg 1.11 w->registered = false;
148    
149 pcg 1.7 unsigned int sz = tw.size ();
150     unsigned int i = find (tw.begin (), tw.end (), w) - tw.begin ();
151 pcg 1.1
152 pcg 1.10 assert (i != sz);
153    
154     if (i != sz - 1)
155     tw[i] = tw[sz - 1];
156 pcg 1.7
157 pcg 1.10 tw.pop_back ();
158     reschedule_time_watchers ();
159 pcg 1.1 }
160     }
161    
162     inline void set_now (void)
163     {
164     struct timeval tv;
165    
166     gettimeofday (&tv, 0);
167    
168 pcg 1.2 NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
169 pcg 1.1 }
170    
171     void io_manager::loop ()
172     {
173     set_now ();
174    
175 pcg 1.4 for (;;)
176 pcg 1.1 {
177 pcg 1.4 while (tw[0]->at <= NOW)
178     {
179 pcg 1.7 // remove the first watcher
180     time_watcher *w = tw[0];
181    
182 pcg 1.9 pop_heap (tw.begin (), tw.end (), earliest_first);
183 pcg 1.6 tw.pop_back ();
184 pcg 1.1
185 pcg 1.7 w->registered = false;
186    
187     // call it
188 pcg 1.9 w->call (*w);
189 pcg 1.7
190     // re-add it if necessary
191     if (w->at >= 0 && !w->registered)
192     reg (w);
193 pcg 1.4 }
194 pcg 1.1
195 pcg 1.4 int timeout = (int) ((tw[0]->at - NOW) * 1000);
196 pcg 1.1
197 pcg 1.4 int fds = poll (&pfs[0], pfs.size (), timeout);
198 pcg 1.1
199 pcg 1.4 set_now ();
200 pcg 1.1
201 pcg 1.9 vector<io_watcher *>::iterator w;
202     vector<pollfd>::iterator p;
203    
204     for (w = iow.begin (), p = pfs.begin ();
205     fds > 0 && w < iow.end ();
206     ++w, ++p)
207     if (p->revents)
208 pcg 1.4 {
209     --fds;
210 pcg 1.11
211     if (p->revents & POLLNVAL)
212     {
213     slog (L_ERR, _("io_watcher started on illegal file descriptor, disabling."));
214     (*w)->stop ();
215     }
216     else
217     (*w)->call (**w, p->revents);
218 pcg 1.4 }
219 pcg 1.1 }
220     }
221    
222 pcg 1.9 void io_manager::idle_cb (time_watcher &w)
223 pcg 1.4 {
224 pcg 1.9 w.at = NOW + 86400; // wake up every day, for no good reason
225 pcg 1.4 }
226    
227 pcg 1.1 io_manager::io_manager ()
228     {
229 pcg 1.10 iom_valid = true;
230    
231 pcg 1.1 set_now ();
232 pcg 1.4 idle = new time_watcher (this, &io_manager::idle_cb);
233     idle->start (0);
234 pcg 1.1 }
235    
236     io_manager::~io_manager ()
237     {
238 pcg 1.10 iom_valid = false;
239 pcg 1.1 }
240