• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

dbus-sysdeps-thread-win.c

00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 /* dbus-sysdeps-pthread.c Implements threads using Windows threads (internal to libdbus)
00003  * 
00004  * Copyright (C) 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 
00024 #include <config.h>
00025 #include "dbus-internals.h"
00026 #include "dbus-sysdeps.h"
00027 #include "dbus-sysdeps-win.h"
00028 #include "dbus-threads.h"
00029 #include "dbus-list.h"
00030 
00031 #include <windows.h>
00032 
00033 struct DBusCondVar {
00034   DBusList *list;        
00035   CRITICAL_SECTION lock; 
00036 };
00037 
00038 static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
00039 
00040 
00041 static HMODULE dbus_dll_hmodule;
00042 
00043 void *
00044 _dbus_win_get_dll_hmodule (void)
00045 {
00046   return dbus_dll_hmodule;
00047 }
00048 
00049 #ifdef DBUS_WINCE
00050 #define hinst_t HANDLE
00051 #else
00052 #define hinst_t HINSTANCE
00053 #endif
00054 
00055 BOOL WINAPI DllMain (hinst_t, DWORD, LPVOID);
00056 
00057 /* We need this to free the TLS events on thread exit */
00058 BOOL WINAPI
00059 DllMain (hinst_t hinstDLL,
00060          DWORD     fdwReason,
00061          LPVOID    lpvReserved)
00062 {
00063   HANDLE event;
00064   switch (fdwReason) 
00065     { 
00066     case DLL_PROCESS_ATTACH:
00067       dbus_dll_hmodule = hinstDLL;
00068       break;
00069     case DLL_THREAD_DETACH:
00070       if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00071         {
00072           event = TlsGetValue(dbus_cond_event_tls);
00073           CloseHandle (event);
00074           TlsSetValue(dbus_cond_event_tls, NULL);
00075         }
00076       break;
00077     case DLL_PROCESS_DETACH: 
00078       if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00079         {
00080           event = TlsGetValue(dbus_cond_event_tls);
00081           CloseHandle (event);
00082           TlsSetValue(dbus_cond_event_tls, NULL);
00083 
00084           TlsFree(dbus_cond_event_tls); 
00085         }
00086       break;
00087     default: 
00088       break; 
00089     }
00090   return TRUE;
00091 }
00092 
00093 static DBusMutex*
00094 _dbus_windows_mutex_new (void)
00095 {
00096   HANDLE handle;
00097   handle = CreateMutex (NULL, FALSE, NULL);
00098   return (DBusMutex *) handle;
00099 }
00100 
00101 static void
00102 _dbus_windows_mutex_free (DBusMutex *mutex)
00103 {
00104   CloseHandle ((HANDLE *) mutex);
00105 }
00106 
00107 static dbus_bool_t
00108 _dbus_windows_mutex_lock (DBusMutex *mutex)
00109 {
00110   return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
00111 }
00112 
00113 static dbus_bool_t
00114 _dbus_windows_mutex_unlock (DBusMutex *mutex)
00115 {
00116   return ReleaseMutex ((HANDLE *) mutex) != 0;
00117 }
00118 
00119 static DBusCondVar *
00120 _dbus_windows_condvar_new (void)
00121 {
00122   DBusCondVar *cond;
00123     
00124   cond = dbus_new (DBusCondVar, 1);
00125   if (cond == NULL)
00126     return NULL;
00127   
00128   cond->list = NULL;
00129   
00130   InitializeCriticalSection (&cond->lock);
00131   return (DBusCondVar *) cond;
00132 }
00133 
00134 static void
00135 _dbus_windows_condvar_free (DBusCondVar *cond)
00136 {
00137   DeleteCriticalSection (&cond->lock);
00138   _dbus_list_clear (&cond->list);
00139   dbus_free (cond);
00140 }
00141 
00142 static dbus_bool_t
00143 _dbus_condvar_wait_win32 (DBusCondVar *cond,
00144                           DBusMutex *mutex,
00145                           int milliseconds)
00146 {
00147   DWORD retval;
00148   dbus_bool_t ret;
00149   HANDLE event = TlsGetValue (dbus_cond_event_tls);
00150 
00151   if (!event)
00152     {
00153       event = CreateEvent (0, FALSE, FALSE, NULL);
00154       if (event == 0)
00155         return FALSE;
00156       TlsSetValue (dbus_cond_event_tls, event);
00157     }
00158 
00159   EnterCriticalSection (&cond->lock);
00160 
00161   /* The event must not be signaled. Check this */
00162   _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
00163 
00164   ret = _dbus_list_append (&cond->list, event);
00165   
00166   LeaveCriticalSection (&cond->lock);
00167   
00168   if (!ret)
00169     return FALSE; /* Prepend failed */
00170 
00171   _dbus_mutex_unlock (mutex);
00172   retval = WaitForSingleObject (event, milliseconds);
00173   _dbus_mutex_lock (mutex);
00174   
00175   if (retval == WAIT_TIMEOUT)
00176     {
00177       EnterCriticalSection (&cond->lock);
00178       _dbus_list_remove (&cond->list, event);
00179 
00180       /* In the meantime we could have been signaled, so we must again
00181        * wait for the signal, this time with no timeout, to reset
00182        * it. retval is set again to honour the late arrival of the
00183        * signal */
00184       retval = WaitForSingleObject (event, 0);
00185 
00186       LeaveCriticalSection (&cond->lock);
00187     }
00188 
00189 #ifndef DBUS_DISABLE_ASSERT
00190   EnterCriticalSection (&cond->lock);
00191 
00192   /* Now event must not be inside the array, check this */
00193   _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);
00194 
00195   LeaveCriticalSection (&cond->lock);
00196 #endif /* !G_DISABLE_ASSERT */
00197 
00198   return retval != WAIT_TIMEOUT;
00199 }
00200 
00201 static void
00202 _dbus_windows_condvar_wait (DBusCondVar *cond,
00203                             DBusMutex   *mutex)
00204 {
00205   _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
00206 }
00207 
00208 static dbus_bool_t
00209 _dbus_windows_condvar_wait_timeout (DBusCondVar               *cond,
00210                                      DBusMutex                 *mutex,
00211                                      int                        timeout_milliseconds)
00212 {
00213   return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
00214 }
00215 
00216 static void
00217 _dbus_windows_condvar_wake_one (DBusCondVar *cond)
00218 {
00219   EnterCriticalSection (&cond->lock);
00220   
00221   if (cond->list != NULL)
00222     SetEvent (_dbus_list_pop_first (&cond->list));
00223     
00224   LeaveCriticalSection (&cond->lock);
00225 }
00226 
00227 static void
00228 _dbus_windows_condvar_wake_all (DBusCondVar *cond)
00229 {
00230   EnterCriticalSection (&cond->lock);
00231 
00232   while (cond->list != NULL)
00233     SetEvent (_dbus_list_pop_first (&cond->list));
00234   
00235   LeaveCriticalSection (&cond->lock);
00236 }
00237 
00238 static const DBusThreadFunctions windows_functions =
00239 {
00240   DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00241   DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00242   DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00243   DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00244   DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00245   DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00246   DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00247   DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00248   DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00249   DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00250   _dbus_windows_mutex_new,
00251   _dbus_windows_mutex_free,
00252   _dbus_windows_mutex_lock,
00253   _dbus_windows_mutex_unlock,
00254   _dbus_windows_condvar_new,
00255   _dbus_windows_condvar_free,
00256   _dbus_windows_condvar_wait,
00257   _dbus_windows_condvar_wait_timeout,
00258   _dbus_windows_condvar_wake_one,
00259   _dbus_windows_condvar_wake_all
00260 };
00261 
00262 dbus_bool_t
00263 _dbus_threads_init_platform_specific (void)
00264 {
00265   /* We reuse this over several generations, because we can't
00266    * free the events once they are in use
00267    */
00268   if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00269     {
00270       dbus_cond_event_tls = TlsAlloc ();
00271       if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00272         return FALSE;
00273     }
00274 
00275   return dbus_threads_init (&windows_functions);
00276 }
00277 

Generated on Fri Jul 22 2011 16:59:34 for D-Bus by  doxygen 1.7.1