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

# 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     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 pcg 1.3
45     at = TSTAMP_CANCEL;
46 pcg 1.1 }
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 pcg 1.3 if (w->at < 0)
108     unreg (w);
109 pcg 1.1 }
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 pcg 1.2 {
125     if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
126     if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
127 pcg 1.1
128 pcg 1.2 if ((*w)->fd > fds) fds = (*w)->fd;
129     }
130 pcg 1.1
131     fds = select (fds + 1, &rfd, &wfd, 0, &to);
132    
133     set_now ();
134    
135     if (fds > 0)
136 pcg 1.2 for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
137 pcg 1.1 {
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