D-Bus  1.10.12
dbus-threads.c
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-threads.h  D-Bus threads handling
00003  *
00004  * Copyright (C) 2002, 2003, 2006 Red Hat Inc.
00005  *
00006  * Licensed under the Academic Free License version 2.1
00007  * 
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program 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
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 #include <config.h>
00024 #include "dbus-threads.h"
00025 #include "dbus-internals.h"
00026 #include "dbus-threads-internal.h"
00027 #include "dbus-list.h"
00028 
00029 static int thread_init_generation = 0;
00030 
00052 void
00053 _dbus_rmutex_new_at_location (DBusRMutex **location_p)
00054 {
00055   _dbus_assert (location_p != NULL);
00056 
00057   if (!dbus_threads_init_default ())
00058     {
00059       *location_p = NULL;
00060       return;
00061     }
00062 
00063   *location_p = _dbus_platform_rmutex_new ();
00064 }
00065 
00076 void
00077 _dbus_cmutex_new_at_location (DBusCMutex **location_p)
00078 {
00079   _dbus_assert (location_p != NULL);
00080 
00081   if (!dbus_threads_init_default ())
00082     {
00083       *location_p = NULL;
00084       return;
00085     }
00086 
00087   *location_p = _dbus_platform_cmutex_new ();
00088 }
00089 
00093 void
00094 _dbus_rmutex_free_at_location (DBusRMutex **location_p)
00095 {
00096   if (location_p == NULL)
00097     return;
00098 
00099   if (*location_p != NULL)
00100     _dbus_platform_rmutex_free (*location_p);
00101 }
00102 
00106 void
00107 _dbus_cmutex_free_at_location (DBusCMutex **location_p)
00108 {
00109   if (location_p == NULL)
00110     return;
00111 
00112   if (*location_p != NULL)
00113     _dbus_platform_cmutex_free (*location_p);
00114 }
00115 
00121 void
00122 _dbus_rmutex_lock (DBusRMutex *mutex)
00123 {
00124   if (mutex == NULL)
00125     return;
00126 
00127   _dbus_platform_rmutex_lock (mutex);
00128 }
00129 
00135 void
00136 _dbus_cmutex_lock (DBusCMutex *mutex)
00137 {
00138   if (mutex == NULL)
00139     return;
00140 
00141   _dbus_platform_cmutex_lock (mutex);
00142 }
00143 
00149 void
00150 _dbus_rmutex_unlock (DBusRMutex *mutex)
00151 {
00152   if (mutex == NULL)
00153     return;
00154 
00155   _dbus_platform_rmutex_unlock (mutex);
00156 }
00157 
00163 void
00164 _dbus_cmutex_unlock (DBusCMutex *mutex)
00165 {
00166   if (mutex == NULL)
00167     return;
00168 
00169   _dbus_platform_cmutex_unlock (mutex);
00170 }
00171 
00180 DBusCondVar *
00181 _dbus_condvar_new (void)
00182 {
00183   if (!dbus_threads_init_default ())
00184     return NULL;
00185 
00186   return _dbus_platform_condvar_new ();
00187 }
00188 
00189 
00198 void 
00199 _dbus_condvar_new_at_location (DBusCondVar **location_p)
00200 {
00201   _dbus_assert (location_p != NULL);
00202 
00203   *location_p = _dbus_condvar_new();
00204 }
00205 
00206 
00211 void
00212 _dbus_condvar_free (DBusCondVar *cond)
00213 {
00214   if (cond == NULL)
00215     return;
00216 
00217   _dbus_platform_condvar_free (cond);
00218 }
00219 
00223 void
00224 _dbus_condvar_free_at_location (DBusCondVar **location_p)
00225 {
00226   if (location_p == NULL)
00227     return;
00228 
00229   if (*location_p != NULL)
00230     _dbus_platform_condvar_free (*location_p);
00231 }
00232 
00239 void
00240 _dbus_condvar_wait (DBusCondVar *cond,
00241                     DBusCMutex  *mutex)
00242 {
00243   if (cond == NULL || mutex == NULL)
00244     return;
00245 
00246   _dbus_platform_condvar_wait (cond, mutex);
00247 }
00248 
00260 dbus_bool_t
00261 _dbus_condvar_wait_timeout (DBusCondVar               *cond,
00262                             DBusCMutex                *mutex,
00263                             int                        timeout_milliseconds)
00264 {
00265   if (cond == NULL || mutex == NULL)
00266     return TRUE;
00267 
00268   return _dbus_platform_condvar_wait_timeout (cond, mutex,
00269       timeout_milliseconds);
00270 }
00271 
00277 void
00278 _dbus_condvar_wake_one (DBusCondVar *cond)
00279 {
00280   if (cond == NULL)
00281     return;
00282 
00283   _dbus_platform_condvar_wake_one (cond);
00284 }
00285 
00286 static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL };
00287 
00288 static void
00289 shutdown_global_locks (void *nil)
00290 {
00291   int i;
00292 
00293   for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
00294     {
00295       _dbus_assert (global_locks[i] != NULL);
00296       _dbus_platform_rmutex_free (global_locks[i]);
00297       global_locks[i] = NULL;
00298     }
00299 }
00300 
00301 static dbus_bool_t
00302 init_global_locks (void)
00303 {
00304   int i;
00305   dbus_bool_t ok;
00306 
00307   for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++)
00308     {
00309       _dbus_assert (global_locks[i] == NULL);
00310 
00311       global_locks[i] = _dbus_platform_rmutex_new ();
00312 
00313       if (global_locks[i] == NULL)
00314         goto failed;
00315     }
00316 
00317   _dbus_platform_rmutex_lock (global_locks[_DBUS_LOCK_shutdown_funcs]);
00318   ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL);
00319   _dbus_platform_rmutex_unlock (global_locks[_DBUS_LOCK_shutdown_funcs]);
00320 
00321   if (!ok)
00322     goto failed;
00323 
00324   return TRUE;
00325 
00326  failed:
00327   for (i = i - 1; i >= 0; i--)
00328     {
00329       _dbus_platform_rmutex_free (global_locks[i]);
00330       global_locks[i] = NULL;
00331     }
00332 
00333   return FALSE;
00334 }
00335 
00336 dbus_bool_t
00337 _dbus_lock (DBusGlobalLock lock)
00338 {
00339   _dbus_assert (lock >= 0);
00340   _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
00341 
00342   if (thread_init_generation != _dbus_current_generation &&
00343       !dbus_threads_init_default ())
00344     return FALSE;
00345 
00346   _dbus_platform_rmutex_lock (global_locks[lock]);
00347   return TRUE;
00348 }
00349 
00350 void
00351 _dbus_unlock (DBusGlobalLock lock)
00352 {
00353   _dbus_assert (lock >= 0);
00354   _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS);
00355 
00356   _dbus_platform_rmutex_unlock (global_locks[lock]);
00357 }
00358  /* end of internals */
00360 
00390 dbus_bool_t
00391 dbus_threads_init (const DBusThreadFunctions *functions)
00392 {
00393   _dbus_threads_lock_platform_specific ();
00394 
00395   if (thread_init_generation == _dbus_current_generation)
00396     {
00397       _dbus_threads_unlock_platform_specific ();
00398       return TRUE;
00399     }
00400 
00401   if (!_dbus_threads_init_platform_specific() ||
00402       !init_global_locks ())
00403     {
00404       _dbus_threads_unlock_platform_specific ();
00405       return FALSE;
00406     }
00407 
00408   thread_init_generation = _dbus_current_generation;
00409 
00410   _dbus_threads_unlock_platform_specific ();
00411   return TRUE;
00412 }
00413 
00414 
00415 
00416 /* Default thread implemenation */
00417 
00437 dbus_bool_t
00438 dbus_threads_init_default (void)
00439 {
00440   return dbus_threads_init (NULL);
00441 }
00442 
00443 
00446 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
00447 
00448 dbus_bool_t
00449 _dbus_threads_init_debug (void)
00450 {
00451   return dbus_threads_init (NULL);
00452 }
00453 
00454 #endif /* DBUS_ENABLE_EMBEDDED_TESTS */