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
58{
60 _disp->_timeouts.remove(this);
62}
63
65 : _enabled(true), _fd(fd), _flags(flags), _state(0), _data(0), _disp(ed)
66{
68 _disp->_watches.push_back(this);
70}
71
73{
75 _disp->_watches.remove(this);
77}
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_t(true),
114 _mutex_w(true)
115{
116}
117
119{
120 _mutex_w.lock();
121
122 DefaultWatches::iterator wi = _watches.begin();
123 while (wi != _watches.end())
124 {
125 DefaultWatches::iterator wmp = wi;
126 ++wmp;
128 delete(*wi);
129 _mutex_w.lock();
130 wi = wmp;
131 }
133
134 _mutex_t.lock();
135
136 DefaultTimeouts::iterator ti = _timeouts.begin();
137 while (ti != _timeouts.end())
138 {
139 DefaultTimeouts::iterator tmp = ti;
140 ++tmp;
142 delete(*ti);
143 _mutex_t.lock();
144 ti = tmp;
145 }
147}
148
150{
151 _mutex_w.lock();
152
153 int nfd = _watches.size();
154
155 if (_fdunlock)
156 {
157 nfd = nfd + 2;
158 }
159
160 pollfd fds[nfd];
161
162 DefaultWatches::iterator wi = _watches.begin();
163
164 for (nfd = 0; wi != _watches.end(); ++wi)
165 {
166 if ((*wi)->enabled())
167 {
168 fds[nfd].fd = (*wi)->descriptor();
169 fds[nfd].events = (*wi)->flags();
170 fds[nfd].revents = 0;
171
172 ++nfd;
173 }
174 }
175
176 if (_fdunlock)
177 {
178 fds[nfd].fd = _fdunlock[0];
179 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
180 fds[nfd].revents = 0;
181
182 nfd++;
183 fds[nfd].fd = _fdunlock[1];
184 fds[nfd].events = POLLIN | POLLOUT | POLLPRI ;
185 fds[nfd].revents = 0;
186 }
187
189
190 int wait_min = 10000;
191
192 DefaultTimeouts::iterator ti;
193
194 _mutex_t.lock();
195
196 for (ti = _timeouts.begin(); ti != _timeouts.end(); ++ti)
197 {
198 if ((*ti)->enabled() && (*ti)->interval() < wait_min)
199 wait_min = (*ti)->interval();
200 }
201
203
204 poll(fds, nfd, wait_min);
205
206 timeval now;
207 gettimeofday(&now, NULL);
208
209 double now_millis = millis(now);
210
211 _mutex_t.lock();
212
213 ti = _timeouts.begin();
214
215 while (ti != _timeouts.end())
216 {
217 DefaultTimeouts::iterator tmp = ti;
218 ++tmp;
219
220 if ((*ti)->enabled() && now_millis >= (*ti)->_expiration)
221 {
222 (*ti)->expired(*(*ti));
223
224 if ((*ti)->_repeat)
225 {
226 (*ti)->_expiration = now_millis + (*ti)->_interval;
227 }
228
229 }
230
231 ti = tmp;
232 }
233
235
236 _mutex_w.lock();
237
238 for (int j = 0; j < nfd; ++j)
239 {
240 DefaultWatches::iterator wi;
241
242 for (wi = _watches.begin(); wi != _watches.end();)
243 {
244 DefaultWatches::iterator tmp = wi;
245 ++tmp;
246
247 if ((*wi)->enabled() && (*wi)->_fd == fds[j].fd)
248 {
249 if (fds[j].revents)
250 {
251 (*wi)->_state = fds[j].revents;
252
253 (*wi)->ready(*(*wi));
254
255 fds[j].revents = 0;
256 }
257 }
258
259 wi = tmp;
260 }
261 }
263}
264
DefaultTimeouts _timeouts
Definition: eventloop.h:214
virtual void dispatch()
Definition: eventloop.cpp:149
DefaultMutex _mutex_t
Definition: eventloop.h:213
DefaultMutex _mutex_w
Definition: eventloop.h:216
DefaultWatches _watches
Definition: eventloop.h:217
virtual ~DefaultMainLoop()
Definition: eventloop.cpp:118
pthread_mutex_t _mutex
Definition: eventloop.h:197
virtual ~DefaultTimeout()
Definition: eventloop.cpp:57
DefaultMainLoop * _disp
Definition: eventloop.h:103
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