ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/iom.C
Revision: 1.2
Committed: Tue Nov 25 15:25:17 2003 UTC (20 years, 6 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.1: +6 -6 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     }
45    
46     io_watcher::~io_watcher ()
47     {
48     if (iom_valid)
49     iom.unreg (this);
50     }
51    
52     void io_manager::reg (io_watcher *w)
53     {
54     if (find (iow.begin (), iow.end (), w) == iow.end ())
55     iow.push_back (w);
56     }
57    
58     void io_manager::unreg (io_watcher *w)
59     {
60     iow.erase (find (iow.begin (), iow.end (), w));
61     }
62    
63     void io_manager::reg (time_watcher *w)
64     {
65     if (find (tw.begin (), tw.end (), w) == tw.end ())
66     tw.push_back (w);
67     }
68    
69     void io_manager::unreg (time_watcher *w)
70     {
71     tw.erase (find (tw.begin (), tw.end (), w));
72     }
73    
74     inline void set_now (void)
75     {
76     struct timeval tv;
77    
78     gettimeofday (&tv, 0);
79    
80     NOW = (tstamp)tv.tv_sec + (tstamp)tv.tv_usec / 1000000;
81     }
82    
83     void io_manager::loop ()
84     {
85     set_now ();
86    
87     for (;;)
88     {
89     time_watcher *w;
90    
91     for (;;)
92     {
93     w = tw[0];
94    
95     for (time_watcher **i = tw.begin (); i != tw.end (); ++i)
96     if ((*i)->at < w->at)
97     w = *i;
98    
99     if (w->at > NOW)
100     break;
101    
102     // call it
103     w->call (*w);
104    
105     // re-add it if necessary
106     if (w->at >= 0)
107     reg (w);
108     }
109    
110     struct timeval to;
111     double diff = w->at - NOW;
112     to.tv_sec = (int)diff;
113     to.tv_usec = (int)((diff - to.tv_sec) * 1000000);
114    
115     fd_set rfd, wfd;
116    
117     FD_ZERO (&rfd);
118     FD_ZERO (&wfd);
119    
120     int fds = 0;
121    
122     for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
123 pcg 1.2 {
124     if ((*w)->events & EVENT_READ ) FD_SET ((*w)->fd, &rfd);
125     if ((*w)->events & EVENT_WRITE) FD_SET ((*w)->fd, &wfd);
126 pcg 1.1
127 pcg 1.2 if ((*w)->fd > fds) fds = (*w)->fd;
128     }
129 pcg 1.1
130     fds = select (fds + 1, &rfd, &wfd, 0, &to);
131    
132     set_now ();
133    
134     if (fds > 0)
135 pcg 1.2 for (io_watcher **w = iow.begin (); w < iow.end (); ++w)
136 pcg 1.1 {
137     short revents = (*w)->events;
138    
139     if (!FD_ISSET ((*w)->fd, &rfd)) revents &= ~EVENT_READ;
140     if (!FD_ISSET ((*w)->fd, &wfd)) revents &= ~EVENT_WRITE;
141    
142     if (revents)
143     (*w)->call (**w, revents);
144     }
145     }
146     }
147    
148     void io_manager::idle_cb (time_watcher &w)
149     {
150     w.at = NOW + 1000000000;
151     }
152    
153     io_manager::io_manager ()
154     {
155     set_now ();
156    
157     iom_valid = true;
158    
159     idle = new time_watcher (this, &io_manager::idle_cb);
160     idle->start (0);
161     }
162    
163     io_manager::~io_manager ()
164     {
165     iom_valid = false;
166     }
167