00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <dbus-c++/dispatcher.h>
00029
00030 #include <dbus/dbus.h>
00031
00032 #include "dispatcher_p.h"
00033 #include "server_p.h"
00034 #include "connection_p.h"
00035
00036 DBus::Dispatcher *DBus::default_dispatcher = NULL;
00037
00038 using namespace DBus;
00039
00040 Timeout::Timeout(Timeout::Internal *i)
00041 : _int(i)
00042 {
00043 dbus_timeout_set_data((DBusTimeout *)i, this, NULL);
00044 }
00045
00046 int Timeout::interval() const
00047 {
00048 return dbus_timeout_get_interval((DBusTimeout *)_int);
00049 }
00050
00051 bool Timeout::enabled() const
00052 {
00053 return dbus_timeout_get_enabled((DBusTimeout *)_int);
00054 }
00055
00056 bool Timeout::handle()
00057 {
00058 return dbus_timeout_handle((DBusTimeout *)_int);
00059 }
00060
00061
00062
00063
00064 Watch::Watch(Watch::Internal *i)
00065 : _int(i)
00066 {
00067 dbus_watch_set_data((DBusWatch *)i, this, NULL);
00068 }
00069
00070 int Watch::descriptor() const
00071 {
00072 #if HAVE_WIN32
00073 return dbus_watch_get_socket((DBusWatch *)_int);
00074 #else
00075
00076 #if (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MINOR == 1 && DBUS_VERSION_MICRO >= 1) || \
00077 (DBUS_VERSION_MAJOR == 1 && DBUS_VERSION_MAJOR > 1) || \
00078 (DBUS_VERSION_MAJOR > 1)
00079 return dbus_watch_get_unix_fd((DBusWatch *)_int);
00080 #else
00081 return dbus_watch_get_fd((DBusWatch *)_int);
00082 #endif
00083 #endif
00084 }
00085
00086 int Watch::flags() const
00087 {
00088 return dbus_watch_get_flags((DBusWatch *)_int);
00089 }
00090
00091 bool Watch::enabled() const
00092 {
00093 return dbus_watch_get_enabled((DBusWatch *)_int);
00094 }
00095
00096 bool Watch::handle(int flags)
00097 {
00098 return dbus_watch_handle((DBusWatch *)_int, flags);
00099 }
00100
00101
00102
00103
00104 dbus_bool_t Dispatcher::Private::on_add_watch(DBusWatch *watch, void *data)
00105 {
00106 Dispatcher *d = static_cast<Dispatcher *>(data);
00107
00108 Watch::Internal *w = reinterpret_cast<Watch::Internal *>(watch);
00109
00110 d->add_watch(w);
00111
00112 return true;
00113 }
00114
00115 void Dispatcher::Private::on_rem_watch(DBusWatch *watch, void *data)
00116 {
00117 Dispatcher *d = static_cast<Dispatcher *>(data);
00118
00119 Watch *w = static_cast<Watch *>(dbus_watch_get_data(watch));
00120
00121 d->rem_watch(w);
00122 }
00123
00124 void Dispatcher::Private::on_toggle_watch(DBusWatch *watch, void *data)
00125 {
00126 Watch *w = static_cast<Watch *>(dbus_watch_get_data(watch));
00127
00128 w->toggle();
00129 }
00130
00131 dbus_bool_t Dispatcher::Private::on_add_timeout(DBusTimeout *timeout, void *data)
00132 {
00133 Dispatcher *d = static_cast<Dispatcher *>(data);
00134
00135 Timeout::Internal *t = reinterpret_cast<Timeout::Internal *>(timeout);
00136
00137 d->add_timeout(t);
00138
00139 return true;
00140 }
00141
00142 void Dispatcher::Private::on_rem_timeout(DBusTimeout *timeout, void *data)
00143 {
00144 Dispatcher *d = static_cast<Dispatcher *>(data);
00145
00146 Timeout *t = static_cast<Timeout *>(dbus_timeout_get_data(timeout));
00147
00148 d->rem_timeout(t);
00149 }
00150
00151 void Dispatcher::Private::on_toggle_timeout(DBusTimeout *timeout, void *data)
00152 {
00153 Timeout *t = static_cast<Timeout *>(dbus_timeout_get_data(timeout));
00154
00155 t->toggle();
00156 }
00157
00158 void Dispatcher::queue_connection(Connection::Private *cp)
00159 {
00160 _mutex_p.lock();
00161 _pending_queue.push_back(cp);
00162 _mutex_p.unlock();
00163 }
00164
00165
00166 bool Dispatcher::has_something_to_dispatch()
00167 {
00168 _mutex_p.lock();
00169 bool has_something = false;
00170 for (Connection::PrivatePList::iterator it = _pending_queue.begin();
00171 it != _pending_queue.end() && !has_something;
00172 ++it)
00173 {
00174 has_something = (*it)->has_something_to_dispatch();
00175 }
00176
00177 _mutex_p.unlock();
00178 return has_something;
00179 }
00180
00181
00182 void Dispatcher::dispatch_pending()
00183 {
00184 while (1)
00185 {
00186 _mutex_p.lock();
00187 if (_pending_queue.empty())
00188 {
00189 _mutex_p.unlock();
00190 break;
00191 }
00192
00193 Connection::PrivatePList pending_queue_copy(_pending_queue);
00194 _mutex_p.unlock();
00195
00196 size_t copy_elem_num(pending_queue_copy.size());
00197
00198 dispatch_pending(pending_queue_copy);
00199
00200
00201 _mutex_p.lock();
00202
00203 Connection::PrivatePList::iterator i, j;
00204 i = _pending_queue.begin();
00205 size_t counter = 0;
00206 while (counter < copy_elem_num && i != _pending_queue.end())
00207 {
00208 j = i;
00209 ++j;
00210 _pending_queue.erase(i);
00211 i = j;
00212 ++counter;
00213 }
00214
00215 _mutex_p.unlock();
00216 }
00217 }
00218
00219 void Dispatcher::dispatch_pending(Connection::PrivatePList &pending_queue)
00220 {
00221
00222
00223 _mutex_p_copy.lock();
00224 while (pending_queue.size() > 0)
00225 {
00226 Connection::PrivatePList::iterator i, j;
00227
00228 i = pending_queue.begin();
00229
00230 while (i != pending_queue.end())
00231 {
00232 j = i;
00233
00234 ++j;
00235
00236 if ((*i)->do_dispatch())
00237 pending_queue.erase(i);
00238 else
00239 debug_log("dispatch_pending_private: do_dispatch error");
00240
00241 i = j;
00242 }
00243 }
00244 _mutex_p_copy.unlock();
00245 }
00246
00247 void DBus::_init_threading()
00248 {
00249 #ifdef DBUS_HAS_THREADS_INIT_DEFAULT
00250 dbus_threads_init_default();
00251 #else
00252 debug_log("Thread support is not enabled! Your D-Bus version is too old!");
00253 #endif//DBUS_HAS_THREADS_INIT_DEFAULT
00254 }
00255
00256 void DBus::_init_threading(
00257 MutexNewFn m1,
00258 MutexFreeFn m2,
00259 MutexLockFn m3,
00260 MutexUnlockFn m4,
00261 CondVarNewFn c1,
00262 CondVarFreeFn c2,
00263 CondVarWaitFn c3,
00264 CondVarWaitTimeoutFn c4,
00265 CondVarWakeOneFn c5,
00266 CondVarWakeAllFn c6
00267 )
00268 {
00269 #ifndef DBUS_HAS_RECURSIVE_MUTEX
00270 DBusThreadFunctions functions =
00271 {
00272 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00273 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00274 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00275 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00276 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00277 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00278 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00279 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00280 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK |
00281 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00282 (DBusMutexNewFunction) m1,
00283 (DBusMutexFreeFunction) m2,
00284 (DBusMutexLockFunction) m3,
00285 (DBusMutexUnlockFunction) m4,
00286 (DBusCondVarNewFunction) c1,
00287 (DBusCondVarFreeFunction) c2,
00288 (DBusCondVarWaitFunction) c3,
00289 (DBusCondVarWaitTimeoutFunction) c4,
00290 (DBusCondVarWakeOneFunction) c5,
00291 (DBusCondVarWakeAllFunction) c6
00292 };
00293 #else
00294 DBusThreadFunctions functions =
00295 {
00296 DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_NEW_MASK |
00297 DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_FREE_MASK |
00298 DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_LOCK_MASK |
00299 DBUS_THREAD_FUNCTIONS_RECURSIVE_MUTEX_UNLOCK_MASK |
00300 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00301 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00302 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00303 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00304 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK |
00305 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00306 0, 0, 0, 0,
00307 (DBusCondVarNewFunction) c1,
00308 (DBusCondVarFreeFunction) c2,
00309 (DBusCondVarWaitFunction) c3,
00310 (DBusCondVarWaitTimeoutFunction) c4,
00311 (DBusCondVarWakeOneFunction) c5,
00312 (DBusCondVarWakeAllFunction) c6,
00313 (DBusRecursiveMutexNewFunction) m1,
00314 (DBusRecursiveMutexFreeFunction) m2,
00315 (DBusRecursiveMutexLockFunction) m3,
00316 (DBusRecursiveMutexUnlockFunction) m4
00317 };
00318 #endif//DBUS_HAS_RECURSIVE_MUTEX
00319 dbus_threads_init(&functions);
00320 }