eventloop.cpp
Go to the documentation of this file.
1/*
2 *
3 * D-Bus++ - C++ bindings for D-Bus
4 *
5 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com>
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <dbus-c++/eventloop.h>
29#include <dbus-c++/debug.h>
30
31#include <sys/poll.h>
32#include <sys/time.h>
33
34#include <dbus/dbus.h>
35
36using namespace DBus;
37using namespace std;
38
39static double millis(timeval tv)
40{
41 return (tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0);
42}
43
44DefaultTimeout::DefaultTimeout(int interval, bool repeat, DefaultMainLoop *ed)
45 : _enabled(true), _interval(interval), _repeat(repeat), _expiration(0), _data(0), _disp(ed)
46{
47 timeval now;
48 gettimeofday(&now, NULL);
49
51
53 _disp->_timeouts.push_back(this);
55}
56
63
65 : _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed)
66{
68 _disp->_watches.push_back(this);
70}
71
78
80{
81 pthread_mutex_init(&_mutex, NULL);
82}
83
85{
86 if (recursive)
87 {
88 pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
89 _mutex = recmutex;
90 }
91 else
92 {
93 pthread_mutex_init(&_mutex, NULL);
94 }
95}
96
98{
99 pthread_mutex_destroy(&_mutex);
100}
101
103{
104 pthread_mutex_lock(&_mutex);
105}
106
108{
109 pthread_mutex_unlock(&_mutex);
110}
111
113 _mutex_w(true)
114{
115}
116
118{
119 _mutex_w.lock();
120
121 DefaultWatches::iterator wi = _watches.begin();
122 while (wi != _watches.end())
123 {
124 DefaultWatches::iterator wmp = wi;
125 ++wmp;
127 delete(*wi);
128 _mutex_w.lock();
129 wi = wmp;
130 }
132
133 _mutex_t.lock();
134
135 DefaultTimeouts::iterator ti = _timeouts.begin();
136 while (ti != _timeouts.end())
137 {
138 DefaultTimeouts::iterator tmp = ti;
139 ++tmp;
141 delete(*ti);
142 _mutex_t.lock();
143 ti = tmp;
144 }
146}
147
149{
150 _mutex_w.lock();
151
152 int nfd = _watches.size();
153
154 if (_fdunlock)
155 {
156 nfd = nfd + 2;
157 }
158
159 pollfd fds[nfd];
160
161 DefaultWatches::iterator wi = _watches.begin();
162
163 for (nfd = 0; wi != _watches.end(); ++wi)
164 {
165 if ((*wi)->enabled())
166 {
167 fds[nfd].fd = (*wi)->descriptor();
168 fds[nfd].events = (*wi)->flags();
169 fds[nfd].revents = 0;
170
171 ++nfd;
172 }
173 }
174
175 if (_fdunlock)
176 {
177 fds[nfd].fd = _fdunlock[0];
178 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
179 fds[nfd].revents = 0;
180
181 nfd++;
182 fds[nfd].fd = _fdunlock[1];
183 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
184 fds[nfd].revents = 0;
185 }
186
188
189 int wait_min = 10000;
190
191 DefaultTimeouts::iterator ti;
192
193 _mutex_t.lock();
194
195 for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti)
196 {
197 if ((*ti)->enabled() && (*ti)->interval() < wait_min)
198 wait_min = (*ti)->interval();
199 }
200
202
203 poll(fds, nfd, wait_min);
204
205 timeval now;
206 gettimeofday(&now, NULL);
207
208 double now_millis = millis(now);
209
210 _mutex_t.lock();
211
212 ti = _timeouts.begin();
213
214 while (ti != _timeouts.end())
215 {
216 DefaultTimeouts::iterator tmp = ti;
217 ++tmp;
218
219 if ((*ti)->enabled() && now_millis >= (*ti)->_expiration)
220 {
221 (*ti)->expired(*(*ti));
222
223 if ((*ti)->_repeat)
224 {
225 (*ti)->_expiration = now_millis + (*ti)->_interval;
226 }
227
228 }
229
230 ti = tmp;
231 }
232
234
235 _mutex_w.lock();
236
237 for (int j = 0; j < nfd; ++j)
238 {
239 DefaultWatches::iterator wi;
240
241 for (wi = _watches.begin(); wi != _watches.end();)
242 {
243 DefaultWatches::iterator tmp = wi;
244 ++tmp;
245
246 if ((*wi)->enabled() && (*wi)->_fd == fds[j].fd)
247 {
248 if (fds[j].revents)
249 {
250 (*wi)->_state = fds[j].revents;
251
252 (*wi)->ready(*(*wi));
253
254 fds[j].revents = 0;
255 }
256 }
257
258 wi = tmp;
259 }
260 }
262}
263
DefaultTimeouts _timeouts
Definition eventloop.h:214
virtual void dispatch()
DefaultMutex _mutex_t
Definition eventloop.h:213
DefaultMutex _mutex_w
Definition eventloop.h:216
DefaultWatches _watches
Definition eventloop.h:217
pthread_mutex_t _mutex
Definition eventloop.h:197
virtual ~DefaultTimeout()
Definition eventloop.cpp:57
DefaultMainLoop * _disp
Definition eventloop.h:103
DefaultTimeout(int interval, bool repeat, DefaultMainLoop *)
Definition eventloop.cpp:44
DefaultMainLoop * _disp
Definition eventloop.h:167
DefaultWatch(int fd, int flags, DefaultMainLoop *)
Definition eventloop.cpp:64
virtual ~DefaultWatch()
Definition eventloop.cpp:72
static double millis(timeval tv)
Definition eventloop.cpp:39