diff options
author | Ryan Lortie <desrt@desrt.ca> | 2011-08-31 18:00:03 -0400 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2011-09-09 12:47:40 -0400 |
commit | cfa1d0540e4aaf83641f3876a2589a1e8f2b1242 (patch) | |
tree | 4ee4a1511122b0a8dbf56cd673c15f6e73101585 /gthread | |
parent | 96e489680423f87428c74b1f6ec8a6b8a9c99645 (diff) |
Move the GThread implementations to glib/
We can now get threads initialised from inside of libglib by calling
g_thread_init_glib().
Diffstat (limited to 'gthread')
-rw-r--r-- | gthread/Makefile.am | 8 | ||||
-rw-r--r-- | gthread/gthread-impl.c | 6 | ||||
-rw-r--r-- | gthread/gthread-posix.c | 409 | ||||
-rw-r--r-- | gthread/gthread-win32.c | 563 |
4 files changed, 5 insertions, 981 deletions
diff --git a/gthread/Makefile.am b/gthread/Makefile.am index 700f39c45..70b630512 100644 --- a/gthread/Makefile.am +++ b/gthread/Makefile.am @@ -13,8 +13,6 @@ AM_CPPFLAGS = \ EXTRA_DIST += \ makefile.msc.in \ - gthread-posix.c \ - gthread-win32.c \ gthread.def \ gthread.rc.in @@ -66,11 +64,7 @@ gthread_win32_res = gthread-win32-res.o gthread_win32_res_ldflag = -Wl,$(gthread_win32_res) endif -if OS_WIN32 -libgthread_2_0_la_SOURCES = gthread-win32.c -else -libgthread_2_0_la_SOURCES = gthread-posix.c -endif +libgthread_2_0_la_SOURCES = gthread-impl.c libgthread_2_0_la_LDFLAGS = $(GLIB_LINK_FLAGS) \ $(gthread_win32_res_ldflag) \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ diff --git a/gthread/gthread-impl.c b/gthread/gthread-impl.c index bd7ba79a3..123faa00f 100644 --- a/gthread/gthread-impl.c +++ b/gthread/gthread-impl.c @@ -31,6 +31,10 @@ * MT safe */ +#include "glib.h" + +#include "gthreadprivate.h" + void g_thread_init (GThreadFunctions *init) { @@ -44,8 +48,6 @@ g_thread_init (GThreadFunctions *init) already_done = TRUE; - g_thread_impl_init (); - g_thread_functions_for_glib_use = g_thread_functions_for_glib_use_default; g_thread_init_glib (); } diff --git a/gthread/gthread-posix.c b/gthread/gthread-posix.c deleted file mode 100644 index da580a766..000000000 --- a/gthread/gthread-posix.c +++ /dev/null @@ -1,409 +0,0 @@ -/* GLIB - Library of useful routines for C programming - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * gthread.c: posix thread system implementation - * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GLib Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GLib Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. - */ - -/* - * MT safe - */ - -#include "config.h" - -#include "glib.h" -#include "gthreadprivate.h" - -#include <pthread.h> -#include <errno.h> -#include <stdlib.h> -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif - -#ifdef HAVE_SCHED_H -#include <sched.h> -#endif - -#define posix_check_err(err, name) G_STMT_START{ \ - int error = (err); \ - if (error) \ - g_error ("file %s: line %d (%s): error '%s' during '%s'", \ - __FILE__, __LINE__, G_STRFUNC, \ - g_strerror (error), name); \ - }G_STMT_END - -#define posix_check_cmd(cmd) posix_check_err (cmd, #cmd) - -#ifdef G_ENABLE_DEBUG -static gboolean posix_check_cmd_prio_warned = FALSE; -# define posix_check_cmd_prio(cmd) G_STMT_START{ \ - int err = (cmd); \ - if (err == EPERM) \ - { \ - if (!posix_check_cmd_prio_warned) \ - { \ - posix_check_cmd_prio_warned = TRUE; \ - g_warning ("Priorities can only be changed " \ - "(resp. increased) by root."); \ - } \ - } \ - else \ - posix_check_err (err, #cmd); \ - }G_STMT_END -#else /* G_ENABLE_DEBUG */ -# define posix_check_cmd_prio(cmd) G_STMT_START{ \ - int err = (cmd); \ - if (err != EPERM) \ - posix_check_err (err, #cmd); \ - }G_STMT_END -#endif /* G_ENABLE_DEBUG */ - -#if defined (POSIX_MIN_PRIORITY) && defined (POSIX_MAX_PRIORITY) -# define HAVE_PRIORITIES 1 -static gint priority_normal_value; -# ifdef __FreeBSD__ - /* FreeBSD threads use different priority values from the POSIX_ - * defines so we just set them here. The corresponding macros - * PTHREAD_MIN_PRIORITY and PTHREAD_MAX_PRIORITY are implied to be - * exported by the docs, but they aren't. - */ -# define PRIORITY_LOW_VALUE 0 -# define PRIORITY_URGENT_VALUE 31 -# else /* !__FreeBSD__ */ -# define PRIORITY_LOW_VALUE POSIX_MIN_PRIORITY -# define PRIORITY_URGENT_VALUE POSIX_MAX_PRIORITY -# endif /* !__FreeBSD__ */ -# define PRIORITY_NORMAL_VALUE priority_normal_value - -# define PRIORITY_HIGH_VALUE \ - ((PRIORITY_NORMAL_VALUE + PRIORITY_URGENT_VALUE * 2) / 3) - -static gint -g_thread_priority_map (GThreadPriority priority) -{ - switch (priority) - { - case G_THREAD_PRIORITY_LOW: - return PRIORITY_LOW_VALUE; - - case G_THREAD_PRIORITY_NORMAL: - return PRIORITY_NORMAL_VALUE; - - case G_THREAD_PRIORITY_HIGH: - return PRIORITY_HIGH_VALUE; - - case G_THREAD_PRIORITY_URGENT: - return PRIORITY_URGENT_VALUE; - - default: - g_assert_not_reached (); - } -} - -#endif /* POSIX_MIN_PRIORITY && POSIX_MAX_PRIORITY */ - -static gulong g_thread_min_stack_size = 0; - -#define G_MUTEX_SIZE (sizeof (pthread_mutex_t)) - -static void -g_thread_impl_init(void) -{ -#ifdef _SC_THREAD_STACK_MIN - g_thread_min_stack_size = MAX (sysconf (_SC_THREAD_STACK_MIN), 0); -#endif /* _SC_THREAD_STACK_MIN */ -#ifdef HAVE_PRIORITIES - { - struct sched_param sched; - int policy; - posix_check_cmd (pthread_getschedparam (pthread_self(), &policy, &sched)); - priority_normal_value = sched.sched_priority; - } -#endif /* HAVE_PRIORITIES */ -} - -static GMutex * -g_mutex_new_posix_impl (void) -{ - GMutex *result = (GMutex *) g_new (pthread_mutex_t, 1); - posix_check_cmd (pthread_mutex_init ((pthread_mutex_t *) result, NULL)); - return result; -} - -static void -g_mutex_free_posix_impl (GMutex * mutex) -{ - posix_check_cmd (pthread_mutex_destroy ((pthread_mutex_t *) mutex)); - g_free (mutex); -} - -/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use - functions from gmem.c and gmessages.c; */ - -/* pthread_mutex_lock, pthread_mutex_unlock can be taken directly, as - signature and semantic are right, but without error check then!!!!, - we might want to change this therefore. */ - -static gboolean -g_mutex_trylock_posix_impl (GMutex * mutex) -{ - int result; - - result = pthread_mutex_trylock ((pthread_mutex_t *) mutex); - - if (result == EBUSY) - return FALSE; - - posix_check_err (result, "pthread_mutex_trylock"); - return TRUE; -} - -static GCond * -g_cond_new_posix_impl (void) -{ - GCond *result = (GCond *) g_new (pthread_cond_t, 1); - posix_check_cmd (pthread_cond_init ((pthread_cond_t *) result, NULL)); - return result; -} - -/* pthread_cond_signal, pthread_cond_broadcast and pthread_cond_wait - can be taken directly, as signature and semantic are right, but - without error check then!!!!, we might want to change this - therefore. */ - -#define G_NSEC_PER_SEC 1000000000 - -static gboolean -g_cond_timed_wait_posix_impl (GCond * cond, - GMutex * entered_mutex, - GTimeVal * abs_time) -{ - int result; - struct timespec end_time; - gboolean timed_out; - - g_return_val_if_fail (cond != NULL, FALSE); - g_return_val_if_fail (entered_mutex != NULL, FALSE); - - if (!abs_time) - { - result = pthread_cond_wait ((pthread_cond_t *)cond, - (pthread_mutex_t *) entered_mutex); - timed_out = FALSE; - } - else - { - end_time.tv_sec = abs_time->tv_sec; - end_time.tv_nsec = abs_time->tv_usec * (G_NSEC_PER_SEC / G_USEC_PER_SEC); - - g_return_val_if_fail (end_time.tv_nsec < G_NSEC_PER_SEC, TRUE); - - result = pthread_cond_timedwait ((pthread_cond_t *) cond, - (pthread_mutex_t *) entered_mutex, - &end_time); - timed_out = (result == ETIMEDOUT); - } - - if (!timed_out) - posix_check_err (result, "pthread_cond_timedwait"); - - return !timed_out; -} - -static void -g_cond_free_posix_impl (GCond * cond) -{ - posix_check_cmd (pthread_cond_destroy ((pthread_cond_t *) cond)); - g_free (cond); -} - -static GPrivate * -g_private_new_posix_impl (GDestroyNotify destructor) -{ - GPrivate *result = (GPrivate *) g_new (pthread_key_t, 1); - posix_check_cmd (pthread_key_create ((pthread_key_t *) result, destructor)); - return result; -} - -/* NOTE: the functions g_private_get and g_private_set may not use - functions from gmem.c and gmessages.c */ - -static void -g_private_set_posix_impl (GPrivate * private_key, gpointer value) -{ - if (!private_key) - return; - pthread_setspecific (*(pthread_key_t *) private_key, value); -} - -static gpointer -g_private_get_posix_impl (GPrivate * private_key) -{ - if (!private_key) - return NULL; - - return pthread_getspecific (*(pthread_key_t *) private_key); -} - -static void -g_thread_create_posix_impl (GThreadFunc thread_func, - gpointer arg, - gulong stack_size, - gboolean joinable, - gboolean bound, - GThreadPriority priority, - gpointer thread, - GError **error) -{ - pthread_attr_t attr; - gint ret; - - g_return_if_fail (thread_func); - g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); - g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); - - posix_check_cmd (pthread_attr_init (&attr)); - -#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE - if (stack_size) - { - stack_size = MAX (g_thread_min_stack_size, stack_size); - /* No error check here, because some systems can't do it and - * we simply don't want threads to fail because of that. */ - pthread_attr_setstacksize (&attr, stack_size); - } -#endif /* HAVE_PTHREAD_ATTR_SETSTACKSIZE */ - -#ifdef PTHREAD_SCOPE_SYSTEM - if (bound) - /* No error check here, because some systems can't do it and we - * simply don't want threads to fail because of that. */ - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); -#endif /* PTHREAD_SCOPE_SYSTEM */ - - posix_check_cmd (pthread_attr_setdetachstate (&attr, - joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED)); - -#ifdef HAVE_PRIORITIES - { - struct sched_param sched; - posix_check_cmd (pthread_attr_getschedparam (&attr, &sched)); - sched.sched_priority = g_thread_priority_map (priority); - posix_check_cmd_prio (pthread_attr_setschedparam (&attr, &sched)); - } -#endif /* HAVE_PRIORITIES */ - ret = pthread_create (thread, &attr, (void* (*)(void*))thread_func, arg); - - posix_check_cmd (pthread_attr_destroy (&attr)); - - if (ret == EAGAIN) - { - g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, - "Error creating thread: %s", g_strerror (ret)); - return; - } - - posix_check_err (ret, "pthread_create"); -} - -static void -g_thread_yield_posix_impl (void) -{ - POSIX_YIELD_FUNC; -} - -static void -g_thread_join_posix_impl (gpointer thread) -{ - gpointer ignore; - posix_check_cmd (pthread_join (*(pthread_t*)thread, &ignore)); -} - -static void -g_thread_exit_posix_impl (void) -{ - pthread_exit (NULL); -} - -static void -g_thread_set_priority_posix_impl (gpointer thread, GThreadPriority priority) -{ - g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); - g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); -#ifdef HAVE_PRIORITIES - { - struct sched_param sched; - int policy; - posix_check_cmd (pthread_getschedparam (*(pthread_t*)thread, &policy, - &sched)); - sched.sched_priority = g_thread_priority_map (priority); - posix_check_cmd_prio (pthread_setschedparam (*(pthread_t*)thread, policy, - &sched)); - } -#endif /* HAVE_PRIORITIES */ -} - -static void -g_thread_self_posix_impl (gpointer thread) -{ - *(pthread_t*)thread = pthread_self(); -} - -static gboolean -g_thread_equal_posix_impl (gpointer thread1, gpointer thread2) -{ - return (pthread_equal (*(pthread_t*)thread1, *(pthread_t*)thread2) != 0); -} - -static GThreadFunctions g_thread_functions_for_glib_use_default = -{ - g_mutex_new_posix_impl, - (void (*)(GMutex *)) pthread_mutex_lock, - g_mutex_trylock_posix_impl, - (void (*)(GMutex *)) pthread_mutex_unlock, - g_mutex_free_posix_impl, - g_cond_new_posix_impl, - (void (*)(GCond *)) pthread_cond_signal, - (void (*)(GCond *)) pthread_cond_broadcast, - (void (*)(GCond *, GMutex *)) pthread_cond_wait, - g_cond_timed_wait_posix_impl, - g_cond_free_posix_impl, - g_private_new_posix_impl, - g_private_get_posix_impl, - g_private_set_posix_impl, - g_thread_create_posix_impl, - g_thread_yield_posix_impl, - g_thread_join_posix_impl, - g_thread_exit_posix_impl, - g_thread_set_priority_posix_impl, - g_thread_self_posix_impl, - g_thread_equal_posix_impl -}; - -#include "gthread-impl.c" diff --git a/gthread/gthread-win32.c b/gthread/gthread-win32.c deleted file mode 100644 index bfd1ef77f..000000000 --- a/gthread/gthread-win32.c +++ /dev/null @@ -1,563 +0,0 @@ -/* GLIB - Library of useful routines for C programming - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * gthread.c: solaris thread system implementation - * Copyright 1998-2001 Sebastian Wilhelmi; University of Karlsruhe - * Copyright 2001 Hans Breuer - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GLib Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GLib Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GLib at ftp://ftp.gtk.org/pub/gtk/. - */ - -/* - * MT safe - */ - -#include "config.h" - -#include "glib.h" -#include "gthreadprivate.h" - -#define STRICT -#define _WIN32_WINDOWS 0x0401 /* to get IsDebuggerPresent */ -#include <windows.h> -#undef STRICT - -#include <process.h> -#include <stdlib.h> -#include <stdio.h> - -#define win32_check_for_error(what) G_STMT_START{ \ - if (!(what)) \ - g_error ("file %s: line %d (%s): error %s during %s", \ - __FILE__, __LINE__, G_STRFUNC, \ - g_win32_error_message (GetLastError ()), #what); \ - }G_STMT_END - -#define G_MUTEX_SIZE (sizeof (gpointer)) - -static DWORD g_thread_self_tls; -static DWORD g_private_tls; -static DWORD g_cond_event_tls; -static CRITICAL_SECTION g_thread_global_spinlock; - -typedef BOOL (__stdcall *GTryEnterCriticalSectionFunc) (CRITICAL_SECTION *); - -/* As noted in the docs, GPrivate is a limited resource, here we take - * a rather low maximum to save memory, use GStaticPrivate instead. */ -#define G_PRIVATE_MAX 100 - -static GDestroyNotify g_private_destructors[G_PRIVATE_MAX]; - -static guint g_private_next = 0; - -/* A "forward" declaration of this structure */ -static GThreadFunctions g_thread_functions_for_glib_use_default; - -typedef struct _GThreadData GThreadData; -struct _GThreadData -{ - GThreadFunc func; - gpointer data; - HANDLE thread; - gboolean joinable; -}; - -struct _GCond -{ - GPtrArray *array; - CRITICAL_SECTION lock; -}; - -static GMutex * -g_mutex_new_win32_impl (void) -{ - 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_impl (GMutex *mutex) -{ - gpointer *ptr = (gpointer *) mutex; - CRITICAL_SECTION *cs = (CRITICAL_SECTION *) *ptr; - - DeleteCriticalSection (cs); - g_free (cs); - g_free (mutex); -} - -/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use - functions from gmem.c and gmessages.c; */ - -static void -g_mutex_lock_win32_impl (GMutex *mutex) -{ - EnterCriticalSection (*(CRITICAL_SECTION **)mutex); -} - -static gboolean -g_mutex_trylock_win32_impl (GMutex * mutex) -{ - return TryEnterCriticalSection (*(CRITICAL_SECTION **)mutex); -} - -static void -g_mutex_unlock_win32_impl (GMutex *mutex) -{ - LeaveCriticalSection (*(CRITICAL_SECTION **)mutex); -} - -static GCond * -g_cond_new_win32_impl (void) -{ - GCond *retval = g_new (GCond, 1); - - retval->array = g_ptr_array_new (); - InitializeCriticalSection (&retval->lock); - - return retval; -} - -static void -g_cond_signal_win32_impl (GCond * cond) -{ - EnterCriticalSection (&cond->lock); - - if (cond->array->len > 0) - { - SetEvent (g_ptr_array_index (cond->array, 0)); - g_ptr_array_remove_index (cond->array, 0); - } - - LeaveCriticalSection (&cond->lock); -} - -static void -g_cond_broadcast_win32_impl (GCond * cond) -{ - guint i; - EnterCriticalSection (&cond->lock); - - for (i = 0; i < cond->array->len; i++) - SetEvent (g_ptr_array_index (cond->array, i)); - - g_ptr_array_set_size (cond->array, 0); - LeaveCriticalSection (&cond->lock); -} - -static gboolean -g_cond_wait_internal (GCond *cond, - GMutex *entered_mutex, - gulong milliseconds) -{ - gulong retval; - HANDLE event = TlsGetValue (g_cond_event_tls); - - if (!event) - { - win32_check_for_error (event = CreateEvent (0, FALSE, FALSE, NULL)); - TlsSetValue (g_cond_event_tls, event); - } - - EnterCriticalSection (&cond->lock); - - /* The event must not be signaled. Check this */ - g_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT); - - g_ptr_array_add (cond->array, event); - LeaveCriticalSection (&cond->lock); - - g_mutex_unlock (entered_mutex); - - win32_check_for_error (WAIT_FAILED != - (retval = WaitForSingleObject (event, milliseconds))); - - g_mutex_lock (entered_mutex); - - if (retval == WAIT_TIMEOUT) - { - EnterCriticalSection (&cond->lock); - 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. 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); - } - -#ifndef G_DISABLE_ASSERT - EnterCriticalSection (&cond->lock); - - /* Now event must not be inside the array, check this */ - g_assert (g_ptr_array_remove (cond->array, event) == FALSE); - - LeaveCriticalSection (&cond->lock); -#endif /* !G_DISABLE_ASSERT */ - - return retval != WAIT_TIMEOUT; -} - -static void -g_cond_wait_win32_impl (GCond *cond, - GMutex *entered_mutex) -{ - g_return_if_fail (cond != NULL); - g_return_if_fail (entered_mutex != NULL); - - g_cond_wait_internal (cond, entered_mutex, INFINITE); -} - -static gboolean -g_cond_timed_wait_win32_impl (GCond *cond, - GMutex *entered_mutex, - GTimeVal *abs_time) -{ - GTimeVal current_time; - gulong to_wait; - - g_return_val_if_fail (cond != NULL, FALSE); - g_return_val_if_fail (entered_mutex != NULL, FALSE); - - if (!abs_time) - to_wait = INFINITE; - else - { - g_get_current_time (¤t_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); -} - -static GPrivate * -g_private_new_win32_impl (GDestroyNotify destructor) -{ - GPrivate *result; - EnterCriticalSection (&g_thread_global_spinlock); - if (g_private_next >= G_PRIVATE_MAX) - { - char buf[100]; - sprintf (buf, - "Too many GPrivate allocated. Their number is limited to %d.", - G_PRIVATE_MAX); - MessageBox (NULL, buf, NULL, MB_ICONERROR|MB_SETFOREGROUND); - if (IsDebuggerPresent ()) - G_BREAKPOINT (); - abort (); - } - g_private_destructors[g_private_next] = destructor; - result = GUINT_TO_POINTER (g_private_next); - g_private_next++; - LeaveCriticalSection (&g_thread_global_spinlock); - - return result; -} - -/* NOTE: the functions g_private_get and g_private_set may not use - functions from gmem.c and gmessages.c */ - -static void -g_private_set_win32_impl (GPrivate * private_key, gpointer value) -{ - gpointer* array = TlsGetValue (g_private_tls); - guint index = GPOINTER_TO_UINT (private_key); - - if (index >= G_PRIVATE_MAX) - return; - - if (!array) - { - array = (gpointer*) calloc (G_PRIVATE_MAX, sizeof (gpointer)); - TlsSetValue (g_private_tls, array); - } - - array[index] = value; -} - -static gpointer -g_private_get_win32_impl (GPrivate * private_key) -{ - gpointer* array = TlsGetValue (g_private_tls); - guint index = GPOINTER_TO_UINT (private_key); - - if (index >= G_PRIVATE_MAX || !array) - return NULL; - - return array[index]; -} - -static void -g_thread_set_priority_win32_impl (gpointer thread, GThreadPriority priority) -{ - GThreadData *target = *(GThreadData **)thread; - gint native_prio; - - switch (priority) - { - case G_THREAD_PRIORITY_LOW: - native_prio = THREAD_PRIORITY_BELOW_NORMAL; - break; - - case G_THREAD_PRIORITY_NORMAL: - native_prio = THREAD_PRIORITY_NORMAL; - break; - - case G_THREAD_PRIORITY_HIGH: - native_prio = THREAD_PRIORITY_ABOVE_NORMAL; - break; - - case G_THREAD_PRIORITY_URGENT: - native_prio = THREAD_PRIORITY_HIGHEST; - break; - - default: - g_return_if_reached (); - } - - win32_check_for_error (SetThreadPriority (target->thread, native_prio)); -} - -static void -g_thread_self_win32_impl (gpointer thread) -{ - GThreadData *self = TlsGetValue (g_thread_self_tls); - - if (!self) - { - /* This should only happen for the main thread! */ - HANDLE handle = GetCurrentThread (); - HANDLE process = GetCurrentProcess (); - self = g_new (GThreadData, 1); - win32_check_for_error (DuplicateHandle (process, handle, process, - &self->thread, 0, FALSE, - DUPLICATE_SAME_ACCESS)); - win32_check_for_error (TlsSetValue (g_thread_self_tls, self)); - self->func = NULL; - self->data = NULL; - self->joinable = FALSE; - } - - *(GThreadData **)thread = self; -} - -static void -g_thread_exit_win32_impl (void) -{ - GThreadData *self = TlsGetValue (g_thread_self_tls); - guint i, private_max; - gpointer *array = TlsGetValue (g_private_tls); - HANDLE event = TlsGetValue (g_cond_event_tls); - - EnterCriticalSection (&g_thread_global_spinlock); - private_max = g_private_next; - LeaveCriticalSection (&g_thread_global_spinlock); - - if (array) - { - gboolean some_data_non_null; - - do { - some_data_non_null = FALSE; - for (i = 0; i < private_max; i++) - { - GDestroyNotify destructor = g_private_destructors[i]; - GDestroyNotify data = array[i]; - - if (data) - some_data_non_null = TRUE; - - array[i] = NULL; - - if (destructor && data) - destructor (data); - } - } while (some_data_non_null); - - free (array); - - win32_check_for_error (TlsSetValue (g_private_tls, NULL)); - } - - if (self) - { - if (!self->joinable) - { - win32_check_for_error (CloseHandle (self->thread)); - g_free (self); - } - win32_check_for_error (TlsSetValue (g_thread_self_tls, NULL)); - } - - if (event) - { - CloseHandle (event); - win32_check_for_error (TlsSetValue (g_cond_event_tls, NULL)); - } - - _endthreadex (0); -} - -static guint __stdcall -g_thread_proxy (gpointer data) -{ - GThreadData *self = (GThreadData*) data; - - win32_check_for_error (TlsSetValue (g_thread_self_tls, self)); - - self->func (self->data); - - g_thread_exit_win32_impl (); - - g_assert_not_reached (); - - return 0; -} - -static void -g_thread_create_win32_impl (GThreadFunc func, - gpointer data, - gulong stack_size, - gboolean joinable, - gboolean bound, - GThreadPriority priority, - gpointer thread, - GError **error) -{ - guint ignore; - GThreadData *retval; - - g_return_if_fail (func); - g_return_if_fail (priority >= G_THREAD_PRIORITY_LOW); - g_return_if_fail (priority <= G_THREAD_PRIORITY_URGENT); - - retval = g_new(GThreadData, 1); - retval->func = func; - retval->data = data; - - retval->joinable = joinable; - - retval->thread = (HANDLE) _beginthreadex (NULL, stack_size, g_thread_proxy, - retval, 0, &ignore); - - if (retval->thread == NULL) - { - gchar *win_error = g_win32_error_message (GetLastError ()); - g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN, - "Error creating thread: %s", win_error); - g_free (retval); - g_free (win_error); - return; - } - - *(GThreadData **)thread = retval; - - g_thread_set_priority_win32_impl (thread, priority); -} - -static void -g_thread_yield_win32_impl (void) -{ - Sleep(0); -} - -static void -g_thread_join_win32_impl (gpointer thread) -{ - GThreadData *target = *(GThreadData **)thread; - - g_return_if_fail (target->joinable); - - win32_check_for_error (WAIT_FAILED != - WaitForSingleObject (target->thread, INFINITE)); - - win32_check_for_error (CloseHandle (target->thread)); - g_free (target); -} - -static GThreadFunctions g_thread_functions_for_glib_use_default = -{ - g_mutex_new_win32_impl, /* mutex */ - g_mutex_lock_win32_impl, - g_mutex_trylock_win32_impl, - g_mutex_unlock_win32_impl, - g_mutex_free_win32_impl, - g_cond_new_win32_impl, /* condition */ - g_cond_signal_win32_impl, - g_cond_broadcast_win32_impl, - g_cond_wait_win32_impl, - g_cond_timed_wait_win32_impl, - g_cond_free_win32_impl, - g_private_new_win32_impl, /* private thread data */ - g_private_get_win32_impl, - g_private_set_win32_impl, - g_thread_create_win32_impl, /* thread */ - g_thread_yield_win32_impl, - g_thread_join_win32_impl, - g_thread_exit_win32_impl, - g_thread_set_priority_win32_impl, - g_thread_self_win32_impl, - NULL /* no equal function necessary */ -}; - -static void -g_thread_impl_init () -{ - static gboolean beenhere = FALSE; - - 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 != - (g_private_tls = TlsAlloc ())); - win32_check_for_error (TLS_OUT_OF_INDEXES != - (g_cond_event_tls = TlsAlloc ())); - InitializeCriticalSection (&g_thread_global_spinlock); -} - -#include "gthread-impl.c" |