? gmutex.c ? gthread ? libgthread.la Index: Makefile.am =================================================================== RCS file: /cvs/gnome/glib/Makefile.am,v retrieving revision 1.18 diff -u -r1.18 Makefile.am --- Makefile.am 1998/12/02 23:45:17 1.18 +++ Makefile.am 1998/12/03 15:02:33 @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in # build . first, then SUBDIRS -SUBDIRS = gmodule docs +SUBDIRS = gmodule gthread docs all-recursive-am: all-am # alpha `automake' supports this better #SUBDIRS = . gmodule docs @@ -50,7 +50,8 @@ gstring.c \ gstrfuncs.c \ gscanner.c \ - gutils.c + gutils.c \ + gmutex.c include_HEADERS = \ glib.h Index: acconfig.h =================================================================== RCS file: /cvs/gnome/glib/acconfig.h,v retrieving revision 1.6 diff -u -r1.6 acconfig.h --- acconfig.h 1998/12/02 14:55:20 1.6 +++ acconfig.h 1998/12/03 15:02:33 @@ -84,6 +84,8 @@ #undef WIN32 #undef NATIVE_WIN32 +#undef G_THREAD_SOURCE + /* #undef PACKAGE */ /* #undef VERSION */ Index: configure.in =================================================================== RCS file: /cvs/gnome/glib/configure.in,v retrieving revision 1.31 diff -u -r1.31 configure.in --- configure.in 1998/12/02 14:55:21 1.31 +++ configure.in 1998/12/03 15:02:38 @@ -508,6 +508,150 @@ AC_SUBST(G_MODULE_NEED_USCORE) AC_SUBST(GLIB_DEBUG_FLAGS) + +dnl *********************** +dnl *** g_thread checks *** +dnl *********************** + +AC_ARG_ENABLE(thread, [ --enable-thread=[none/posix/solaris] specify a thread implementation to use.],,) + +dnl error and warning message +dnl ************************* + +THREAD_NO_IMPLEMENTATION="You do not have any known thread system on your + computer. glib will not be thread safe on your computer." + +THREAD_UNKNOWN_COMPILER="Your compiler is not known, so I cannot + determine the necessary compiler options to compile programs + which are using threads. Please provide such information." + +FLAG_DOES_NOT_WORK="I can't find the MACRO, that enables thread safety on your + platform (normaly it's "_REENTRANT"). I'll not use any flag on + compilation now, but then your programs might not work. + Please provide information on how it is done on your system." + +LIBS_NOT_FOUND_1="I can't find the libraries for the thread implementation + " + +LIBS_NOT_FOUND_2=". Please choose another thread implementation or + provide informationon your thread implementation." + +dnl determination of thread implementation +dnl *************************************** + +if test x"$enable_thread" = x; then + case $host in + *-*-solaris*) + AC_CHECK_LIB(thread,cond_init,enable_thread=solaris) + ;; + esac + if test x"$enable_thread" = x; then + AC_CHECK_LIB(pthread,pthread_cond_init,enable_thread=posix) + AC_CHECK_LIB(pthreads,pthread_attr_init,enable_thread=posix) + fi +fi + +AC_MSG_CHECKING(for thread implementation) + +if test x"$enable_thread" = x; then + enable_thread=none + AC_MSG_WARN($THREAD_NO_IMPLEMENTATION) +fi + +AC_MSG_RESULT($enable_thread) + +dnl determination of G_THREAD_LIBS +dnl ****************************** + +G_THREAD_LIBS= + +case $enable_thread in + posix) + G_THREAD_LIBS=error + AC_CHECK_LIB(pthreads,pthread_cond_init, + G_THREAD_LIBS="-lpthreads") + AC_CHECK_LIB(pthread,pthread_cond_init, + G_THREAD_LIBS="-lpthread") + ;; + solaris) + G_THREAD_LIBS=error + AC_CHECK_LIB(thread,cond_init,G_THREAD_LIBS="-lthread") + # solaris has a broken initializer for mutexes, if we find it, + # we will replace it. + AC_MSG_CHECKING(for broken solaris mutex initialization) + AC_EGREP_CPP([ *begin *{ *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *, *0 *} *end *], + [#include + begin DEFAULTMUTEX end], + [solaris_mutex_init_broken=yes], + [solaris_mutex_init_broken=no]) + AC_MSG_RESULT($solaris_mutex_init_broken) + ;; + none) + ;; + *) + G_THREAD_LIBS=error + ;; +esac + +if test "x$G_THREAD_LIBS" = xerror; then + AC_MSG_ERROR($LIBS_NOT_FOUND_1$enable_thread$LIBS_NOT_FOUND_2) +fi + +AC_MSG_CHECKING(necessary linker options) +AC_MSG_RESULT($G_THREAD_LIBS) + +dnl determination of G_THREAD_CFLAGS +dnl ******************************** + +if test x"$enable_thread" != xnone; then + G_THREAD_CFLAGS="-D_REENTRANT" # good default + + case $host in + -aix*) + # FIXME: can somebody confirm this -D_THREAD_SAFE ??? + G_THREAD_CFLAGS="$G_THREAD_CFLAGS -D_THREAD_SAFE" + if test x"$GCC" = xyes; then + G_THREAD_CFLAGS="$G_THREAD_CFLAGS -mthreads" + fi + ;; + esac + + # if we are not finding the ctime_r function, then we probably are + # not using the proper multithread flag + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $G_THREAD_CFLAGS" + AC_EGREP_HEADER([[^a-zA-Z_]ctime_r[^a-zA-Z_]], time.h, , + G_THREAD_CFLAGS= + AC_MSG_WARN($FLAG_DOES_NOT_WORK)) + CPPFLAGS=$old_CPPFLAGS + + if test x"$GCC" = xyes; then + # older gcc's do not know the -fstack-check option and will + # stop compiling, so just check this here + old_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -fstack-check" + AC_TRY_COMPILE(,, + G_THREAD_CFLAGS="$G_THREAD_CFLAGS -fstack-check") + CPPFLAGS=$old_CPPFLAGS + else + AC_MSG_WARN($THREAD_UNKNOWN_COMPILER) + fi + + AC_MSG_CHECKING(necessary compiler options) + + AC_MSG_RESULT($G_THREAD_CFLAGS) +else + G_THREAD_CFLAGS= +fi + +AC_DEFINE_UNQUOTED(G_THREAD_SOURCE,"gthread-$enable_thread.c") +AC_SUBST(G_THREAD_CFLAGS) +AC_SUBST(G_THREAD_LIBS) + +dnl ****************************** +dnl *** output the whole stuff *** +dnl ****************************** + AC_OUTPUT_COMMANDS([ ## Generate `glibconfig.h' in two cases @@ -550,6 +694,9 @@ if test x$glib_values_h = xyes; then echo '#include ' >> $outfile fi + if test x$g_mutex_header_file != x; then + echo '#include <'"$g_mutex_header_file"'>' >> $outfile + fi if test x$glib_sys_poll_h = xyes; then echo '#include ' >> $outfile fi @@ -623,6 +770,34 @@ #define G_BYTE_ORDER $g_byte_order outfile_EOF +cat >>$outfile <>$outfile <>$outfile < #include "glib.h" @@ -40,10 +45,9 @@ static void g_array_maybe_expand (GRealArray *array, gint len); - static GMemChunk *array_mem_chunk = NULL; +static G_LOCK(array_mem_chunk); - GArray* g_array_new (gboolean zero_terminated, gboolean clear, @@ -51,12 +55,14 @@ { GRealArray *array; + g_lock(array_mem_chunk); if (!array_mem_chunk) array_mem_chunk = g_mem_chunk_new ("array mem chunk", sizeof (GRealArray), 1024, G_ALLOC_AND_FREE); array = g_chunk_new (GRealArray, array_mem_chunk); + g_unlock(array_mem_chunk); array->data = NULL; array->len = 0; @@ -75,7 +81,9 @@ if (free_segment) g_free (array->data); + g_lock(array_mem_chunk); g_mem_chunk_free (array_mem_chunk, array); + g_unlock(array_mem_chunk); } GArray* @@ -241,9 +249,8 @@ static void g_ptr_array_maybe_expand (GRealPtrArray *array, gint len); - static GMemChunk *ptr_array_mem_chunk = NULL; - +static G_LOCK(ptr_array_mem_chunk); GPtrArray* @@ -251,12 +258,14 @@ { GRealPtrArray *array; + g_lock(ptr_array_mem_chunk); if (!ptr_array_mem_chunk) ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk", sizeof (GRealPtrArray), 1024, G_ALLOC_AND_FREE); array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk); + g_unlock(ptr_array_mem_chunk); array->pdata = NULL; array->len = 0; @@ -274,7 +283,9 @@ if (free_segment) g_free (array->pdata); + g_lock(ptr_array_mem_chunk); g_mem_chunk_free (ptr_array_mem_chunk, array); + g_unlock(ptr_array_mem_chunk); } static void Index: gcache.c =================================================================== RCS file: /cvs/gnome/glib/gcache.c,v retrieving revision 1.1.1.1 diff -u -r1.1.1.1 gcache.c --- gcache.c 1998/06/10 23:21:13 1.1.1.1 +++ gcache.c 1998/12/03 15:02:38 @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "glib.h" @@ -56,7 +61,7 @@ static GMemChunk *node_mem_chunk = NULL; - +static G_LOCK(node_mem_chunk); GCache* g_cache_new (GCacheNewFunc value_new_func, @@ -193,11 +198,13 @@ { GCacheNode *node; + g_lock(node_mem_chunk); if (!node_mem_chunk) node_mem_chunk = g_mem_chunk_new ("cache node mem chunk", sizeof (GCacheNode), 1024, G_ALLOC_AND_FREE); node = g_chunk_new (GCacheNode, node_mem_chunk); + g_unlock(node_mem_chunk); node->value = value; node->ref_count = 1; @@ -208,5 +215,7 @@ static void g_cache_node_destroy (GCacheNode *node) { + g_lock(node_mem_chunk); g_mem_chunk_free (node_mem_chunk, node); + g_unlock(node_mem_chunk); } Index: gcompletion.c =================================================================== RCS file: /cvs/gnome/glib/gcompletion.c,v retrieving revision 1.2 diff -u -r1.2 gcompletion.c --- gcompletion.c 1998/07/25 03:02:57 1.2 +++ gcompletion.c 1998/12/03 15:02:38 @@ -17,6 +17,10 @@ * Boston, MA 02111-1307, USA. */ +/* + * MT safe + */ + #include "glib.h" #include Index: gdataset.c =================================================================== RCS file: /cvs/gnome/glib/gdataset.c,v retrieving revision 1.9 diff -u -r1.9 gdataset.c --- gdataset.c 1998/11/24 12:18:15 1.9 +++ gdataset.c 1998/12/03 15:02:38 @@ -18,6 +18,12 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ + +/* + * MT safe ; FIXME: might still freeze, watch out, not thoroughly + * looked at yet. + */ + #include #include "glib.h" @@ -48,6 +54,8 @@ /* --- prototypes --- */ +/* all of the following static functions must be called, while holding + the g_dataset_global lock */ static inline GDataset* g_dataset_lookup (gconstpointer dataset_location); static inline void g_datalist_clear_i (GData **datalist); static void g_dataset_destroy_internal (GDataset *dataset); @@ -57,16 +65,22 @@ GDestroyNotify destroy_func, GDataset *dataset); static void g_data_initialize (void); +/* the following static function must be called, while holding the + g_quark_global lock */ static inline GQuark g_quark_new (gchar *string); /* --- variables --- */ +static G_LOCK(g_dataset_global); static GHashTable *g_dataset_location_ht = NULL; -static GDataset *g_dataset_cached = NULL; +static GDataset *g_dataset_cached = NULL; /* should this be + threadspecific? */ static GMemChunk *g_dataset_mem_chunk = NULL; static GMemChunk *g_data_mem_chunk = NULL; static GData *g_data_cache = NULL; static guint g_data_cache_length = 0; + +static G_LOCK(g_quark_global); static GHashTable *g_quark_ht = NULL; static gchar **g_quarks = NULL; static GQuark g_quark_seq_id = 0; @@ -109,11 +123,13 @@ { g_return_if_fail (datalist != NULL); + g_lock(g_dataset_global); if (!g_dataset_location_ht) g_data_initialize (); while (*datalist) g_datalist_clear_i (datalist); + g_unlock(g_dataset_global); } static inline GDataset* @@ -158,6 +174,7 @@ { g_return_if_fail (dataset_location != NULL); + g_lock(g_dataset_global); if (g_dataset_location_ht) { register GDataset *dataset; @@ -166,6 +183,7 @@ if (dataset) g_dataset_destroy_internal (dataset); } + g_unlock(g_dataset_global); } static inline void @@ -293,9 +311,10 @@ return; } + g_lock(g_dataset_global); if (!g_dataset_location_ht) g_data_initialize (); - + dataset = g_dataset_lookup (dataset_location); if (!dataset) { @@ -308,6 +327,7 @@ } g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset); + g_unlock(g_dataset_global); } void @@ -327,10 +347,12 @@ return; } + g_lock(g_dataset_global); if (!g_dataset_location_ht) g_data_initialize (); g_data_set_internal (datalist, key_id, data, destroy_func, NULL); + g_unlock(g_dataset_global); } void @@ -339,6 +361,7 @@ { g_return_if_fail (dataset_location != NULL); + g_lock(g_dataset_global); if (key_id && g_dataset_location_ht) { GDataset *dataset; @@ -346,7 +369,8 @@ dataset = g_dataset_lookup (dataset_location); if (dataset) g_data_set_internal (&dataset->datalist, key_id, NULL, (GDestroyNotify) 42, dataset); - } + } + g_unlock(g_dataset_global); } void @@ -355,8 +379,10 @@ { g_return_if_fail (datalist != NULL); + g_lock(g_dataset_global); if (key_id && g_dataset_location_ht) g_data_set_internal (datalist, key_id, NULL, (GDestroyNotify) 42, NULL); + g_unlock(g_dataset_global); } gpointer @@ -365,6 +391,7 @@ { g_return_val_if_fail (dataset_location != NULL, NULL); + g_lock(g_dataset_global); if (key_id && g_dataset_location_ht) { register GDataset *dataset; @@ -376,10 +403,14 @@ for (list = dataset->datalist; list; list = list->next) if (list->id == key_id) - return list->data; + { + g_unlock(g_dataset_global); + return list->data; + } } } - + g_unlock(g_dataset_global); + return NULL; } @@ -411,17 +442,23 @@ g_return_if_fail (dataset_location != NULL); g_return_if_fail (func != NULL); + g_lock(g_dataset_global); if (g_dataset_location_ht) { dataset = g_dataset_lookup (dataset_location); + g_unlock(g_dataset_global); if (dataset) { register GData *list; for (list = dataset->datalist; list; list = list->next) - func (list->id, list->data, user_data); + func (list->id, list->data, user_data); } } + else + { + g_unlock(g_dataset_global); + } } void @@ -468,12 +505,15 @@ GQuark g_quark_try_string (const gchar *string) { + GQuark quark = 0; g_return_val_if_fail (string != NULL, 0); + g_lock(g_quark_global); if (g_quark_ht) - return (gulong) g_hash_table_lookup (g_quark_ht, string); - else - return 0; + quark = g_hash_table_lookup (g_quark_ht, string); + g_unlock(g_quark_global); + + return quark; } GQuark @@ -483,6 +523,7 @@ g_return_val_if_fail (string != NULL, 0); + g_lock(g_quark_global); if (g_quark_ht) quark = (gulong) g_hash_table_lookup (g_quark_ht, string); else @@ -493,6 +534,7 @@ if (!quark) quark = g_quark_new (g_strdup (string)); + g_unlock(g_quark_global); return quark; } @@ -504,6 +546,7 @@ g_return_val_if_fail (string != NULL, 0); + g_lock(g_quark_global); if (g_quark_ht) quark = (gulong) g_hash_table_lookup (g_quark_ht, string); else @@ -514,17 +557,21 @@ if (!quark) quark = g_quark_new ((gchar*) string); - + g_unlock(g_quark_global); + return quark; } gchar* g_quark_to_string (GQuark quark) { + gchar* result = NULL; + g_lock(g_quark_global); if (quark > 0 && quark <= g_quark_seq_id) - return g_quarks[quark - 1]; - else - return NULL; + result = g_quarks[quark - 1]; + g_unlock(g_quark_global); + + return result; } static inline GQuark Index: gdate.c =================================================================== RCS file: /cvs/gnome/glib/gdate.c,v retrieving revision 1.5 diff -u -r1.5 gdate.c --- gdate.c 1998/12/02 23:47:01 1.5 +++ gdate.c 1998/12/03 15:02:44 @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "glib.h" #include @@ -383,6 +388,8 @@ memset (d, 0x0, ndates*sizeof (GDate)); } +static G_LOCK(gdate_global); + /* These are for the parser, output to the user should use * * g_date_strftime () - this creates more never-freed memory to annoy * all those memory debugger users. :-) @@ -429,6 +436,7 @@ #define NUM_LEN 10 +/* must be called, while holding the gdate_global lock */ static void g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt) { @@ -488,7 +496,7 @@ if (found != NULL) { pt->month = i; - return; + return; } } @@ -502,12 +510,13 @@ return; } } - + ++i; - } + } } } +/* must be called, while holding the gdate_global lock */ static void g_date_prepare_to_parse (const gchar *str, GDateParseTokens *pt) { @@ -641,6 +650,8 @@ /* set invalid */ g_date_clear (d, 1); + g_lock(gdate_global); + g_date_prepare_to_parse (str, &pt); #ifdef G_ENABLE_DEBUG @@ -649,7 +660,11 @@ #endif - if (pt.num_ints == 4) return; /* presumably a typo; bail out. */ + if (pt.num_ints == 4) + { + g_unlock(gdate_global); + return; /* presumably a typo; bail out. */ + } if (pt.num_ints > 1) { @@ -765,6 +780,7 @@ else g_message ("Rejected DMY %u %u %u", day, m, y); #endif + g_unlock(gdate_global); } void Index: gerror.c =================================================================== RCS file: /cvs/gnome/glib/gerror.c,v retrieving revision 1.5 diff -u -r1.5 gerror.c --- gerror.c 1998/11/01 01:32:55 1.5 +++ gerror.c 1998/12/03 15:02:44 @@ -17,6 +17,11 @@ * Boston, MA 02111-1307, USA. */ +/* + * MT safe ; except for g_on_error_stack_trace, but who wants thread safety + * then + */ + #ifdef HAVE_CONFIG_H #include #endif Index: ghash.c =================================================================== RCS file: /cvs/gnome/glib/ghash.c,v retrieving revision 1.10 diff -u -r1.10 ghash.c --- ghash.c 1998/11/28 01:54:54 1.10 +++ ghash.c 1998/12/03 15:02:44 @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "glib.h" @@ -52,6 +57,8 @@ static void g_hash_nodes_destroy (GHashNode *hash_node); +static G_LOCK(ghash_global); + static GMemChunk *node_mem_chunk = NULL; static GHashNode *node_free_list = NULL; @@ -338,6 +345,7 @@ { GHashNode *hash_node; + g_lock(ghash_global); if (node_free_list) { hash_node = node_free_list; @@ -352,6 +360,7 @@ hash_node = g_chunk_new (GHashNode, node_mem_chunk); } + g_unlock(ghash_global); hash_node->key = key; hash_node->value = value; @@ -363,8 +372,10 @@ static void g_hash_node_destroy (GHashNode *hash_node) { + g_lock(ghash_global); hash_node->next = node_free_list; node_free_list = hash_node; + g_unlock(ghash_global); } static void @@ -380,6 +391,8 @@ while (node->next) node = node->next; + g_lock(ghash_global); node->next = node_free_list; node_free_list = hash_node; + g_unlock(ghash_global); } Index: ghook.c =================================================================== RCS file: /cvs/gnome/glib/ghook.c,v retrieving revision 1.6 diff -u -r1.6 ghook.c --- ghook.c 1998/11/30 07:08:53 1.6 +++ ghook.c 1998/12/03 15:02:45 @@ -19,6 +19,11 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "glib.h" Index: giochannel.c =================================================================== RCS file: /cvs/gnome/glib/giochannel.c,v retrieving revision 1.2 diff -u -r1.2 giochannel.c --- giochannel.c 1998/12/02 14:55:22 1.2 +++ giochannel.c 1998/12/03 15:02:45 @@ -20,6 +20,10 @@ * Boston, MA 02111-1307, USA. */ +/* + * MT safe + */ + #include "glib.h" #include Index: giounix.c =================================================================== RCS file: /cvs/gnome/glib/giounix.c,v retrieving revision 1.2 diff -u -r1.2 giounix.c --- giounix.c 1998/12/02 14:55:23 1.2 +++ giounix.c 1998/12/03 15:02:46 @@ -20,6 +20,10 @@ * Boston, MA 02111-1307, USA. */ +/* + * MT safe + */ + #include "glib.h" #include #include Index: glib-config.in =================================================================== RCS file: /cvs/gnome/glib/glib-config.in,v retrieving revision 1.3 diff -u -r1.3 glib-config.in --- glib-config.in 1998/09/15 19:08:07 1.3 +++ glib-config.in 1998/12/03 15:02:46 @@ -17,6 +17,7 @@ Libraries: glib gmodule + gthread EOF exit $1 } @@ -69,6 +70,9 @@ gmodule) lib_gmodule=yes ;; + gthread) + lib_gthread=yes + ;; *) usage 1 1>&2 ;; @@ -83,7 +87,11 @@ echo $exec_prefix fi if test "$echo_cflags" = "yes"; then - echo -I@libdir@/glib/include $includes + cflags="" + if test "$lib_gthread" = "yes"; then + cflags="$cflags @G_THREAD_CFLAGS@" + fi + echo -I@libdir@/glib/include $includes $cflags fi if test "$echo_libs" = "yes"; then libs="" @@ -92,6 +100,9 @@ fi if test "$lib_gmodule" = "yes"; then libs="@G_MODULE_LDFLAGS@ -lgmodule $libs @G_MODULE_LIBS@" + fi + if test "$lib_gthread" = "yes"; then + libs="-lgthread $libs @G_THREAD_LIBS@" fi - echo "-L@libdir@ $libs" + echo -L@libdir@ $libs fi Index: glib.h =================================================================== RCS file: /cvs/gnome/glib/glib.h,v retrieving revision 1.86 diff -u -r1.86 glib.h --- glib.h 1998/12/02 18:47:08 1.86 +++ glib.h 1998/12/03 15:02:52 @@ -2597,6 +2597,91 @@ #endif /* NATIVE_WIN32 */ +/* functions for mutex and condition support for glib. */ + +/* glib is not completly thread safe now, make 'grep -L "MT safe" g*.c' + to see the files, that are not yet made thread safe */ + +typedef struct _GMutex GMutex; +typedef struct _GCond GCond; + +typedef struct _GMutexFunctions GMutexFunctions; +struct _GMutexFunctions +{ + GMutex* (*mutex_new) (); + void (*mutex_lock) (GMutex* mutex); + gboolean (*mutex_try_lock) (GMutex* mutex); + void (*mutex_unlock) (GMutex* mutex); + void (*mutex_free) (GMutex* mutex); + GCond* (*cond_new) (); + void (*cond_signal) (GCond* cond); + void (*cond_broadcast) (GCond* cond); + void (*cond_wait) (GCond* cond, GMutex* mutex); + gboolean (*cond_timed_wait) (GCond* cond, GMutex* mutex, + GTimeVal *end_time); + void (*cond_free) (GCond* cond); +}; + +GUTILS_C_VAR GMutexFunctions g_mutex_functions_for_glib_use; +GUTILS_C_VAR gboolean g_mutex_use_default_impl; +GUTILS_C_VAR gboolean g_mutex_supported; +GUTILS_C_VAR gboolean g_cond_supported; +GUTILS_C_VAR GMutex *g_mutex_protect_static_mutex_allocation; + +/* initializes the mutex/cond implementation for glib, might only be +called once, and must not be called directly or indirectly from +another glib-function, e.g. as a callback. */ +void g_thread_init(GMutexFunctions* init); + +/* like above, but might be called several times, returning TRUE, if +it was the first call to this function, otherwise FALSE is returned +and the init vetcor is ignored */ +gboolean g_thread_try_init(GMutexFunctions* init); + +/* internal functions for fallback static mutex implementation, please + don't use it directly */ +GMutex* g_static_mutex_get_mutex_impl(GMutex** mutex); + +#define G_USE_MUTEX_FUNC(name,fail,arg) \ + (g_mutex_supported ? (*g_mutex_functions_for_glib_use.name)arg : (fail)) +#define G_USE_COND_FUNC(name,fail,arg) \ + (g_cond_supported ? (*g_mutex_functions_for_glib_use.name)arg : (fail)) + +/* keep in mind, all those mutexes ans static mutexes are not + recursive in general, don't rely on that */ +#define g_mutex_new() G_USE_MUTEX_FUNC(mutex_new,NULL,()) +#define g_mutex_lock(mutex) G_USE_MUTEX_FUNC(mutex_lock,(void)0,(mutex)) +#define g_mutex_try_lock(mutex) G_USE_MUTEX_FUNC(mutex_try_lock,TRUE,(mutex)) +#define g_mutex_unlock(mutex) G_USE_MUTEX_FUNC(mutex_unlock,(void)0,(mutex)) +#define g_mutex_free(mutex) G_USE_MUTEX_FUNC(mutex_free,(void)0,(mutex)) +#define g_cond_new() G_USE_COND_FUNC(cond_new,NULL,()) +#define g_cond_signal(cond) G_USE_COND_FUNC(cond_signal,(void)0,(cond)) +#define g_cond_broadcast(cond) G_USE_COND_FUNC(cond_broadcast,(void)0,(cond)) +#define g_cond_wait(cond,mutex) G_USE_COND_FUNC(cond_wait,(void)0,(cond,mutex)) +#define g_cond_timed_wait(cond,mutex,abs_time) \ + G_USE_COND_FUNC(cond_timed_wait,TRUE,(cond,mutex,abs_time)) +#define g_cond_free(cond) G_USE_COND_FUNC(cond_free,(void)0,(cond)) + +/* GStaticMutex'es can be statically initialized with the value + G_STATIC_MUTEX_INIT, and then they can directly be used, that is + much easier, than having to explicitly allocate the mutex before + use */ +#define g_static_mutex_lock(mutex) \ + g_mutex_lock( g_static_mutex_get_mutex(mutex) ) +#define g_static_mutex_try_lock(mutex) \ + g_mutex_try_lock( g_static_mutex_get_mutex(mutex) ) +#define g_static_mutex_unlock(mutex) \ + g_mutex_unlock( g_static_mutex_get_mutex(mutex) ) + +/* these are some convenience macros, for using StaticMutex'es, you + define them by G_LOCK(name), where name could for example be the + name of the protected varibale, and you (un)lock them with + g_(un)lock(name) */ +#define g_lock_name(name) (name ## _lock) +#define G_LOCK(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT +#define g_lock(name) g_static_mutex_lock(g_lock_name(name)) +#define g_trylock(name) g_static_mutex_try_lock(g_lock_name(name)) +#define g_unlock(name) g_static_mutex_unlock(g_lock_name(name)) #ifdef __cplusplus } Index: glist.c =================================================================== RCS file: /cvs/gnome/glib/glist.c,v retrieving revision 1.5 diff -u -r1.5 glist.c --- glist.c 1998/12/02 14:55:25 1.5 +++ glist.c 1998/12/03 15:02:53 @@ -16,6 +16,11 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ + +/* + * MT safe + */ + #include "glib.h" @@ -31,9 +36,10 @@ }; static GAllocator *current_allocator = NULL; +static G_LOCK(current_allocator); -void -g_list_push_allocator (GAllocator *allocator) +static void +g_list_validate_allocator (GAllocator *allocator) { g_return_if_fail (allocator != NULL); g_return_if_fail (allocator->is_unused == TRUE); @@ -58,13 +64,22 @@ } allocator->is_unused = FALSE; +} + +void +g_list_push_allocator(GAllocator *allocator) +{ + g_list_validate_allocator ( allocator ); + g_lock(current_allocator); allocator->last = current_allocator; current_allocator = allocator; + g_unlock(current_allocator); } void g_list_pop_allocator (void) { + g_lock(current_allocator); if (current_allocator) { GAllocator *allocator; @@ -74,6 +89,7 @@ allocator->last = NULL; allocator->is_unused = TRUE; } + g_unlock(current_allocator); } GList* @@ -81,9 +97,15 @@ { GList *list; + g_lock(current_allocator); if (!current_allocator) - g_list_push_allocator (g_allocator_new ("GLib default GList allocator", 1024)); - + { + GAllocator *allocator = g_allocator_new ("GLib default GList allocator", + 1024); + g_list_validate_allocator ( allocator ); + allocator->last = NULL; + current_allocator = allocator; + } if (!current_allocator->free_lists) { list = g_chunk_new (GList, current_allocator->mem_chunk); @@ -103,6 +125,7 @@ current_allocator->free_lists = list->next; } } + g_unlock(current_allocator); list->next = NULL; list->prev = NULL; @@ -114,9 +137,11 @@ { if (list) { - list->data = list->next; + list->data = list->next; + g_lock(current_allocator); list->next = current_allocator->free_lists; current_allocator->free_lists = list; + g_unlock(current_allocator); } } @@ -125,9 +150,11 @@ { if (list) { - list->data = NULL; + list->data = NULL; + g_lock(current_allocator); list->next = current_allocator->free_lists; current_allocator->free_lists = list; + g_unlock(current_allocator); } }