ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.3
Committed: Tue Nov 25 17:11:33 2003 UTC (20 years, 6 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +4 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
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 void time_watcher::trigger ()
34 {
35 call (*this);
36
37 iom.reg (this);
38 }
39
40 time_watcher::~time_watcher ()
41 {
42 if (iom_valid)
43 iom.unreg (this);
44
45 at = TSTAMP_CANCEL;
46 }
47
48 io_watcher::~io_watcher ()
49 {
50 if (iom_valid)
51 iom.unreg (this);
52 }
53
54 void io_manager::reg (io_watcher *w)
55 {
56 if (find (iow.begin (), iow.end (), w) == iow.end ())
57 iow.push_back (w);
58 }
59
60 void io_manager::unreg (io_watcher *w)
61 {
62 iow.erase (find (iow.begin (), iow.end (), w));
63 }
64
65 void io_manager::reg (time_watcher *w)
66 {
67 if (find (tw.begin (), tw.end (), w) == tw.end ())
68 tw.push_back (w);
69 }
70
71 void io_manager::unreg (time_watcher *w)
72 {
73 tw.erase (find (tw.begin (), tw.end (), w));
74 }
75
76 inline void set_now (void)
77 {
78 struct timeval tv;
79
80 gettimeofday (&tv, 0);
81
82 NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
83 }
84
85 void io_manager::loop ()
86 {
87 set_now ();
88
89 for (;;)
90 {
91 time_watcher *w;
92
93 for (;;)
94 {
95 w = tw[0];
96
97 for (time_watcher **i = tw.begin (); i != tw.end (); ++i)
98 if ((*i)->at < w->at)
99 w = *i;
100
101 if (w->at > NOW)
102 break;
103
104 // call it
105 w->call (*w);
106
107 if (w->at < 0)
108 unreg (w);
109 }
110
111 struct timeval to;
112 double diff = w->at - NOW;
113 to.tv_sec = (int)diff;
114 to.tv_usec = (int)((diff - to.tv_sec) * 1000000);
115
116 fd_set rfd, wfd;
117
118 FD_ZERO (&rfd);
119 FD_ZERO (&wfd);
120
121 int fds = 0;
122
123 for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
124 {
125 if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
126 if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
127
128 if ((*w)->fd > fds) fds = (*w)->fd;
129 }
130
131 fds = select (fds + 1, &rfd, &wfd, 0, &to);
132
133 set_now ();
134
135 if (fds > 0)
136 for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
137 {
138 short revents = (*w)->events;
139
140 if (!FD_ISSET ((*w)->fd, &rfd)) revents &= ~EVENT_READ;
141 if (!FD_ISSET ((*w)->fd, &wfd)) revents &= ~EVENT_WRITE;
142
143 if (revents)
144 (*w)->call (**w, revents);
145 }
146 }
147 }
148
149 void io_manager::idle_cb (time_watcher &w)
150 {
151 w.at = NOW + 1000000000;
152 }
153
154 io_manager::io_manager ()
155 {
156 set_now ();
157
158 iom_valid = true;
159
160 idle = new time_watcher (this, &io_manager::idle_cb);
161 idle->start (0);
162 }
163
164 io_manager::~io_manager ()
165 {
166 iom_valid = false;
167 }
168