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