dispatcher.cpp
Go to the documentation of this file.
00001 /* 00002 * 00003 * D-Bus++ - C++ bindings for D-Bus 00004 * 00005 * Copyright (C) 2005-2007 Paolo Durante <shackan@gmail.com> 00006 * 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 // check dbus version and use dbus_watch_get_unix_fd() only in dbus >= 1.1.1 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 //only push_back on list is mandatory! 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 // SEEME: dbus-glib is dispatching only one message at a time to not starve the loop/other things... 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 }