📄 gthread.c
字号:
/* GLIB - Library of useful routines for C programming * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * gmutex.c: MT safety related functions * Copyright 1998 Sebastian Wilhelmi; University of Karlsruhe * Owen Taylor * * 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 "glibconfig.h"#include "glib.h"#ifdef G_THREAD_USE_PID_SURROGATE#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#include <errno.h>#endif /* G_THREAD_USE_PID_SURROGATE */#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <string.h>#if GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P# define g_system_thread_equal_simple(thread1, thread2) \ ((thread1).dummy_pointer == (thread2).dummy_pointer)# define g_system_thread_assign(dest, src) \ ((dest).dummy_pointer = (src).dummy_pointer)#else /* GLIB_SIZEOF_SYSTEM_THREAD != SIZEOF_VOID_P */# define g_system_thread_equal_simple(thread1, thread2) \ (memcmp (&(thread1), &(thread2), GLIB_SIZEOF_SYSTEM_THREAD) == 0)# define g_system_thread_assign(dest, src) \ (memcpy (&(dest), &(src), GLIB_SIZEOF_SYSTEM_THREAD))#endif /* GLIB_SIZEOF_SYSTEM_THREAD == SIZEOF_VOID_P */#define g_system_thread_equal(thread1, thread2) \ (g_thread_functions_for_glib_use.thread_equal ? \ g_thread_functions_for_glib_use.thread_equal (&(thread1), &(thread2)) :\ g_system_thread_equal_simple((thread1), (thread2)))GQuark g_thread_error_quark (void){ static GQuark quark; if (!quark) quark = g_quark_from_static_string ("g_thread_error"); return quark;}/* Keep this in sync with GRealThread in gmain.c! */typedef struct _GRealThread GRealThread;struct _GRealThread{ GThread thread; gpointer private_data; gpointer retval; GSystemThread system_thread;#ifdef G_THREAD_USE_PID_SURROGATE pid_t pid;#endif /* G_THREAD_USE_PID_SURROGATE */};#ifdef G_THREAD_USE_PID_SURROGATEstatic gint priority_map[] = { 15, 0, -15, -20 };static gboolean prio_warned = FALSE;# define SET_PRIO(pid, prio) G_STMT_START{ \ gint error = setpriority (PRIO_PROCESS, (pid), priority_map[prio]); \ if (error == -1 && errno == EACCES && !prio_warned) \ { \ prio_warned = TRUE; \ g_warning ("Priorities can only be increased by root."); \ } \ }G_STMT_END#endif /* G_THREAD_USE_PID_SURROGATE */typedef struct _GStaticPrivateNode GStaticPrivateNode;struct _GStaticPrivateNode{ gpointer data; GDestroyNotify destroy;};static void g_thread_cleanup (gpointer data);static void g_thread_fail (void);/* Global variables */static GSystemThread zero_thread; /* This is initialized to all zero */gboolean g_thread_use_default_impl = TRUE;gboolean g_threads_got_initialized = FALSE;#if defined(G_PLATFORM_WIN32) && defined(__GNUC__)__declspec(dllexport)#endifGThreadFunctions g_thread_functions_for_glib_use = { (GMutex*(*)())g_thread_fail, /* mutex_new */ NULL, /* mutex_lock */ NULL, /* mutex_trylock */ NULL, /* mutex_unlock */ NULL, /* mutex_free */ (GCond*(*)())g_thread_fail, /* cond_new */ NULL, /* cond_signal */ NULL, /* cond_broadcast */ NULL, /* cond_wait */ NULL, /* cond_timed_wait */ NULL, /* cond_free */ (GPrivate*(*)(GDestroyNotify))g_thread_fail, /* private_new */ NULL, /* private_get */ NULL, /* private_set */ (void(*)(GThreadFunc, gpointer, gulong, gboolean, gboolean, GThreadPriority, gpointer, GError**))g_thread_fail, /* thread_create */ NULL, /* thread_yield */ NULL, /* thread_join */ NULL, /* thread_exit */ NULL, /* thread_set_priority */ NULL /* thread_self */}; /* Local data */static GMutex *g_mutex_protect_static_mutex_allocation = NULL;static GPrivate *g_thread_specific_private = NULL;static GSList *g_thread_all_threads = NULL;static GSList *g_thread_free_indeces = NULL;G_LOCK_DEFINE_STATIC (g_thread);/* This must be called only once, before any threads are created. * It will only be called from g_thread_init() in -lgthread. */voidg_mutex_init (void){ GRealThread* main_thread; /* We let the main thread (the one that calls g_thread_init) inherit * the data, that it set before calling g_thread_init */ main_thread = (GRealThread*) g_thread_self (); g_thread_specific_private = g_private_new (g_thread_cleanup); G_THREAD_UF (private_set, (g_thread_specific_private, main_thread)); G_THREAD_UF (thread_self, (&main_thread->system_thread)); g_mutex_protect_static_mutex_allocation = g_mutex_new ();}void g_static_mutex_init (GStaticMutex *mutex){ static GStaticMutex init_mutex = G_STATIC_MUTEX_INIT; g_return_if_fail (mutex); *mutex = init_mutex;}GMutex *g_static_mutex_get_mutex_impl (GMutex** mutex){ if (!g_thread_supported ()) return NULL; g_assert (g_mutex_protect_static_mutex_allocation); g_mutex_lock (g_mutex_protect_static_mutex_allocation); if (!(*mutex)) *mutex = g_mutex_new (); g_mutex_unlock (g_mutex_protect_static_mutex_allocation); return *mutex;}voidg_static_mutex_free (GStaticMutex* mutex){ GMutex **runtime_mutex; g_return_if_fail (mutex); /* The runtime_mutex is the first (or only) member of GStaticMutex, * see both versions (of glibconfig.h) in configure.in */ runtime_mutex = ((GMutex**)mutex); if (*runtime_mutex) g_mutex_free (*runtime_mutex); *runtime_mutex = NULL;}void g_static_rec_mutex_init (GStaticRecMutex *mutex){ static GStaticRecMutex init_mutex = G_STATIC_REC_MUTEX_INIT; g_return_if_fail (mutex); *mutex = init_mutex;}voidg_static_rec_mutex_lock (GStaticRecMutex* mutex){ GSystemThread self; g_return_if_fail (mutex); if (!g_thread_supported ()) return; G_THREAD_UF (thread_self, (&self)); if (g_system_thread_equal (self, mutex->owner)) { mutex->depth++; return; } g_static_mutex_lock (&mutex->mutex); g_system_thread_assign (mutex->owner, self); mutex->depth = 1;}gbooleang_static_rec_mutex_trylock (GStaticRecMutex* mutex){ GSystemThread self; g_return_val_if_fail (mutex, FALSE); if (!g_thread_supported ()) return TRUE; G_THREAD_UF (thread_self, (&self)); if (g_system_thread_equal (self, mutex->owner)) { mutex->depth++; return TRUE; } if (!g_static_mutex_trylock (&mutex->mutex)) return FALSE; g_system_thread_assign (mutex->owner, self); mutex->depth = 1; return TRUE;}voidg_static_rec_mutex_unlock (GStaticRecMutex* mutex){ g_return_if_fail (mutex); if (!g_thread_supported ()) return; if (mutex->depth > 1) { mutex->depth--; return; } g_system_thread_assign (mutex->owner, zero_thread); g_static_mutex_unlock (&mutex->mutex); }voidg_static_rec_mutex_lock_full (GStaticRecMutex *mutex, guint depth){ GSystemThread self; g_return_if_fail (mutex); if (!g_thread_supported ()) return; G_THREAD_UF (thread_self, (&self)); if (g_system_thread_equal (self, mutex->owner)) { mutex->depth += depth; return; } g_static_mutex_lock (&mutex->mutex); g_system_thread_assign (mutex->owner, self); mutex->depth = depth;}guint g_static_rec_mutex_unlock_full (GStaticRecMutex *mutex){ guint depth; g_return_val_if_fail (mutex, 0); if (!g_thread_supported ()) return 1; depth = mutex->depth; g_system_thread_assign (mutex->owner, zero_thread); mutex->depth = 0; g_static_mutex_unlock (&mutex->mutex); return depth;}voidg_static_rec_mutex_free (GStaticRecMutex *mutex){ g_return_if_fail (mutex); g_static_mutex_free (&mutex->mutex);}void g_static_private_init (GStaticPrivate *private_key){ private_key->index = 0;}gpointerg_static_private_get (GStaticPrivate *private_key){ GRealThread *self = (GRealThread*) g_thread_self (); GArray *array; array = self->private_data; if (!array) return NULL; if (!private_key->index) return NULL; else if (private_key->index <= array->len) return g_array_index (array, GStaticPrivateNode, private_key->index - 1).data; else return NULL;}voidg_static_private_set (GStaticPrivate *private_key, gpointer data, GDestroyNotify notify){ GRealThread *self = (GRealThread*) g_thread_self (); GArray *array; static guint next_index = 0; GStaticPrivateNode *node; array = self->private_data; if (!array) { array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode)); self->private_data = array; } if (!private_key->index) { G_LOCK (g_thread); if (!private_key->index) { if (g_thread_free_indeces) { private_key->index = GPOINTER_TO_UINT (g_thread_free_indeces->data); g_thread_free_indeces = g_slist_delete_link (g_thread_free_indeces, g_thread_free_indeces); } else private_key->index = ++next_index; } G_UNLOCK (g_thread); } if (private_key->index > array->len) g_array_set_size (array, private_key->index); node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1); if (node->destroy) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -