00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "dbus-internals.h"
00025 #include "dbus-sysdeps.h"
00026 #include "dbus-threads.h"
00027 #include "dbus-list.h"
00028
00029 #include <windows.h>
00030
00031 struct DBusCondVar {
00032 DBusList *list;
00033 CRITICAL_SECTION lock;
00034 };
00035
00036 static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
00037
00038
00039 BOOL WINAPI DllMain (HINSTANCE hinstDLL,
00040 DWORD fdwReason,
00041 LPVOID lpvReserved);
00042
00043
00044 BOOL WINAPI
00045 DllMain (HINSTANCE hinstDLL,
00046 DWORD fdwReason,
00047 LPVOID lpvReserved)
00048 {
00049 HANDLE event;
00050 switch (fdwReason)
00051 {
00052 case DLL_THREAD_DETACH:
00053 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00054 {
00055 event = TlsGetValue(dbus_cond_event_tls);
00056 CloseHandle (event);
00057 TlsSetValue(dbus_cond_event_tls, NULL);
00058 }
00059 break;
00060 case DLL_PROCESS_DETACH:
00061 if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
00062 {
00063 event = TlsGetValue(dbus_cond_event_tls);
00064 CloseHandle (event);
00065 TlsSetValue(dbus_cond_event_tls, NULL);
00066
00067 TlsFree(dbus_cond_event_tls);
00068 }
00069 break;
00070 default:
00071 break;
00072 }
00073 return TRUE;
00074 }
00075
00076 static DBusMutex*
00077 _dbus_windows_mutex_new (void)
00078 {
00079 HANDLE handle;
00080 handle = CreateMutex (NULL, FALSE, NULL);
00081 return (DBusMutex *) handle;
00082 }
00083
00084 static void
00085 _dbus_windows_mutex_free (DBusMutex *mutex)
00086 {
00087 CloseHandle ((HANDLE *) mutex);
00088 }
00089
00090 static dbus_bool_t
00091 _dbus_windows_mutex_lock (DBusMutex *mutex)
00092 {
00093 return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
00094 }
00095
00096 static dbus_bool_t
00097 _dbus_windows_mutex_unlock (DBusMutex *mutex)
00098 {
00099 return ReleaseMutex ((HANDLE *) mutex) != 0;
00100 }
00101
00102 static DBusCondVar *
00103 _dbus_windows_condvar_new (void)
00104 {
00105 DBusCondVar *cond;
00106
00107 cond = dbus_new (DBusCondVar, 1);
00108 if (cond == NULL)
00109 return NULL;
00110
00111 cond->list = NULL;
00112
00113 InitializeCriticalSection (&cond->lock);
00114 return (DBusCondVar *) cond;
00115 }
00116
00117 static void
00118 _dbus_windows_condvar_free (DBusCondVar *cond)
00119 {
00120 DeleteCriticalSection (&cond->lock);
00121 _dbus_list_clear (&cond->list);
00122 dbus_free (cond);
00123 }
00124
00125 static dbus_bool_t
00126 _dbus_condvar_wait_win32 (DBusCondVar *cond,
00127 DBusMutex *mutex,
00128 int milliseconds)
00129 {
00130 DWORD retval;
00131 dbus_bool_t ret;
00132 HANDLE event = TlsGetValue (dbus_cond_event_tls);
00133
00134 if (!event)
00135 {
00136 event = CreateEvent (0, FALSE, FALSE, NULL);
00137 if (event == 0)
00138 return FALSE;
00139 TlsSetValue (dbus_cond_event_tls, event);
00140 }
00141
00142 EnterCriticalSection (&cond->lock);
00143
00144
00145 _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
00146
00147 ret = _dbus_list_append (&cond->list, event);
00148
00149 LeaveCriticalSection (&cond->lock);
00150
00151 if (!ret)
00152 return FALSE;
00153
00154 _dbus_mutex_unlock (mutex);
00155 retval = WaitForSingleObject (event, milliseconds);
00156 _dbus_mutex_lock (mutex);
00157
00158 if (retval == WAIT_TIMEOUT)
00159 {
00160 EnterCriticalSection (&cond->lock);
00161 _dbus_list_remove (&cond->list, event);
00162
00163
00164
00165
00166
00167 retval = WaitForSingleObject (event, 0);
00168
00169 LeaveCriticalSection (&cond->lock);
00170 }
00171
00172 #ifndef DBUS_DISABLE_ASSERT
00173 EnterCriticalSection (&cond->lock);
00174
00175
00176 _dbus_assert (_dbus_list_remove (&cond->list, event) == FALSE);
00177
00178 LeaveCriticalSection (&cond->lock);
00179 #endif
00180
00181 return retval != WAIT_TIMEOUT;
00182 }
00183
00184 static void
00185 _dbus_windows_condvar_wait (DBusCondVar *cond,
00186 DBusMutex *mutex)
00187 {
00188 _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
00189 }
00190
00191 static dbus_bool_t
00192 _dbus_windows_condvar_wait_timeout (DBusCondVar *cond,
00193 DBusMutex *mutex,
00194 int timeout_milliseconds)
00195 {
00196 return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
00197 }
00198
00199 static void
00200 _dbus_windows_condvar_wake_one (DBusCondVar *cond)
00201 {
00202 EnterCriticalSection (&cond->lock);
00203
00204 if (cond->list != NULL)
00205 SetEvent (_dbus_list_pop_first (&cond->list));
00206
00207 LeaveCriticalSection (&cond->lock);
00208 }
00209
00210 static void
00211 _dbus_windows_condvar_wake_all (DBusCondVar *cond)
00212 {
00213 EnterCriticalSection (&cond->lock);
00214
00215 while (cond->list != NULL)
00216 SetEvent (_dbus_list_pop_first (&cond->list));
00217
00218 LeaveCriticalSection (&cond->lock);
00219 }
00220
00221 static const DBusThreadFunctions windows_functions =
00222 {
00223 DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
00224 DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
00225 DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
00226 DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
00227 DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
00228 DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
00229 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
00230 DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
00231 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
00232 DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
00233 _dbus_windows_mutex_new,
00234 _dbus_windows_mutex_free,
00235 _dbus_windows_mutex_lock,
00236 _dbus_windows_mutex_unlock,
00237 _dbus_windows_condvar_new,
00238 _dbus_windows_condvar_free,
00239 _dbus_windows_condvar_wait,
00240 _dbus_windows_condvar_wait_timeout,
00241 _dbus_windows_condvar_wake_one,
00242 _dbus_windows_condvar_wake_all
00243 };
00244
00245 dbus_bool_t
00246 _dbus_threads_init_platform_specific (void)
00247 {
00248
00249
00250
00251 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00252 {
00253 dbus_cond_event_tls = TlsAlloc ();
00254 if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
00255 return FALSE;
00256 }
00257
00258 return dbus_threads_init (&windows_functions);
00259 }
00260