glib/gdebug.h glib/gutils.c gobject/gtype.c gthread/gthread-posix.c
[platform/upstream/glib.git] / gthread / gthread-win32.c
index 17b9eea..358ba6e 100644 (file)
 #undef STRICT
 
 #include <process.h>
-#include <malloc.h>
+#include <stdlib.h>
 
 #define win32_check_for_error(what) G_STMT_START{                      \
   if (!(what))                                                         \
-    g_error ("file %s: line %d (%s): error %ld during %s",             \
+    g_error ("file %s: line %d (%s): error %s during %s",              \
             __FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION,                \
-            GetLastError (), #what);                                   \
+            g_win32_error_message (GetLastError ()), #what);           \
   }G_STMT_END
 
-#define G_MUTEX_SIZE (sizeof (HANDLE))
+#define G_MUTEX_SIZE (sizeof (gpointer))
 
 #define PRIORITY_LOW_VALUE    THREAD_PRIORITY_BELOW_NORMAL
 #define PRIORITY_NORMAL_VALUE THREAD_PRIORITY_NORMAL
@@ -94,14 +94,22 @@ struct _GCond
 static GMutex *
 g_mutex_new_win32_cs_impl (void)
 {
-  CRITICAL_SECTION *retval = g_new (CRITICAL_SECTION, 1);
-  InitializeCriticalSection (retval);
+  CRITICAL_SECTION *cs = g_new (CRITICAL_SECTION, 1);
+  gpointer *retval = g_new (gpointer, 1);
+
+  InitializeCriticalSection (cs);
+  *retval = cs;
   return (GMutex *) retval;
 }
 
 static void
 g_mutex_free_win32_cs_impl (GMutex *mutex)
 {
+  gpointer *ptr = (gpointer *) mutex;
+  CRITICAL_SECTION *cs = (CRITICAL_SECTION *) *ptr;
+
+  DeleteCriticalSection (cs);
+  g_free (cs);
   g_free (mutex);
 }
 
@@ -111,33 +119,37 @@ g_mutex_free_win32_cs_impl (GMutex *mutex)
 static void
 g_mutex_lock_win32_cs_impl (GMutex *mutex)
 {
-  EnterCriticalSection ((CRITICAL_SECTION *)mutex);
+  EnterCriticalSection (*(CRITICAL_SECTION **)mutex);
 }
 
 static gboolean
 g_mutex_trylock_win32_cs_impl (GMutex * mutex)
 {
-  return try_enter_critical_section ((CRITICAL_SECTION *)mutex);
+  return try_enter_critical_section (*(CRITICAL_SECTION **)mutex);
 }
 
 static void
 g_mutex_unlock_win32_cs_impl (GMutex *mutex)
 {
-  LeaveCriticalSection ((CRITICAL_SECTION *)mutex);
+  LeaveCriticalSection (*(CRITICAL_SECTION **)mutex);
 }
 
 static GMutex *
 g_mutex_new_win32_impl (void)
 {
   HANDLE handle;
+  HANDLE *retval;
   win32_check_for_error (handle = CreateMutex (NULL, FALSE, NULL));
-  return (GMutex *) handle;
+  retval = g_new (HANDLE, 1);
+  *retval = handle;
+  return (GMutex *) retval;
 }
 
 static void
 g_mutex_free_win32_impl (GMutex *mutex)
 {
-  win32_check_for_error (CloseHandle ((HANDLE) mutex));
+  win32_check_for_error (CloseHandle (*(HANDLE *) mutex));
+  g_free (mutex);
 }
 
 /* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
@@ -146,7 +158,7 @@ g_mutex_free_win32_impl (GMutex *mutex)
 static void
 g_mutex_lock_win32_impl (GMutex *mutex)
 {
-  WaitForSingleObject ((HANDLE) mutex, INFINITE);
+  WaitForSingleObject (*(HANDLE *) mutex, INFINITE);
 }
 
 static gboolean
@@ -154,14 +166,14 @@ g_mutex_trylock_win32_impl (GMutex * mutex)
 {
   DWORD result;
   win32_check_for_error (WAIT_FAILED != 
-                        (result = WaitForSingleObject ((HANDLE)mutex, 0)));
+                        (result = WaitForSingleObject (*(HANDLE *)mutex, 0)));
   return result != WAIT_TIMEOUT;
 }
 
 static void
 g_mutex_unlock_win32_impl (GMutex *mutex)
 {
-  ReleaseMutex ((HANDLE) mutex);
+  ReleaseMutex (*(HANDLE *) mutex);
 }
 
 static GCond *
@@ -237,8 +249,11 @@ g_cond_wait_internal (GCond *cond,
       g_ptr_array_remove (cond->array, event);
 
       /* In the meantime we could have been signaled, so we must again
-       * wait for the signal, this time with no timeout, to reset it */
-      win32_check_for_error (WAIT_FAILED != WaitForSingleObject (event, 0));
+       * wait for the signal, this time with no timeout, to reset
+       * it. retval is set again to honour the late arrival of the
+       * signal */
+      win32_check_for_error (WAIT_FAILED != 
+                            (retval = WaitForSingleObject (event, 0)));
 
       LeaveCriticalSection (&cond->lock);
     }
@@ -276,16 +291,27 @@ g_cond_timed_wait_win32_impl (GCond *cond,
   g_return_val_if_fail (cond != NULL, FALSE);
   g_return_val_if_fail (entered_mutex != NULL, FALSE);
 
-  g_get_current_time (&current_time);
-  to_wait = (abs_time->tv_sec - current_time.tv_sec) * 1000 +
-    (abs_time->tv_usec - current_time.tv_usec) / 1000;
-
+  if (!abs_time)
+    to_wait = INFINITE;
+  else
+    {
+      g_get_current_time (&current_time);
+      if (abs_time->tv_sec < current_time.tv_sec ||
+         (abs_time->tv_sec == current_time.tv_sec &&
+          abs_time->tv_usec <= current_time.tv_usec))
+       to_wait = 0;
+      else
+       to_wait = (abs_time->tv_sec - current_time.tv_sec) * 1000 +
+         (abs_time->tv_usec - current_time.tv_usec) / 1000;      
+    }
+  
   return g_cond_wait_internal (cond, entered_mutex, to_wait);
 }
 
 static void
 g_cond_free_win32_impl (GCond * cond)
 {
+  DeleteCriticalSection (&cond->lock);
   g_ptr_array_free (cond->array, TRUE);
   g_free (cond);
 }
@@ -464,9 +490,11 @@ g_thread_create_win32_impl (GThreadFunc func,
 
   if (retval->thread == NULL)
     {
-      g_free (retval);
+      gchar *win_error = g_win32_error_message (GetLastError ());
       g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, 
-                   "Error creating thread: %ld", GetLastError());
+                   "Error creating thread: %s", win_error);
+      g_free (retval);
+      g_free (win_error);
       return;
     }
 
@@ -516,15 +544,22 @@ static GThreadFunctions g_thread_functions_for_glib_use_default =
   g_thread_join_win32_impl,
   g_thread_exit_win32_impl,
   g_thread_set_priority_win32_impl,
-  g_thread_self_win32_impl
+  g_thread_self_win32_impl,
+  NULL                              /* no equal function necessary */
 };
 
 #define HAVE_G_THREAD_IMPL_INIT
 static void
 g_thread_impl_init ()
 {
+  static gboolean beenhere = FALSE;
   HMODULE kernel32;
 
+  if (beenhere)
+    return;
+
+  beenhere = TRUE;
+  
   win32_check_for_error (TLS_OUT_OF_INDEXES != 
                         (g_thread_self_tls = TlsAlloc ()));
   win32_check_for_error (TLS_OUT_OF_INDEXES != 
@@ -564,4 +599,3 @@ g_thread_impl_init ()
        }
     }
 }
-