dispatcher.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++/dispatcher.h>
29 
30 #include <dbus/dbus.h>
31 
32 #include "dispatcher_p.h"
33 #include "server_p.h"
34 #include "connection_p.h"
35 
37 
38 using namespace DBus;
39 
40 Timeout::Timeout(Timeout::Internal *i)
41  : _int(i)
42 {
43  dbus_timeout_set_data((DBusTimeout *)i, this, NULL);
44 }
45 
46 int Timeout::interval() const
47 {
48  return dbus_timeout_get_interval((DBusTimeout *)_int);
49 }
50 
51 bool Timeout::enabled() const
52 {
53  return dbus_timeout_get_enabled((DBusTimeout *)_int);
54 }
55 
57 {
58  return dbus_timeout_handle((DBusTimeout *)_int);
59 }
60 
61 /*
62 */
63 
64 Watch::Watch(Watch::Internal *i)
65  : _int(i)
66 {
67  dbus_watch_set_data((DBusWatch *)i, this, NULL);
68 }
69 
70 int Watch::descriptor() const
71 {
72 #if HAVE_WIN32
73  return dbus_watch_get_socket((DBusWatch *)_int);
74 #else
75  // check dbus version and use dbus_watch_get_unix_fd() only in dbus >= 1.1.1
76 #if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || \
77  (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || \
78  (DBUS_VERSION_MAJOR > 1)
79  return dbus_watch_get_unix_fd((DBusWatch *)_int);
80 #else
81  return dbus_watch_get_fd((DBusWatch *)_int);
82 #endif
83 #endif
84 }
85 
86 int Watch::flags() const
87 {
88  return dbus_watch_get_flags((DBusWatch *)_int);
89 }
90 
91 bool Watch::enabled() const
92 {
93  return dbus_watch_get_enabled((DBusWatch *)_int);
94 }
95 
96 bool Watch::handle(int flags)
97 {
98  return dbus_watch_handle((DBusWatch *)_int, flags);
99 }
100 
101 /*
102 */
103 
104 dbus_bool_t Dispatcher::Private::on_add_watch(DBusWatch *watch, void *data)
105 {
106  Dispatcher *d = static_cast<Dispatcher *>(data);
107 
108  Watch::Internal *w = reinterpret_cast<Watch::Internal *>(watch);
109 
110  d->add_watch(w);
111 
112  return true;
113 }
114 
115 void Dispatcher::Private::on_rem_watch(DBusWatch *watch, void *data)
116 {
117  Dispatcher *d = static_cast<Dispatcher *>(data);
118 
119  Watch *w = static_cast<Watch *>(dbus_watch_get_data(watch));
120 
121  d->rem_watch(w);
122 }
123 
124 void Dispatcher::Private::on_toggle_watch(DBusWatch *watch, void *data)
125 {
126  Watch *w = static_cast<Watch *>(dbus_watch_get_data(watch));
127 
128  w->toggle();
129 }
130 
131 dbus_bool_t Dispatcher::Private::on_add_timeout(DBusTimeout *timeout, void *data)
132 {
133  Dispatcher *d = static_cast<Dispatcher *>(data);
134 
135  Timeout::Internal *t = reinterpret_cast<Timeout::Internal *>(timeout);
136 
137  d->add_timeout(t);
138 
139  return true;
140 }
141 
142 void Dispatcher::Private::on_rem_timeout(DBusTimeout *timeout, void *data)
143 {
144  Dispatcher *d = static_cast<Dispatcher *>(data);
145 
146  Timeout *t = static_cast<Timeout *>(dbus_timeout_get_data(timeout));
147 
148  d->rem_timeout(t);
149 }
150 
151 void Dispatcher::Private::on_toggle_timeout(DBusTimeout *timeout, void *data)
152 {
153  Timeout *t = static_cast<Timeout *>(dbus_timeout_get_data(timeout));
154 
155  t->toggle();
156 }
157 
159 {
160  _mutex_p.lock();
161  _pending_queue.push_back(cp);
162  _mutex_p.unlock();
163 }
164 
165 
167 {
168  _mutex_p.lock();
169  bool has_something = false;
170  for (Connection::PrivatePList::iterator it = _pending_queue.begin();
171  it != _pending_queue.end() && !has_something;
172  ++it)
173  {
174  has_something = (*it)->has_something_to_dispatch();
175  }
176 
177  _mutex_p.unlock();
178  return has_something;
179 }
180 
181 
183 {
184  while (1)
185  {
186  _mutex_p.lock();
187  if (_pending_queue.empty())
188  {
189  _mutex_p.unlock();
190  break;
191  }
192 
193  Connection::PrivatePList pending_queue_copy(_pending_queue);
194  _mutex_p.unlock();
195 
196  size_t copy_elem_num(pending_queue_copy.size());
197 
198  dispatch_pending(pending_queue_copy);
199 
200  //only push_back on list is mandatory!
201  _mutex_p.lock();
202 
203  Connection::PrivatePList::iterator i, j;
204  i = _pending_queue.begin();
205  size_t counter = 0;
206  while (counter < copy_elem_num && i != _pending_queue.end())
207  {
208  j = i;
209  ++j;
210  _pending_queue.erase(i);
211  i = j;
212  ++counter;
213  }
214 
215  _mutex_p.unlock();
216  }
217 }
218 
220 {
221  // SEEME: dbus-glib is dispatching only one message at a time to not starve the loop/other things...
222 
224  while (pending_queue.size() > 0)
225  {
226  Connection::PrivatePList::iterator i, j;
227 
228  i = pending_queue.begin();
229 
230  while (i != pending_queue.end())
231  {
232  j = i;
233 
234  ++j;
235 
236  if ((*i)->do_dispatch())
237  pending_queue.erase(i);
238  else
239  debug_log("dispatch_pending_private: do_dispatch error");
240 
241  i = j;
242  }
243  }
245 }
246 
248 {
249 #ifdef DBUS_HAS_THREADS_INIT_DEFAULT
250  dbus_threads_init_default();
251 #else
252  debug_log("Thread support is not enabled! Your D-Bus version is too old!");
253 #endif//DBUS_HAS_THREADS_INIT_DEFAULT
254 }
255 
257  MutexNewFn m1,
258  MutexFreeFn m2,
259  MutexLockFn m3,
260  MutexUnlockFn m4,
261  CondVarNewFn c1,
262  CondVarFreeFn c2,
263  CondVarWaitFn c3,
265  CondVarWakeOneFn c5,
267 )
268 {
269 #ifndef DBUS_HAS_RECURSIVE_MUTEX
270  DBusThreadFunctions functions =
271  {
272  DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
273  DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
274  DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
275  DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
276  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
277  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
278  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
279  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
280  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK |
281  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
282  (DBusMutexNewFunction) m1,
283  (DBusMutexFreeFunction) m2,
284  (DBusMutexLockFunction) m3,
285  (DBusMutexUnlockFunction) m4,
286  (DBusCondVarNewFunction) c1,
287  (DBusCondVarFreeFunction) c2,
288  (DBusCondVarWaitFunction) c3,
289  (DBusCondVarWaitTimeoutFunction) c4,
290  (DBusCondVarWakeOneFunction) c5,
291  (DBusCondVarWakeAllFunction) c6
292  };
293 #else
294  DBusThreadFunctions functions =
295  {
296  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK |
297  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK |
298  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK |
299  DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK |
300  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
301  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
302  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
303  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
304  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK |
305  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
306  0, 0, 0, 0,
307  (DBusCondVarNewFunction) c1,
308  (DBusCondVarFreeFunction) c2,
309  (DBusCondVarWaitFunction) c3,
310  (DBusCondVarWaitTimeoutFunction) c4,
311  (DBusCondVarWakeOneFunction) c5,
312  (DBusCondVarWakeAllFunction) c6,
313  (DBusRecursiveMutexNewFunction) m1,
314  (DBusRecursiveMutexFreeFunction) m2,
315  (DBusRecursiveMutexLockFunction) m3,
316  (DBusRecursiveMutexUnlockFunction) m4
317  };
318 #endif//DBUS_HAS_RECURSIVE_MUTEX
319  dbus_threads_init(&functions);
320 }
bool enabled() const
Definition: dispatcher.cpp:51
void(* CondVarWaitFn)(CondVar *cv, Mutex *mx)
Definition: dispatcher.h:242
std::list< Private * > PrivatePList
Definition: connection.h:58
void(* CondVarWakeOneFn)(CondVar *cv)
Definition: dispatcher.h:244
Connection::PrivatePList _pending_queue
Definition: dispatcher.h:183
void(* CondVarWakeAllFn)(CondVar *cv)
Definition: dispatcher.h:245
DefaultMutex _mutex_p
Definition: dispatcher.h:180
void(* CondVarFreeFn)(CondVar *cv)
Definition: dispatcher.h:241
void dispatch_pending()
Definition: dispatcher.cpp:182
bool enabled() const
Definition: dispatcher.cpp:91
bool(* MutexFreeFn)(Mutex *mx)
Definition: dispatcher.h:233
void queue_connection(Connection::Private *)
Definition: dispatcher.cpp:158
Internal * _int
Definition: dispatcher.h:83
virtual void rem_timeout(Timeout *)=0
Internal * _int
Definition: dispatcher.h:148
Mutex *(* MutexNewFn)()
Definition: dispatcher.h:229
bool handle(int flags)
Called to notify the D-Bus library when a previously-added watch is ready for reading or writing,...
Definition: dispatcher.cpp:96
int flags() const
Gets flags from DBusWatchFlags indicating what conditions should be monitored on the file descriptor.
Definition: dispatcher.cpp:86
void(* MutexUnlockFn)(Mutex *mx)
Definition: dispatcher.h:230
virtual void toggle()=0
DefaultMutex _mutex_p_copy
Definition: dispatcher.h:181
Watch(Internal *i)
virtual void toggle()=0
CondVar *(* CondVarNewFn)()
Definition: dispatcher.h:240
DXXAPI LogFunction debug_log
Definition: debug.cpp:55
Timeout(Internal *i)
DXXAPI Dispatcher * default_dispatcher
Definition: dispatcher.cpp:36
bool has_something_to_dispatch()
Definition: dispatcher.cpp:166
bool handle()
Calls the timeout handler for this timeout.
Definition: dispatcher.cpp:56
virtual Timeout * add_timeout(Timeout::Internal *)=0
Private(DBusConnection *, Server::Private *=NULL)
bool(* MutexLockFn)(Mutex *mx)
Definition: dispatcher.h:234
int descriptor() const
A main loop could poll this descriptor to integrate dbus-c++.
Definition: dispatcher.cpp:70
void DXXAPI _init_threading()
Definition: dispatcher.cpp:247
virtual void rem_watch(Watch *)=0
virtual Watch * add_watch(Watch::Internal *)=0
bool(* CondVarWaitTimeoutFn)(CondVar *cv, Mutex *mx, int timeout)
Definition: dispatcher.h:243