ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/iom.C
Revision: 1.10
Committed: Fri Apr 4 05:26:45 2003 UTC (21 years, 1 month ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +35 -22 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     #include "slog.h"
27     #include "iom.h"
28    
29 pcg 1.10 tstamp NOW;
30     bool iom_valid;
31     io_manager iom;
32    
33 pcg 1.9 inline bool earliest_first (const time_watcher *a, const time_watcher *b)
34 pcg 1.1 {
35     return a->at > b->at;
36     }
37    
38 pcg 1.2 void time_watcher::set (tstamp when)
39 pcg 1.1 {
40     at = when;
41 pcg 1.6
42     if (registered)
43     iom.reschedule_time_watchers ();
44     else
45     iom.reg (this);
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     void time_watcher::start ()
59     {
60 pcg 1.6 if (!registered)
61     iom.reg (this);
62 pcg 1.4 }
63    
64 pcg 1.10 time_watcher::~time_watcher ()
65     {
66     if (iom_valid)
67     iom.unreg (this);
68     }
69    
70     io_watcher::~io_watcher ()
71     {
72     if (iom_valid)
73     iom.unreg (this);
74     }
75    
76 pcg 1.9 void io_manager::reg (io_watcher *w)
77 pcg 1.1 {
78     pollfd pfd;
79    
80     pfs.push_back (pfd);
81     iow.push_back (w);
82 pcg 1.10
83     w->p = &(*(pfs.end () - 1));
84 pcg 1.1 }
85    
86 pcg 1.7 void io_manager::unreg (io_watcher *w)
87 pcg 1.1 {
88 pcg 1.10 if (w->p)
89     {
90     unsigned int sz = iow.size ();
91     unsigned int i = find (iow.begin (), iow.end (), w) - iow.begin ();
92    
93     assert (i != sz);
94 pcg 1.1
95     if (sz == 1)
96     {
97     pfs.clear ();
98     iow.clear ();
99     }
100     else if (i == sz - 1)
101     {
102     iow.pop_back ();
103     pfs.pop_back ();
104     }
105     else
106     {
107     iow[i] = iow[sz - 1]; iow.pop_back ();
108     pfs[i] = pfs[sz - 1]; pfs.pop_back ();
109     }
110 pcg 1.10
111     w->p = 0;
112 pcg 1.1 }
113     }
114    
115 pcg 1.6 void io_manager::reschedule_time_watchers ()
116     {
117 pcg 1.9 make_heap (tw.begin (), tw.end (), earliest_first);
118 pcg 1.6 }
119    
120 pcg 1.1 void io_manager::reg (time_watcher *w)
121     {
122 pcg 1.7 w->registered = true;
123    
124 pcg 1.1 tw.push_back (w);
125 pcg 1.9 push_heap (tw.begin (), tw.end (), earliest_first);
126 pcg 1.1 }
127    
128 pcg 1.7 void io_manager::unreg (time_watcher *w)
129 pcg 1.1 {
130 pcg 1.7 if (w->registered)
131     {
132     unsigned int sz = tw.size ();
133     unsigned int i = find (tw.begin (), tw.end (), w) - tw.begin ();
134 pcg 1.1
135 pcg 1.10 assert (i != sz);
136    
137     if (i != sz - 1)
138     tw[i] = tw[sz - 1];
139 pcg 1.7
140 pcg 1.10 tw.pop_back ();
141     reschedule_time_watchers ();
142 pcg 1.1
143 pcg 1.7 w->registered = false;
144 pcg 1.1 }
145     }
146    
147     inline void set_now (void)
148     {
149     struct timeval tv;
150    
151     gettimeofday (&tv, 0);
152    
153 pcg 1.2 NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
154 pcg 1.1 }
155    
156     void io_manager::loop ()
157     {
158     set_now ();
159    
160 pcg 1.4 for (;;)
161 pcg 1.1 {
162 pcg 1.4 while (tw[0]->at <= NOW)
163     {
164 pcg 1.7 // remove the first watcher
165     time_watcher *w = tw[0];
166    
167 pcg 1.9 pop_heap (tw.begin (), tw.end (), earliest_first);
168 pcg 1.6 tw.pop_back ();
169 pcg 1.1
170 pcg 1.7 w->registered = false;
171    
172     // call it
173 pcg 1.9 w->call (*w);
174 pcg 1.7
175     // re-add it if necessary
176     if (w->at >= 0 && !w->registered)
177     reg (w);
178 pcg 1.4 }
179 pcg 1.1
180 pcg 1.4 int timeout = (int) ((tw[0]->at - NOW) * 1000);
181 pcg 1.1
182 pcg 1.4 int fds = poll (&pfs[0], pfs.size (), timeout);
183 pcg 1.1
184 pcg 1.4 set_now ();
185 pcg 1.1
186 pcg 1.9 vector<io_watcher *>::iterator w;
187     vector<pollfd>::iterator p;
188    
189     for (w = iow.begin (), p = pfs.begin ();
190     fds > 0 && w < iow.end ();
191     ++w, ++p)
192     if (p->revents)
193 pcg 1.4 {
194     --fds;
195 pcg 1.9 (*w)->call (**w, p->revents);
196 pcg 1.4 }
197 pcg 1.1 }
198     }
199    
200 pcg 1.9 void io_manager::idle_cb (time_watcher &w)
201 pcg 1.4 {
202 pcg 1.9 w.at = NOW + 86400; // wake up every day, for no good reason
203 pcg 1.4 }
204    
205 pcg 1.1 io_manager::io_manager ()
206     {
207 pcg 1.10 iom_valid = true;
208    
209 pcg 1.1 set_now ();
210 pcg 1.4 idle = new time_watcher (this, &io_manager::idle_cb);
211     idle->start (0);
212 pcg 1.1 }
213    
214     io_manager::~io_manager ()
215     {
216 pcg 1.10 iom_valid = false;
217 pcg 1.1 }
218