This commit merges the glib-threads branch into the main

branch. See the ChangeLog for details of the changes.

In brief overview:

 - The set of threading functions can be set
 - A default implementation is provided in -lgthread
 - All static data structures are locked using these
   functions if g_thread_init() is called.
This commit is contained in:
Owen Taylor 1998-12-15 05:28:02 +00:00
parent c8ba100dab
commit 931ea95265
79 changed files with 3635 additions and 245 deletions

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -1,3 +1,87 @@
1998-12-11 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/gthread-nspr.c, configure.in: Added new default thread
implementation on top of the mozilla nspr library.
* gmem.c, gmessaged.c, gthread/gthread.c, gthread/gthread-*.c:
Changed GStaticMutex and GStaticPrivate in gmem.c and gmessages.c
into GMutex and GPrivate resp. to make error reporting and use of
gmem possible in most (not all, though) gthread functions. Also
initialized the modules via new init functions.
* configure.in: Fixed syntax bug in definition of type
GStaticMutex.
* gthread/testgthread.c: Updated to work with nspr, but see note
there for remaining problems.
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmutex.c, glib.h: Now abort, if a mutex/cond/private is
allocated before the thread system is set up.
* gthread/gthread.c (g_thread_init): Removed g_thread_try_init(),
as it is not necessary. Changed the error message. Corrected logic
for g_thread_use_default_impl.
* gmutex.c (g_mutex_init): Keep the thread private data array
after calling g_thread_init().
1998-12-09 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread/testgthread.c (new_thread): Now also working for posix
threads; (wait_thread): Now a better implementation, that does not
use 100% CPU.
* Made the thread related code follow GNU coding standard.
* Made a comment (HOLDS:) above each function, that expects the
given locks to be held.
* Changed try_lock to trylock throughout.
* glib.c: Eventually removed the #if 0'ed code for old GStaticMutex.
* glib.c: Corrected g_trylock macro for G_DEBUG_LOCKS.
* gmain.c (g_main_poll_add_unlocked): first take a new poll record
form the poll_free_list.
* gmem.c, gstrfuncs.c, gutils.c: Made it MT safe.
* gthraed/*.c: Added copyright headers.
* gthread/gthread-solaris.c: do not use g_log for errors, as g_log
uses these module and endless recursions might happen, just use a
plain fprintf(stderr,...).
* gthread/gthread.c (g_thread_try_init): Call g_mutex_init().
* gthread/testgthread.c: updated test program.
Tue Dec 8 18:49:56 1998 Owen Taylor <otaylor@redhat.com>
* Start at adding thread-safety. (mostly work
of Sebastian Wilhelmi <wilhelmi@ira.uka.de>)
- configure.in now looks for a system thread implementation.
Currently support is included for POSIX threads
and Solaris threads. The default support is built
into a separate library -lgthread.
- The thread implementation can be modified by passing
a vector of functions g_thread_init().
- The default or supplied functions are used to
implement a small set of thread functions for
mutexes, condition variables, and thread-private
data.
- GLib now uses these functions to provide thread
safety. (In the sense that all global static
data is locked... individual structures must still
be locked by the caller.)
Sat Dec 12 19:08:59 1998 Tim Janik <timj@gtk.org>
* configure.in: always define G_HAVE_INLINE if __cplusplus is

View File

@ -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 @@ libglib_la_SOURCES = \
gstring.c \
gstrfuncs.c \
gscanner.c \
gutils.c
gutils.c \
gmutex.c
include_HEADERS = \
glib.h

View File

@ -84,6 +84,8 @@
#undef WIN32
#undef NATIVE_WIN32
#undef G_THREAD_SOURCE
/* #undef PACKAGE */
/* #undef VERSION */

View File

@ -508,6 +508,155 @@ AC_SUBST(G_MODULE_HAVE_DLERROR)
AC_SUBST(G_MODULE_NEED_USCORE)
AC_SUBST(GLIB_DEBUG_FLAGS)
dnl ***********************
dnl *** g_thread checks ***
dnl ***********************
AC_ARG_WITH(threads, [ --with-threads=[none/posix/solaris/nspr] 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"$with_threads" = x; then
case $host in
*-*-solaris*)
AC_CHECK_LIB(thread,cond_init,with_threads=solaris)
;;
esac
if test x"$with_threads" = x; then
AC_CHECK_LIB(pthread,pthread_cond_init,with_threads=posix)
AC_CHECK_LIB(pthreads,pthread_attr_init,with_threads=posix)
AC_CHECK_LIB(nspr21,PRP_NewNakedCondVar,with_threads=nspr)
fi
fi
AC_MSG_CHECKING(for thread implementation)
if test x"$with_threads" = x; then
with_threads=none
AC_MSG_WARN($THREAD_NO_IMPLEMENTATION)
fi
AC_MSG_RESULT($with_threads)
dnl determination of G_THREAD_LIBS
dnl ******************************
G_THREAD_LIBS=
case $with_threads 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 <thread.h>
begin DEFAULTMUTEX end],
[solaris_mutex_init_broken=yes],
[solaris_mutex_init_broken=no])
AC_MSG_RESULT($solaris_mutex_init_broken)
;;
nspr)
AC_CHECK_LIB(nspr21,PRP_NewNakedCondVar,
G_THREAD_LIBS="-lnspr21")
;;
none)
;;
*)
G_THREAD_LIBS=error
;;
esac
if test "x$G_THREAD_LIBS" = xerror; then
AC_MSG_ERROR($LIBS_NOT_FOUND_1$with_threads$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"$with_threads" != 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-$with_threads.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 +699,9 @@ outfile_EOF
if test x$glib_values_h = xyes; then
echo '#include <values.h>' >> $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 <sys/types.h>' >> $outfile
echo '#include <sys/poll.h>' >> $outfile
@ -628,6 +780,34 @@ $glib_inline
#define G_BYTE_ORDER $g_byte_order
outfile_EOF
cat >>$outfile <<outfile_EOF
/* definitions for the default mutex implementation */
outfile_EOF
if test x$g_mutex_has_default = xyes; then
cat >>$outfile <<outfile_EOF
typedef struct _GStaticMutex GStaticMutex;
struct _GStaticMutex
{
$g_mutex_default_type default_mutex;
struct _GMutex* runtime_mutex;
};
#define G_STATIC_MUTEX_INIT { $g_mutex_default_init, NULL }
#define g_static_mutex_get_mutex(mutex) \
( g_thread_use_default_impl ? (GMutex*)&mutex.default_mutex : \
g_static_mutex_get_mutex_impl(&mutex.runtime_mutex) )
outfile_EOF
else
cat >>$outfile <<outfile_EOF
typedef struct _GMutex* GStaticMutex;
#define G_STATIC_MUTEX_INIT NULL
#define g_static_mutex_get_mutex(mutex) g_static_mutex_get_mutex_impl(&mutex)
outfile_EOF
fi
g_bit_sizes="16 32"
if test -n "$gint64"; then
g_bit_sizes="$g_bit_sizes 64"
@ -841,6 +1021,31 @@ if test x$glib_working_wctype = xno; then
glib_wc="\$glib_wc
#define G_HAVE_BROKEN_WCTYPE 1"
fi
case $with_threads in
posix)
g_mutex_has_default=yes
g_mutex_default_type='pthread_mutex_t'
g_mutex_default_init='PTHREAD_MUTEX_INITIALIZER'
g_mutex_header_file='pthread.h'
;;
solaris)
g_mutex_has_default=yes
g_mutex_default_type='mutex_t'
if test x$solaris_mutex_init_broken = xyes; then
g_mutex_default_init="{ { { 0, 0, 0, 0 }, USYNC_THREAD }, { { { 0, 0, 0, 0, 0, 0, 0, 0 } } }, 0}"
else
g_mutex_default_init="DEFAULTMUTEX"
fi
g_mutex_header_file='thread.h'
;;
nspr)
g_mutex_has_default=no
;;
*)
g_mutex_has_default=no
;;
esac
])
AC_OUTPUT([
@ -848,6 +1053,7 @@ Makefile
glib-config
gmodule/gmoduleconf.h
gmodule/Makefile
gthread/Makefile
docs/Makefile
],[case "$CONFIG_FILES" in
*glib-config*)chmod +x glib-config;;

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <string.h>
#include "glib.h"
@ -40,9 +45,8 @@ static gint g_nearest_pow (gint num);
static void g_array_maybe_expand (GRealArray *array,
gint len);
static GMemChunk *array_mem_chunk = NULL;
static G_LOCK_DEFINE(array_mem_chunk);
GArray*
g_array_new (gboolean zero_terminated,
@ -51,12 +55,14 @@ g_array_new (gboolean zero_terminated,
{
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 @@ g_array_free (GArray *array,
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 @@ struct _GRealPtrArray
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len);
static GMemChunk *ptr_array_mem_chunk = NULL;
static G_LOCK_DEFINE(ptr_array_mem_chunk);
GPtrArray*
@ -251,12 +258,14 @@ g_ptr_array_new (void)
{
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 @@ g_ptr_array_free (GPtrArray *array,
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

View File

@ -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 <config.h>
#endif

View File

@ -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 void g_cache_node_destroy (GCacheNode *node);
static GMemChunk *node_mem_chunk = NULL;
static G_LOCK_DEFINE(node_mem_chunk);
GCache*
g_cache_new (GCacheNewFunc value_new_func,
@ -193,11 +198,13 @@ g_cache_node_new (gpointer value)
{
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 @@ g_cache_node_new (gpointer value)
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);
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <string.h>

View File

@ -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 <string.h>
#include "glib.h"
@ -61,18 +67,24 @@ static inline GQuark g_quark_new (gchar *string);
/* --- variables --- */
static G_LOCK_DEFINE(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_DEFINE(g_quark_global);
static GHashTable *g_quark_ht = NULL;
static gchar **g_quarks = NULL;
static GQuark g_quark_seq_id = 0;
/* --- functions --- */
/* HOLDS: g_dataset_global_lock */
static inline void
g_datalist_clear_i (GData **datalist)
{
@ -109,13 +121,16 @@ g_datalist_clear (GData **datalist)
{
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);
}
/* HOLDS: g_dataset_global_lock */
static inline GDataset*
g_dataset_lookup (gconstpointer dataset_location)
{
@ -131,6 +146,7 @@ g_dataset_lookup (gconstpointer dataset_location)
return dataset;
}
/* HOLDS: g_dataset_global_lock */
static void
g_dataset_destroy_internal (GDataset *dataset)
{
@ -158,6 +174,7 @@ g_dataset_destroy (gconstpointer dataset_location)
{
g_return_if_fail (dataset_location != NULL);
g_lock (g_dataset_global);
if (g_dataset_location_ht)
{
register GDataset *dataset;
@ -166,8 +183,10 @@ g_dataset_destroy (gconstpointer dataset_location)
if (dataset)
g_dataset_destroy_internal (dataset);
}
g_unlock (g_dataset_global);
}
/* HOLDS: g_dataset_global_lock */
static inline void
g_data_set_internal (GData **datalist,
GQuark key_id,
@ -293,9 +312,10 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
return;
}
g_lock (g_dataset_global);
if (!g_dataset_location_ht)
g_data_initialize ();
dataset = g_dataset_lookup (dataset_location);
if (!dataset)
{
@ -308,6 +328,7 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
}
g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
g_unlock (g_dataset_global);
}
void
@ -327,10 +348,12 @@ g_datalist_id_set_data_full (GData **datalist,
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 +362,7 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
{
g_return_if_fail (dataset_location != NULL);
g_lock (g_dataset_global);
if (key_id && g_dataset_location_ht)
{
GDataset *dataset;
@ -346,7 +370,8 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
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 +380,10 @@ g_datalist_id_remove_no_notify (GData **datalist,
{
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 +392,7 @@ g_dataset_id_get_data (gconstpointer dataset_location,
{
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 +404,14 @@ g_dataset_id_get_data (gconstpointer dataset_location,
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 +443,23 @@ g_dataset_foreach (gconstpointer dataset_location,
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
@ -446,6 +484,7 @@ g_datalist_init (GData **datalist)
*datalist = NULL;
}
/* HOLDS: g_dataset_global_lock */
static void
g_data_initialize (void)
{
@ -468,12 +507,15 @@ g_data_initialize (void)
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 = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
g_unlock (g_quark_global);
return quark;
}
GQuark
@ -483,6 +525,7 @@ g_quark_from_string (const gchar *string)
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 +536,7 @@ g_quark_from_string (const gchar *string)
if (!quark)
quark = g_quark_new (g_strdup (string));
g_unlock (g_quark_global);
return quark;
}
@ -504,6 +548,7 @@ g_quark_from_static_string (const gchar *string)
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,19 +559,24 @@ g_quark_from_static_string (const gchar *string)
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;
}
/* HOLDS: g_quark_global_lock */
static inline GQuark
g_quark_new (gchar *string)
{

24
gdate.c
View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <time.h>
@ -383,6 +388,8 @@ g_date_clear (GDate *d, guint ndates)
memset (d, 0x0, ndates*sizeof (GDate));
}
static G_LOCK_DEFINE(g_date_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 @@ typedef struct _GDateParseTokens GDateParseTokens;
#define NUM_LEN 10
/* HOLDS: g_date_global_lock */
static void
g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
{
@ -488,7 +496,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
if (found != NULL)
{
pt->month = i;
return;
return;
}
}
@ -502,12 +510,13 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
return;
}
}
++i;
}
}
}
}
/* HOLDS: g_date_global_lock */
static void
g_date_prepare_to_parse (const gchar *str, GDateParseTokens *pt)
{
@ -641,6 +650,8 @@ g_date_set_parse (GDate *d,
/* set invalid */
g_date_clear (d, 1);
g_lock (g_date_global);
g_date_prepare_to_parse (str, &pt);
#ifdef G_ENABLE_DEBUG
@ -649,7 +660,11 @@ g_date_set_parse (GDate *d,
#endif
if (pt.num_ints == 4) return; /* presumably a typo; bail out. */
if (pt.num_ints == 4)
{
g_unlock (g_date_global);
return; /* presumably a typo; bail out. */
}
if (pt.num_ints > 1)
{
@ -765,6 +780,7 @@ g_date_set_parse (GDate *d,
else
g_message ("Rejected DMY %u %u %u", day, m, y);
#endif
g_unlock (g_date_global);
}
void

View File

@ -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 <config.h>
#endif

13
ghash.c
View File

@ -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_node_destroy (GHashNode *hash_node);
static void g_hash_nodes_destroy (GHashNode *hash_node);
static G_LOCK_DEFINE(g_hash_global);
static GMemChunk *node_mem_chunk = NULL;
static GHashNode *node_free_list = NULL;
@ -338,6 +345,7 @@ g_hash_node_new (gpointer key,
{
GHashNode *hash_node;
g_lock (g_hash_global);
if (node_free_list)
{
hash_node = node_free_list;
@ -352,6 +360,7 @@ g_hash_node_new (gpointer key,
hash_node = g_chunk_new (GHashNode, node_mem_chunk);
}
g_unlock (g_hash_global);
hash_node->key = key;
hash_node->value = value;
@ -363,8 +372,10 @@ g_hash_node_new (gpointer key,
static void
g_hash_node_destroy (GHashNode *hash_node)
{
g_lock (g_hash_global);
hash_node->next = node_free_list;
node_free_list = hash_node;
g_unlock (g_hash_global);
}
static void
@ -380,6 +391,8 @@ g_hash_nodes_destroy (GHashNode *hash_node)
while (node->next)
node = node->next;
g_lock (g_hash_global);
node->next = node_free_list;
node_free_list = hash_node;
g_unlock (g_hash_global);
}

View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"

View File

@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <unistd.h>

View File

@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <sys/types.h>
#include <unistd.h>

View File

@ -17,6 +17,7 @@ Options:
Libraries:
glib
gmodule
gthread
EOF
exit $1
}
@ -69,6 +70,9 @@ while test $# -gt 0; do
gmodule)
lib_gmodule=yes
;;
gthread)
lib_gthread=yes
;;
*)
usage 1 1>&2
;;
@ -83,7 +87,11 @@ if test "$echo_exec_prefix" = "yes"; then
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=""
@ -93,5 +101,8 @@ if test "$echo_libs" = "yes"; then
if test "$lib_gmodule" = "yes"; then
libs="@G_MODULE_LDFLAGS@ -lgmodule $libs @G_MODULE_LIBS@"
fi
echo "-L@libdir@ $libs"
if test "$lib_gthread" = "yes"; then
libs="-lgthread $libs @G_THREAD_LIBS@"
fi
echo -L@libdir@ $libs
fi

134
glib.h
View File

@ -2597,6 +2597,140 @@ gint gwin_closedir (DIR *dir);
#endif /* NATIVE_WIN32 */
/* functions for thread support for glib. */
typedef struct _GMutex GMutex;
typedef struct _GCond GCond;
typedef struct _GPrivate GPrivate;
typedef struct _GStaticPrivate GStaticPrivate;
typedef struct _GThreadFunctions GThreadFunctions;
struct _GThreadFunctions
{
GMutex* (*mutex_new) (void);
void (*mutex_lock) (GMutex* mutex);
gboolean (*mutex_trylock) (GMutex* mutex);
void (*mutex_unlock) (GMutex* mutex);
void (*mutex_free) (GMutex* mutex);
GCond* (*cond_new) (void);
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);
GPrivate* (*private_new) (GDestroyNotify destructor);
gpointer (*private_get) (GPrivate* private);
void (*private_set) (GPrivate* private, gpointer value);
};
GUTILS_C_VAR GThreadFunctions g_thread_functions_for_glib_use;
GUTILS_C_VAR gboolean g_thread_use_default_impl;
GUTILS_C_VAR gboolean g_thread_supported;
/* initializes the mutex/cond/private 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(GThreadFunctions* 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_THREAD_FUNC_UNCOND(name,arg) \
(*g_thread_functions_for_glib_use.name)arg
#define G_USE_THREAD_FUNC(name,fail,arg) \
(g_thread_supported ? G_USE_THREAD_FUNC_UNCOND(name,arg) : (fail))
/* keep in mind, all those mutexes and static mutexes are not
* recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC_UNCOND(mutex_new,())
#define g_mutex_lock(mutex) G_USE_THREAD_FUNC(mutex_lock,(void)0,(mutex))
#define g_mutex_trylock(mutex) G_USE_THREAD_FUNC(mutex_trylock,TRUE,(mutex))
#define g_mutex_unlock(mutex) G_USE_THREAD_FUNC(mutex_unlock,(void)0,(mutex))
#define g_mutex_free(mutex) G_USE_THREAD_FUNC(mutex_free,(void)0,(mutex))
#define g_cond_new() G_USE_THREAD_FUNC_UNCOND(cond_new,())
#define g_cond_signal(cond) G_USE_THREAD_FUNC(cond_signal,(void)0,(cond))
#define g_cond_broadcast(cond) G_USE_THREAD_FUNC(cond_broadcast,(void)0,(cond))
#define g_cond_wait(cond,mutex) G_USE_THREAD_FUNC(cond_wait,(void)0,(cond,mutex))
#define g_cond_timed_wait(cond,mutex,abs_time) \
G_USE_THREAD_FUNC(cond_timed_wait,TRUE,(cond,mutex,abs_time))
#define g_cond_free(cond) G_USE_THREAD_FUNC(cond_free,(void)0,(cond))
#define g_private_new(destructor) \
G_USE_THREAD_FUNC_UNCOND(private_new,(destructor))
#define g_private_get(private) \
G_USE_THREAD_FUNC(private_get,((gpointer)private),(private))
#define g_private_set(private,value) \
G_USE_THREAD_FUNC(private_set,(void)(private=(GPrivate *)(value)), \
(private,value))
/* 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_trylock(mutex) \
g_mutex_trylock( g_static_mutex_get_mutex(mutex) )
#define g_static_mutex_unlock(mutex) \
g_mutex_unlock( g_static_mutex_get_mutex(mutex) )
struct _GStaticPrivate
{
guint index;
};
#define G_STATIC_PRIVATE_INIT { 0 }
gpointer g_static_private_get (GStaticPrivate* private);
void g_static_private_set (GStaticPrivate *private,
gpointer data,
GDestroyNotify notify);
/* these are some convenience macros, for using StaticMutex'es, you
* define them by G_LOCK_DEFINE(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_DEFINE(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT
#ifdef G_DEBUG_LOCKS
#define g_lock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): locking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
g_static_mutex_lock(g_lock_name(name)); \
}G_STMT_END
#define g_unlock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): unlocking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
g_static_mutex_unlock(g_lock_name(name)); \
}G_STMT_END
#define g_trylock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): try locking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
}G_STMT_END, g_static_mutex_trylock(g_lock_name(name))
#else /* !G_DEBUG_LOCKS */
#define g_lock(name) g_static_mutex_lock(g_lock_name(name))
#define g_unlock(name) g_static_mutex_unlock(g_lock_name(name))
#define g_trylock(name) g_static_mutex_trylock(g_lock_name(name))
#endif
#ifdef __cplusplus
}

View File

@ -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 @@ libglib_la_SOURCES = \
gstring.c \
gstrfuncs.c \
gscanner.c \
gutils.c
gutils.c \
gmutex.c
include_HEADERS = \
glib.h

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <string.h>
#include "glib.h"
@ -40,9 +45,8 @@ static gint g_nearest_pow (gint num);
static void g_array_maybe_expand (GRealArray *array,
gint len);
static GMemChunk *array_mem_chunk = NULL;
static G_LOCK_DEFINE(array_mem_chunk);
GArray*
g_array_new (gboolean zero_terminated,
@ -51,12 +55,14 @@ g_array_new (gboolean zero_terminated,
{
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 @@ g_array_free (GArray *array,
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 @@ struct _GRealPtrArray
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
gint len);
static GMemChunk *ptr_array_mem_chunk = NULL;
static G_LOCK_DEFINE(ptr_array_mem_chunk);
GPtrArray*
@ -251,12 +258,14 @@ g_ptr_array_new (void)
{
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 @@ g_ptr_array_free (GPtrArray *array,
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

View File

@ -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 <config.h>
#endif

View File

@ -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 void g_cache_node_destroy (GCacheNode *node);
static GMemChunk *node_mem_chunk = NULL;
static G_LOCK_DEFINE(node_mem_chunk);
GCache*
g_cache_new (GCacheNewFunc value_new_func,
@ -193,11 +198,13 @@ g_cache_node_new (gpointer value)
{
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 @@ g_cache_node_new (gpointer value)
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);
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <string.h>

View File

@ -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 <string.h>
#include "glib.h"
@ -61,18 +67,24 @@ static inline GQuark g_quark_new (gchar *string);
/* --- variables --- */
static G_LOCK_DEFINE(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_DEFINE(g_quark_global);
static GHashTable *g_quark_ht = NULL;
static gchar **g_quarks = NULL;
static GQuark g_quark_seq_id = 0;
/* --- functions --- */
/* HOLDS: g_dataset_global_lock */
static inline void
g_datalist_clear_i (GData **datalist)
{
@ -109,13 +121,16 @@ g_datalist_clear (GData **datalist)
{
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);
}
/* HOLDS: g_dataset_global_lock */
static inline GDataset*
g_dataset_lookup (gconstpointer dataset_location)
{
@ -131,6 +146,7 @@ g_dataset_lookup (gconstpointer dataset_location)
return dataset;
}
/* HOLDS: g_dataset_global_lock */
static void
g_dataset_destroy_internal (GDataset *dataset)
{
@ -158,6 +174,7 @@ g_dataset_destroy (gconstpointer dataset_location)
{
g_return_if_fail (dataset_location != NULL);
g_lock (g_dataset_global);
if (g_dataset_location_ht)
{
register GDataset *dataset;
@ -166,8 +183,10 @@ g_dataset_destroy (gconstpointer dataset_location)
if (dataset)
g_dataset_destroy_internal (dataset);
}
g_unlock (g_dataset_global);
}
/* HOLDS: g_dataset_global_lock */
static inline void
g_data_set_internal (GData **datalist,
GQuark key_id,
@ -293,9 +312,10 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
return;
}
g_lock (g_dataset_global);
if (!g_dataset_location_ht)
g_data_initialize ();
dataset = g_dataset_lookup (dataset_location);
if (!dataset)
{
@ -308,6 +328,7 @@ g_dataset_id_set_data_full (gconstpointer dataset_location,
}
g_data_set_internal (&dataset->datalist, key_id, data, destroy_func, dataset);
g_unlock (g_dataset_global);
}
void
@ -327,10 +348,12 @@ g_datalist_id_set_data_full (GData **datalist,
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 +362,7 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
{
g_return_if_fail (dataset_location != NULL);
g_lock (g_dataset_global);
if (key_id && g_dataset_location_ht)
{
GDataset *dataset;
@ -346,7 +370,8 @@ g_dataset_id_remove_no_notify (gconstpointer dataset_location,
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 +380,10 @@ g_datalist_id_remove_no_notify (GData **datalist,
{
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 +392,7 @@ g_dataset_id_get_data (gconstpointer dataset_location,
{
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 +404,14 @@ g_dataset_id_get_data (gconstpointer dataset_location,
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 +443,23 @@ g_dataset_foreach (gconstpointer dataset_location,
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
@ -446,6 +484,7 @@ g_datalist_init (GData **datalist)
*datalist = NULL;
}
/* HOLDS: g_dataset_global_lock */
static void
g_data_initialize (void)
{
@ -468,12 +507,15 @@ g_data_initialize (void)
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 = GPOINTER_TO_UINT (g_hash_table_lookup (g_quark_ht, string));
g_unlock (g_quark_global);
return quark;
}
GQuark
@ -483,6 +525,7 @@ g_quark_from_string (const gchar *string)
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 +536,7 @@ g_quark_from_string (const gchar *string)
if (!quark)
quark = g_quark_new (g_strdup (string));
g_unlock (g_quark_global);
return quark;
}
@ -504,6 +548,7 @@ g_quark_from_static_string (const gchar *string)
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,19 +559,24 @@ g_quark_from_static_string (const gchar *string)
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;
}
/* HOLDS: g_quark_global_lock */
static inline GQuark
g_quark_new (gchar *string)
{

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <time.h>
@ -383,6 +388,8 @@ g_date_clear (GDate *d, guint ndates)
memset (d, 0x0, ndates*sizeof (GDate));
}
static G_LOCK_DEFINE(g_date_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 @@ typedef struct _GDateParseTokens GDateParseTokens;
#define NUM_LEN 10
/* HOLDS: g_date_global_lock */
static void
g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
{
@ -488,7 +496,7 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
if (found != NULL)
{
pt->month = i;
return;
return;
}
}
@ -502,12 +510,13 @@ g_date_fill_parse_tokens (const gchar *str, GDateParseTokens *pt)
return;
}
}
++i;
}
}
}
}
/* HOLDS: g_date_global_lock */
static void
g_date_prepare_to_parse (const gchar *str, GDateParseTokens *pt)
{
@ -641,6 +650,8 @@ g_date_set_parse (GDate *d,
/* set invalid */
g_date_clear (d, 1);
g_lock (g_date_global);
g_date_prepare_to_parse (str, &pt);
#ifdef G_ENABLE_DEBUG
@ -649,7 +660,11 @@ g_date_set_parse (GDate *d,
#endif
if (pt.num_ints == 4) return; /* presumably a typo; bail out. */
if (pt.num_ints == 4)
{
g_unlock (g_date_global);
return; /* presumably a typo; bail out. */
}
if (pt.num_ints > 1)
{
@ -765,6 +780,7 @@ g_date_set_parse (GDate *d,
else
g_message ("Rejected DMY %u %u %u", day, m, y);
#endif
g_unlock (g_date_global);
}
void

View File

@ -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 <config.h>
#endif

View File

@ -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_node_destroy (GHashNode *hash_node);
static void g_hash_nodes_destroy (GHashNode *hash_node);
static G_LOCK_DEFINE(g_hash_global);
static GMemChunk *node_mem_chunk = NULL;
static GHashNode *node_free_list = NULL;
@ -338,6 +345,7 @@ g_hash_node_new (gpointer key,
{
GHashNode *hash_node;
g_lock (g_hash_global);
if (node_free_list)
{
hash_node = node_free_list;
@ -352,6 +360,7 @@ g_hash_node_new (gpointer key,
hash_node = g_chunk_new (GHashNode, node_mem_chunk);
}
g_unlock (g_hash_global);
hash_node->key = key;
hash_node->value = value;
@ -363,8 +372,10 @@ g_hash_node_new (gpointer key,
static void
g_hash_node_destroy (GHashNode *hash_node)
{
g_lock (g_hash_global);
hash_node->next = node_free_list;
node_free_list = hash_node;
g_unlock (g_hash_global);
}
static void
@ -380,6 +391,8 @@ g_hash_nodes_destroy (GHashNode *hash_node)
while (node->next)
node = node->next;
g_lock (g_hash_global);
node->next = node_free_list;
node_free_list = hash_node;
g_unlock (g_hash_global);
}

View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"

View File

@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <unistd.h>

View File

@ -20,6 +20,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <sys/types.h>
#include <unistd.h>

View File

@ -2597,6 +2597,140 @@ gint gwin_closedir (DIR *dir);
#endif /* NATIVE_WIN32 */
/* functions for thread support for glib. */
typedef struct _GMutex GMutex;
typedef struct _GCond GCond;
typedef struct _GPrivate GPrivate;
typedef struct _GStaticPrivate GStaticPrivate;
typedef struct _GThreadFunctions GThreadFunctions;
struct _GThreadFunctions
{
GMutex* (*mutex_new) (void);
void (*mutex_lock) (GMutex* mutex);
gboolean (*mutex_trylock) (GMutex* mutex);
void (*mutex_unlock) (GMutex* mutex);
void (*mutex_free) (GMutex* mutex);
GCond* (*cond_new) (void);
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);
GPrivate* (*private_new) (GDestroyNotify destructor);
gpointer (*private_get) (GPrivate* private);
void (*private_set) (GPrivate* private, gpointer value);
};
GUTILS_C_VAR GThreadFunctions g_thread_functions_for_glib_use;
GUTILS_C_VAR gboolean g_thread_use_default_impl;
GUTILS_C_VAR gboolean g_thread_supported;
/* initializes the mutex/cond/private 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(GThreadFunctions* 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_THREAD_FUNC_UNCOND(name,arg) \
(*g_thread_functions_for_glib_use.name)arg
#define G_USE_THREAD_FUNC(name,fail,arg) \
(g_thread_supported ? G_USE_THREAD_FUNC_UNCOND(name,arg) : (fail))
/* keep in mind, all those mutexes and static mutexes are not
* recursive in general, don't rely on that */
#define g_mutex_new() G_USE_THREAD_FUNC_UNCOND(mutex_new,())
#define g_mutex_lock(mutex) G_USE_THREAD_FUNC(mutex_lock,(void)0,(mutex))
#define g_mutex_trylock(mutex) G_USE_THREAD_FUNC(mutex_trylock,TRUE,(mutex))
#define g_mutex_unlock(mutex) G_USE_THREAD_FUNC(mutex_unlock,(void)0,(mutex))
#define g_mutex_free(mutex) G_USE_THREAD_FUNC(mutex_free,(void)0,(mutex))
#define g_cond_new() G_USE_THREAD_FUNC_UNCOND(cond_new,())
#define g_cond_signal(cond) G_USE_THREAD_FUNC(cond_signal,(void)0,(cond))
#define g_cond_broadcast(cond) G_USE_THREAD_FUNC(cond_broadcast,(void)0,(cond))
#define g_cond_wait(cond,mutex) G_USE_THREAD_FUNC(cond_wait,(void)0,(cond,mutex))
#define g_cond_timed_wait(cond,mutex,abs_time) \
G_USE_THREAD_FUNC(cond_timed_wait,TRUE,(cond,mutex,abs_time))
#define g_cond_free(cond) G_USE_THREAD_FUNC(cond_free,(void)0,(cond))
#define g_private_new(destructor) \
G_USE_THREAD_FUNC_UNCOND(private_new,(destructor))
#define g_private_get(private) \
G_USE_THREAD_FUNC(private_get,((gpointer)private),(private))
#define g_private_set(private,value) \
G_USE_THREAD_FUNC(private_set,(void)(private=(GPrivate *)(value)), \
(private,value))
/* 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_trylock(mutex) \
g_mutex_trylock( g_static_mutex_get_mutex(mutex) )
#define g_static_mutex_unlock(mutex) \
g_mutex_unlock( g_static_mutex_get_mutex(mutex) )
struct _GStaticPrivate
{
guint index;
};
#define G_STATIC_PRIVATE_INIT { 0 }
gpointer g_static_private_get (GStaticPrivate* private);
void g_static_private_set (GStaticPrivate *private,
gpointer data,
GDestroyNotify notify);
/* these are some convenience macros, for using StaticMutex'es, you
* define them by G_LOCK_DEFINE(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_DEFINE(name) GStaticMutex g_lock_name(name)=G_STATIC_MUTEX_INIT
#ifdef G_DEBUG_LOCKS
#define g_lock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): locking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
g_static_mutex_lock(g_lock_name(name)); \
}G_STMT_END
#define g_unlock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): unlocking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
g_static_mutex_unlock(g_lock_name(name)); \
}G_STMT_END
#define g_trylock(name) G_STMT_START{ \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_MESSAGE, \
"file %s: line %d (%s): try locking: %s ", \
__FILE__, \
__LINE__, \
__PRETTY_FUNCTION__, \
#name); \
}G_STMT_END, g_static_mutex_trylock(g_lock_name(name))
#else /* !G_DEBUG_LOCKS */
#define g_lock(name) g_static_mutex_lock(g_lock_name(name))
#define g_unlock(name) g_static_mutex_unlock(g_lock_name(name))
#define g_trylock(name) g_static_mutex_trylock(g_lock_name(name))
#endif
#ifdef __cplusplus
}

View File

@ -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,11 @@ struct _GAllocator /* from gmem.c */
};
static GAllocator *current_allocator = NULL;
static G_LOCK_DEFINE(current_allocator);
void
g_list_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_list_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -58,13 +65,22 @@ g_list_push_allocator (GAllocator *allocator)
}
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 +90,7 @@ g_list_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
GList*
@ -81,9 +98,15 @@ g_list_alloc (void)
{
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 +126,7 @@ g_list_alloc (void)
current_allocator->free_lists = list->next;
}
}
g_unlock (current_allocator);
list->next = NULL;
list->prev = NULL;
@ -112,23 +136,31 @@ g_list_alloc (void)
void
g_list_free (GList *list)
{
#if 0
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);
}
#endif
}
void
g_list_free_1 (GList *list)
{
#if 0
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);
}
#endif
}
GList*

View File

@ -20,9 +20,14 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include "config.h"
/* Types */
@ -65,9 +70,12 @@ struct _GPollRec {
/* Forward declarations */
static void g_main_poll (gint timeout,
gboolean use_priority,
gint priority);
static void g_main_poll (gint timeout,
gboolean use_priority,
gint priority);
static void g_main_poll_add_unlocked (gint priority,
GPollFD *fd);
static gboolean g_timeout_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout);
@ -90,6 +98,11 @@ static gboolean g_idle_dispatch (gpointer source_data,
static GSList *pending_dispatches = NULL;
static GHookList source_list = { 0 };
/* The following lock is used for both the list of sources
* and the list of poll records
*/
static G_LOCK_DEFINE (main_loop);
static GSourceFuncs timeout_funcs = {
g_timeout_prepare,
g_timeout_check,
@ -104,6 +117,17 @@ static GSourceFuncs idle_funcs = {
(GDestroyNotify)g_free
};
static GPollRec *poll_records = NULL;
static GPollRec *poll_free_list = NULL;
static GMemChunk *poll_chunk;
static guint n_poll_records = 0;
/* this pipe is used to wake up the main loop when a source is added.
*/
static gint wake_up_pipe[2] = { -1, -1 };
static GPollFD wake_up_rec;
static gboolean poll_waiting = FALSE;
#ifdef HAVE_POLL
static GPollFunc poll_func = (GPollFunc)poll;
#else
@ -205,8 +229,11 @@ g_source_add (gint priority,
gpointer user_data,
GDestroyNotify notify)
{
guint return_val;
GSource *source;
g_lock (main_loop);
if (!source_list.is_setup)
g_hook_list_init (&source_list, sizeof(GSource));
@ -224,31 +251,55 @@ g_source_add (gint priority,
if (can_recurse)
source->hook.flags |= G_SOURCE_CAN_RECURSE;
return source->hook.hook_id;
return_val = source->hook.hook_id;
/* Now wake up the main loop if it is waiting in the poll() */
if (poll_waiting)
{
poll_waiting = FALSE;
write (wake_up_pipe[1], "A", 1);
}
g_unlock (main_loop);
return return_val;
}
void
g_source_remove (guint tag)
{
GHook *hook = g_hook_get (&source_list, tag);
GHook *hook;
g_lock (main_loop);
hook = g_hook_get (&source_list, tag);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
void
g_source_remove_by_user_data (gpointer user_data)
{
GHook *hook = g_hook_find_data (&source_list, TRUE, user_data);
GHook *hook;
g_lock (main_loop);
hook = g_hook_find_data (&source_list, TRUE, user_data);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
static gboolean
@ -262,7 +313,11 @@ g_source_find_source_data (GHook *hook,
void
g_source_remove_by_source_data (gpointer source_data)
{
GHook *hook = g_hook_find (&source_list, TRUE,
GHook *hook;
g_lock (main_loop);
hook = g_hook_find (&source_list, TRUE,
g_source_find_source_data, source_data);
if (hook)
{
@ -270,6 +325,8 @@ g_source_remove_by_source_data (gpointer source_data)
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
void g_get_current_time (GTimeVal *result)
@ -279,6 +336,7 @@ void g_get_current_time (GTimeVal *result)
/* Running the main loop */
/* HOLDS: main_loop_lock */
static void
g_main_dispatch (GTimeVal *current_time)
{
@ -294,10 +352,20 @@ g_main_dispatch (GTimeVal *current_time)
if (G_HOOK_IS_VALID (source))
{
gboolean (*dispatch) (gpointer, GTimeVal *, gpointer);
gpointer hook_data = source->hook.data;
gpointer source_data = source->source_data;
dispatch = ((GSourceFuncs *)source->hook.func)->dispatch;
source->hook.flags |= G_HOOK_FLAG_IN_CALL;
need_destroy = !((GSourceFuncs *)source->hook.func)->dispatch (source->source_data,
current_time,
source->hook.data);
g_unlock (main_loop);
need_destroy = ! dispatch(source_data,
current_time,
hook_data);
g_lock (main_loop);
source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
if (need_destroy)
@ -320,10 +388,13 @@ g_main_iterate (gboolean block, gboolean dispatch)
gint nready = 0;
gint current_priority = 0;
gint timeout;
gboolean retval = FALSE;
g_return_val_if_fail (!block || dispatch, FALSE);
g_get_current_time (&current_time);
g_lock (main_loop);
/* If recursing, finish up current dispatch, before starting over */
if (pending_dispatches)
@ -331,6 +402,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (dispatch)
g_main_dispatch (&current_time);
g_unlock (main_loop);
return TRUE;
}
@ -362,6 +434,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (!dispatch)
{
g_hook_unref (&source_list, hook);
g_unlock (main_loop);
return TRUE;
}
else
@ -426,6 +499,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
else
{
g_hook_unref (&source_list, hook);
g_unlock (main_loop);
return TRUE;
}
}
@ -442,10 +516,12 @@ g_main_iterate (gboolean block, gboolean dispatch)
{
pending_dispatches = g_slist_reverse (pending_dispatches);
g_main_dispatch (&current_time);
return TRUE;
retval = TRUE;
}
else
return FALSE;
g_unlock (main_loop);
return retval;
}
/* See if any events are pending
@ -494,11 +570,7 @@ g_main_destroy (GMainLoop *loop)
g_free (loop);
}
static GPollRec *poll_records = NULL;
static GPollRec *poll_free_list = NULL;
static GMemChunk *poll_chunk;
static guint n_poll_records = 0;
/* HOLDS: main_loop_lock */
static void
g_main_poll (gint timeout, gboolean use_priority, gint priority)
{
@ -508,6 +580,17 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
gint i;
gint npoll;
if (wake_up_pipe[0] < 0)
{
if (pipe (wake_up_pipe) < 0)
g_error ("Cannot create pipe main loop wake-up: %s\n",
g_strerror(errno));
wake_up_rec.fd = wake_up_pipe[0];
wake_up_rec.events = G_IO_IN;
g_main_poll_add_unlocked (0, &wake_up_rec);
}
pollrec = poll_records;
i = 0;
while (pollrec && (!use_priority || priority >= pollrec->priority))
@ -520,8 +603,20 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
i++;
}
poll_waiting = TRUE;
g_unlock (main_loop);
npoll = i;
(*poll_func) (fd_array, npoll, timeout);
g_lock (main_loop);
if (!poll_waiting)
{
gchar c;
read (wake_up_pipe[0], &c, 1);
}
else
poll_waiting = FALSE;
pollrec = poll_records;
i = 0;
@ -538,13 +633,29 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
void
g_main_poll_add (gint priority,
GPollFD *fd)
{
g_lock (main_loop);
g_main_poll_add_unlocked (priority, fd);
g_unlock (main_loop);
}
static void
g_main_poll_add_unlocked (gint priority,
GPollFD *fd)
{
GPollRec *lastrec, *pollrec, *newrec;
if (!poll_chunk)
poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
newrec = g_chunk_new (GPollRec, poll_chunk);
if (poll_free_list)
{
newrec = poll_free_list;
poll_free_list = newrec->next;
}
else
newrec = g_chunk_new (GPollRec, poll_chunk);
newrec->fd = fd;
newrec->priority = priority;
@ -564,6 +675,8 @@ g_main_poll_add (gint priority,
newrec->next = pollrec;
n_poll_records++;
g_unlock (main_loop);
}
void
@ -571,6 +684,8 @@ g_main_poll_remove (GPollFD *fd)
{
GPollRec *pollrec, *lastrec;
g_lock (main_loop);
lastrec = NULL;
pollrec = poll_records;
@ -585,12 +700,15 @@ g_main_poll_remove (GPollFD *fd)
pollrec->next = poll_free_list;
poll_free_list = pollrec;
n_poll_records--;
break;
}
lastrec = pollrec;
pollrec = pollrec->next;
}
n_poll_records--;
g_unlock (main_loop);
}
void

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -48,8 +52,12 @@
*/
#if defined(ENABLE_MEM_PROFILE) && defined(ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS)
#define ENTER_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk++
#define LEAVE_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk--
#define ENTER_MEM_CHUNK_ROUTINE() \
g_static_set (allocating_for_mem_chunk, \
g_static_get (allocating_for_mem_chunk) + 1)
#define ENTER_MEM_CHUNK_ROUTINE() \
g_static_set (allocating_for_mem_chunk, \
g_static_get (allocating_for_mem_chunk) - 1)
#else
#define ENTER_MEM_CHUNK_ROUTINE()
#define LEAVE_MEM_CHUNK_ROUTINE()
@ -117,13 +125,19 @@ static gint g_mem_chunk_area_search (GMemArea *a,
gchar *addr);
/* here we can't use StaticMutexes, as they depend upon a working
* g_malloc, the same holds true for StaticPrivate */
static GMutex* mem_chunks_lock = NULL;
static GRealMemChunk *mem_chunks = NULL;
#ifdef ENABLE_MEM_PROFILE
static GMutex* mem_profile_lock;
static gulong allocations[MEM_PROFILE_TABLE_SIZE] = { 0 };
static gulong allocated_mem = 0;
static gulong freed_mem = 0;
static gint allocating_for_mem_chunk = 0;
static GPrivate* allocating_for_mem_chunk = NULL;
#define IS_IN_MEM_CHUNK_ROUTINE() \
GPOINTER_TO_UINT (g_static_get (allocating_for_mem_chunk))
#endif /* ENABLE_MEM_PROFILE */
@ -174,8 +188,9 @@ g_malloc (gulong size)
*t = size;
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= MEM_PROFILE_TABLE_SIZE - 1)
allocations[size-1] += 1;
@ -185,6 +200,7 @@ g_malloc (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -237,8 +253,9 @@ g_malloc0 (gulong size)
*t = size;
# ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@ -248,8 +265,9 @@ g_malloc0 (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
g_mutex_unlock (mem_profile_lock);
# endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
return p;
@ -286,7 +304,9 @@ g_realloc (gpointer mem,
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile);
freed_mem += *t;
g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -321,8 +341,9 @@ g_realloc (gpointer mem,
*t = size;
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
#endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@ -332,6 +353,7 @@ g_realloc (gpointer mem,
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
#endif
g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -352,8 +374,10 @@ g_free (gpointer mem)
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
size = *t;
#ifdef ENABLE_MEM_PROFILE
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile);
freed_mem += size;
g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -380,19 +404,29 @@ g_mem_profile (void)
{
#ifdef ENABLE_MEM_PROFILE
gint i;
gulong local_allocations[MEM_PROFILE_TABLE_SIZE];
gulong local_allocated_mem;
gulong local_freed_mem;
g_mutex_lock (mem_profile);
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
if (allocations[i] > 0)
local_allocations[i] = allocations[i];
local_allocated_mem = allocated_mem;
local_freed_mem = freed_mem;
g_mutex_unlock (mem_profile);
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
if (local_allocations[i] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
"%lu allocations of %d bytes\n", allocations[i], i + 1);
"%lu allocations of %d bytes\n", local_allocations[i], i + 1);
if (allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
if (local_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
"%lu allocations of greater than %d bytes\n",
allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", allocated_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", freed_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", allocated_mem - freed_mem);
local_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", local_allocated_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", local_freed_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", local_allocated_mem - local_freed_mem);
#endif /* ENABLE_MEM_PROFILE */
}
@ -460,11 +494,13 @@ g_mem_chunk_new (gchar *name,
mem_chunk->area_size += mem_chunk->atom_size - (mem_chunk->area_size % mem_chunk->atom_size);
*/
g_mutex_lock (mem_chunks_lock);
mem_chunk->next = mem_chunks;
mem_chunk->prev = NULL;
if (mem_chunks)
mem_chunks->prev = mem_chunk;
mem_chunks = mem_chunk;
g_mutex_unlock (mem_chunks_lock);
LEAVE_MEM_CHUNK_ROUTINE();
@ -497,8 +533,10 @@ g_mem_chunk_destroy (GMemChunk *mem_chunk)
if (rmem_chunk->prev)
rmem_chunk->prev->next = rmem_chunk->next;
g_mutex_lock (mem_chunks_lock);
if (rmem_chunk == mem_chunks)
mem_chunks = mem_chunks->next;
g_mutex_unlock (mem_chunks_lock);
if (rmem_chunk->type == G_ALLOC_AND_FREE)
g_tree_destroy (rmem_chunk->mem_tree);
@ -826,21 +864,26 @@ g_mem_chunk_info (void)
gint count;
count = 0;
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
while (mem_chunk)
{
count += 1;
mem_chunk = mem_chunk->next;
}
g_mutex_unlock (mem_chunks_lock);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%d mem chunks\n", count);
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
g_mutex_unlock (mem_chunks_lock);
while (mem_chunk)
{
g_mem_chunk_print ((GMemChunk*) mem_chunk);
mem_chunk = mem_chunk->next;
}
}
}
void
@ -848,7 +891,9 @@ g_blow_chunks (void)
{
GRealMemChunk *mem_chunk;
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
g_mutex_unlock (mem_chunks_lock);
while (mem_chunk)
{
g_mem_chunk_clean ((GMemChunk*) mem_chunk);
@ -940,3 +985,13 @@ g_allocator_free (GAllocator *allocator)
g_free (allocator);
}
void
g_mem_init (void)
{
mem_chunks_lock = g_mutex_new();
#ifdef ENABLE_MEM_PROFILE
mem_profile_lock = g_mutex_new();
allocating_for_mem_chunk = g_private_new(NULL);
#endif
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -31,7 +35,7 @@
#endif
#ifdef NATIVE_WIN32
/* Just use stdio. If we're out of memroy, we're hosed anyway. */
/* Just use stdio. If we're out of memory, we're hosed anyway. */
#undef write
static inline int
@ -67,6 +71,9 @@ struct _GLogHandler
/* --- variables --- */
static GMutex* g_messages_lock = NULL;
const gchar *g_log_domain_glib = "GLib";
static GLogDomain *g_log_domains = NULL;
static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
@ -76,20 +83,27 @@ static GErrorFunc glib_error_func = NULL;
static GWarningFunc glib_warning_func = NULL;
static GPrintFunc glib_message_func = NULL;
static GPrivate* g_log_depth = NULL;
/* --- functions --- */
static inline GLogDomain*
g_log_find_domain (const gchar *log_domain)
{
register GLogDomain *domain;
g_mutex_lock (g_messages_lock);
domain = g_log_domains;
while (domain)
{
if (strcmp (domain->log_domain, log_domain) == 0)
return domain;
{
g_mutex_unlock (g_messages_lock);
return domain;
}
domain = domain->next;
}
g_mutex_unlock (g_messages_lock);
return NULL;
}
@ -102,8 +116,11 @@ g_log_domain_new (const gchar *log_domain)
domain->log_domain = g_strdup (log_domain);
domain->fatal_mask = G_LOG_FATAL_MASK;
domain->handlers = NULL;
g_mutex_lock (g_messages_lock);
domain->next = g_log_domains;
g_log_domains = domain;
g_mutex_unlock (g_messages_lock);
return domain;
}
@ -116,7 +133,9 @@ g_log_domain_check_free (GLogDomain *domain)
{
register GLogDomain *last, *work;
last = NULL;
last = NULL;
g_mutex_lock (g_messages_lock);
work = g_log_domains;
while (work)
{
@ -131,7 +150,8 @@ g_log_domain_check_free (GLogDomain *domain)
break;
}
work = work->next;
}
}
g_mutex_unlock (g_messages_lock);
}
}
@ -170,8 +190,10 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask)
/* remove bogus flag */
fatal_mask &= ~G_LOG_FLAG_FATAL;
g_mutex_lock (g_messages_lock);
old_mask = g_log_always_fatal;
g_log_always_fatal = fatal_mask;
g_mutex_unlock (g_messages_lock);
return old_mask;
}
@ -223,7 +245,9 @@ g_log_set_handler (const gchar *log_domain,
domain = g_log_domain_new (log_domain);
handler = g_new (GLogHandler, 1);
g_mutex_lock (g_messages_lock);
handler->id = ++handler_id;
g_mutex_unlock (g_messages_lock);
handler->log_level = log_levels;
handler->log_func = log_func;
handler->data = user_data;
@ -311,19 +335,25 @@ g_logv (const gchar *log_domain,
test_level = 1 << i;
if (log_level & test_level)
{
static guint g_log_depth = 0;
guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
GLogDomain *domain;
GLogFunc log_func;
gpointer data = NULL;
domain = g_log_find_domain (log_domain ? log_domain : "");
if (g_log_depth++)
if (depth)
test_level |= G_LOG_FLAG_RECURSION;
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | g_log_always_fatal) &
test_level) != 0)
test_level |= G_LOG_FLAG_FATAL;
depth++;
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
g_mutex_lock (g_messages_lock);
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
g_log_always_fatal) & test_level) != 0)
test_level |= G_LOG_FLAG_FATAL;
g_mutex_unlock (g_messages_lock);
log_func = g_log_domain_get_handler (domain, test_level, &data);
log_func (log_domain, test_level, buffer, data);
@ -332,7 +362,8 @@ g_logv (const gchar *log_domain,
if (test_level & G_LOG_FLAG_FATAL)
abort ();
g_log_depth--;
depth--;
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
}
}
}
@ -362,8 +393,11 @@ g_log_default_handler (const gchar *log_domain,
gint fd;
#endif
gboolean in_recursion;
gboolean is_fatal;
gboolean is_fatal;
GErrorFunc local_glib_error_func;
GWarningFunc local_glib_warning_func;
GPrintFunc local_glib_message_func;
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
log_level &= G_LOG_LEVEL_MASK;
@ -380,13 +414,19 @@ g_log_default_handler (const gchar *log_domain,
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
#endif
g_mutex_lock (g_messages_lock);
local_glib_error_func = glib_error_func;
local_glib_warning_func = glib_warning_func;
local_glib_message_func = glib_message_func;
g_mutex_unlock (g_messages_lock);
switch (log_level)
{
case G_LOG_LEVEL_ERROR:
if (!log_domain && glib_error_func)
if (!log_domain && local_glib_error_func)
{
/* compatibility code */
glib_error_func (message);
local_glib_error_func (message);
return;
}
/* use write(2) for output, in case we are out of memeory */
@ -428,10 +468,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_WARNING:
if (!log_domain && glib_warning_func)
if (!log_domain && local_glib_warning_func)
{
/* compatibility code */
glib_warning_func (message);
local_glib_warning_func (message);
return;
}
if (log_domain)
@ -453,10 +493,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_MESSAGE:
if (!log_domain && glib_message_func)
if (!log_domain && local_glib_message_func)
{
/* compatibility code */
glib_message_func (message);
local_glib_message_func (message);
return;
}
if (log_domain)
@ -553,8 +593,10 @@ g_set_print_handler (GPrintFunc func)
{
GPrintFunc old_print_func;
g_mutex_lock (g_messages_lock);
old_print_func = glib_print_func;
glib_print_func = func;
g_mutex_unlock (g_messages_lock);
return old_print_func;
}
@ -565,6 +607,7 @@ g_print (const gchar *format,
{
va_list args;
gchar *string;
GPrintFunc local_glib_print_func;
g_return_if_fail (format != NULL);
@ -572,8 +615,12 @@ g_print (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
if (glib_print_func)
glib_print_func (string);
g_mutex_lock (g_messages_lock);
local_glib_print_func = glib_print_func;
g_mutex_unlock (g_messages_lock);
if (local_glib_print_func)
local_glib_print_func (string);
else
{
fputs (string, stdout);
@ -587,8 +634,10 @@ g_set_printerr_handler (GPrintFunc func)
{
GPrintFunc old_printerr_func;
g_mutex_lock (g_messages_lock);
old_printerr_func = glib_printerr_func;
glib_printerr_func = func;
g_mutex_unlock (g_messages_lock);
return old_printerr_func;
}
@ -599,6 +648,7 @@ g_printerr (const gchar *format,
{
va_list args;
gchar *string;
GPrintFunc local_glib_printerr_func;
g_return_if_fail (format != NULL);
@ -606,8 +656,12 @@ g_printerr (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
if (glib_printerr_func)
glib_printerr_func (string);
g_mutex_lock (g_messages_lock);
local_glib_printerr_func = glib_printerr_func;
g_mutex_unlock (g_messages_lock);
if (local_glib_printerr_func)
local_glib_printerr_func (string);
else
{
fputs (string, stderr);
@ -622,9 +676,11 @@ g_set_error_handler (GErrorFunc func)
{
GErrorFunc old_error_func;
g_mutex_lock (g_messages_lock);
old_error_func = glib_error_func;
glib_error_func = func;
g_mutex_unlock (g_messages_lock);
return old_error_func;
}
@ -634,8 +690,10 @@ g_set_warning_handler (GWarningFunc func)
{
GWarningFunc old_warning_func;
g_mutex_lock (g_messages_lock);
old_warning_func = glib_warning_func;
glib_warning_func = func;
g_mutex_unlock (g_messages_lock);
return old_warning_func;
}
@ -646,8 +704,17 @@ g_set_message_handler (GPrintFunc func)
{
GPrintFunc old_message_func;
g_mutex_lock (g_messages_lock);
old_message_func = glib_message_func;
glib_message_func = func;
g_mutex_unlock (g_messages_lock);
return old_message_func;
}
void
g_messages_init (void)
{
g_messages_lock = g_mutex_new();
g_log_depth = g_private_new(NULL);
}

View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
/* node allocation
@ -34,10 +39,12 @@ struct _GAllocator /* from gmem.c */
GNode *free_nodes; /* implementation specific */
};
static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
void
g_node_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_node_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -62,13 +69,22 @@ g_node_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
}
void
g_node_push_allocator (GAllocator *allocator)
{
g_node_validate_allocator ( allocator );
g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
g_unlock (current_allocator);
}
void
g_node_pop_allocator (void)
{
g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@ -78,6 +94,7 @@ g_node_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
@ -87,9 +104,15 @@ g_node_new (gpointer data)
{
GNode *node;
g_lock (current_allocator);
if (!current_allocator)
g_node_push_allocator (g_allocator_new ("GLib default GNode allocator", 1024));
{
GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
1024);
g_node_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_nodes)
node = g_chunk_new (GNode, current_allocator->mem_chunk);
else
@ -97,6 +120,7 @@ g_node_new (gpointer data)
node = current_allocator->free_nodes;
current_allocator->free_nodes = node->next;
}
g_unlock (current_allocator);
node->data = data;
node->next = NULL;
@ -122,9 +146,11 @@ g_nodes_free (GNode *node)
else
break;
}
g_lock (current_allocator);
parent->next = current_allocator->free_nodes;
current_allocator->free_nodes = node;
g_unlock (current_allocator);
}
void

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
static const guint g_primes[] =

View File

@ -15,6 +15,11 @@
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <stdarg.h>
#include <string.h>

View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#define __gscanner_c__
#ifdef HAVE_CONFIG_H

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
@ -30,10 +35,12 @@ struct _GAllocator /* from gmem.c */
GSList *free_lists; /* implementation specific */
};
static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
void
g_slist_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_slist_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -58,13 +65,22 @@ g_slist_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
}
void
g_slist_push_allocator (GAllocator *allocator)
{
g_slist_validate_allocator (allocator);
g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
g_unlock (current_allocator);
}
void
g_slist_pop_allocator (void)
{
g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@ -74,6 +90,7 @@ g_slist_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
GSList*
@ -81,9 +98,15 @@ g_slist_alloc (void)
{
GSList *list;
g_lock (current_allocator);
if (!current_allocator)
g_slist_push_allocator (g_allocator_new ("GLib default GSList allocator", 1024));
{
GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
1024);
g_slist_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_lists)
{
list = g_chunk_new (GSList, current_allocator->mem_chunk);
@ -103,6 +126,8 @@ g_slist_alloc (void)
current_allocator->free_lists = list->next;
}
}
g_unlock (current_allocator);
list->next = NULL;
return list;
@ -114,8 +139,10 @@ g_slist_free (GSList *list)
if (list)
{
list->data = list->next;
g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
g_unlock (current_allocator);
}
}
@ -125,8 +152,10 @@ g_slist_free_1 (GSList *list)
if (list)
{
list->data = NULL;
g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
g_unlock (current_allocator);
}
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -208,7 +212,8 @@ g_strtod (const gchar *nptr,
gchar*
g_strerror (gint errnum)
{
static char msg[64];
static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
char *msg;
#ifdef HAVE_STRERROR
return strerror (errnum);
@ -634,7 +639,14 @@ g_strerror (gint errnum)
if ((errnum > 0) && (errnum <= sys_nerr))
return sys_errlist [errnum];
#endif /* NO_SYS_ERRLIST */
msg = g_static_private_get (&msg_private);
if( !msg )
{
msg = g_new( gchar, 64 );
g_static_private_set (&msg_private, msg, g_free);
}
sprintf (msg, "unknown error (%d)", errnum);
return msg;
}
@ -642,7 +654,8 @@ g_strerror (gint errnum)
gchar*
g_strsignal (gint signum)
{
static char msg[64];
static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
char *msg;
#ifdef HAVE_STRSIGNAL
extern char *strsignal (int sig);
@ -748,6 +761,13 @@ g_strsignal (gint signum)
extern char *sys_siglist[];
return sys_siglist [signum];
#endif /* NO_SYS_SIGLIST */
msg = g_static_private_get (&msg_private);
if( !msg )
{
msg = g_new( gchar, 64 );
g_static_private_set (&msg_private, msg, g_free);
}
sprintf (msg, "unknown signal (%d)", signum);
return msg;

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@ -43,7 +48,7 @@ struct _GRealString
gint alloc;
};
static G_LOCK_DEFINE(string_mem_chunk);
static GMemChunk *string_mem_chunk = NULL;
/* Hash Functions.
@ -202,12 +207,14 @@ g_string_sized_new (guint dfl_size)
{
GRealString *string;
g_lock (string_mem_chunk);
if (!string_mem_chunk)
string_mem_chunk = g_mem_chunk_new ("string mem chunk",
sizeof (GRealString),
1024, G_ALLOC_AND_FREE);
string = g_chunk_new (GRealString, string_mem_chunk);
g_unlock (string_mem_chunk);
string->alloc = 0;
string->len = 0;
@ -241,7 +248,9 @@ g_string_free (GString *string,
if (free_segment)
g_free (string->str);
g_lock (string_mem_chunk);
g_mem_chunk_free (string_mem_chunk, string);
g_unlock (string_mem_chunk);
}
GString*

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
@ -78,6 +83,7 @@ static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
static void g_tree_node_check (GTreeNode *node);
static G_LOCK_DEFINE(g_tree_global);
static GMemChunk *node_mem_chunk = NULL;
static GTreeNode *node_free_list = NULL;
@ -88,6 +94,7 @@ g_tree_node_new (gpointer key,
{
GTreeNode *node;
g_lock (g_tree_global);
if (node_free_list)
{
node = node_free_list;
@ -102,7 +109,8 @@ g_tree_node_new (gpointer key,
G_ALLOC_ONLY);
node = g_chunk_new (GTreeNode, node_mem_chunk);
}
}
g_unlock (g_tree_global);
node->balance = 0;
node->left = NULL;
@ -120,9 +128,11 @@ g_tree_node_destroy (GTreeNode *node)
{
g_tree_node_destroy (node->right);
g_tree_node_destroy (node->left);
g_lock (g_tree_global);
node->right = node_free_list;
node_free_list = node;
}
g_unlock (g_tree_global);
}
}
@ -375,9 +385,11 @@ g_tree_node_remove (GTreeNode *node,
node = g_tree_node_restore_right_balance (new_root, old_balance);
}
g_lock (g_tree_global);
garbage->right = node_free_list;
node_free_list = garbage;
}
g_unlock (g_tree_global);
}
else if (cmp < 0)
{
if (node->left)

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe for the unix part, FIXME: make the win32 part MT safe as well.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -367,11 +371,14 @@ g_getenv (const gchar *variable)
#endif
}
static G_LOCK_DEFINE(g_utils_global);
static gchar *g_tmp_dir = NULL;
static gchar *g_user_name = NULL;
static gchar *g_real_name = NULL;
static gchar *g_home_dir = NULL;
/* HOLDS: g_utils_global_lock */
static void
g_get_any_init (void)
{
@ -442,14 +449,16 @@ g_get_any_init (void)
g_home_dir = NULL;
# endif /* !NATIVE_WIN32 */
#endif /* !HAVE_PWD_H */
}
}
}
gchar*
g_get_user_name (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_user_name;
}
@ -457,9 +466,11 @@ g_get_user_name (void)
gchar*
g_get_real_name (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_real_name;
}
@ -472,8 +483,10 @@ g_get_real_name (void)
gchar*
g_get_home_dir (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_home_dir;
}
@ -488,8 +501,10 @@ g_get_home_dir (void)
gchar*
g_get_tmp_dir (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_tmp_dir;
}
@ -499,16 +514,25 @@ static gchar *g_prgname = NULL;
gchar*
g_get_prgname (void)
{
return g_prgname;
gchar* retval;
g_lock (g_utils_global);
retval = g_prgname;
g_unlock (g_utils_global);
return retval;
}
void
g_set_prgname (const gchar *prgname)
{
gchar *c = g_prgname;
gchar *c;
g_lock (g_utils_global);
c = g_prgname;
g_prgname = g_strdup (prgname);
g_free (c);
g_unlock (g_utils_global);
}
guint

44
glist.c
View File

@ -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,11 @@ struct _GAllocator /* from gmem.c */
};
static GAllocator *current_allocator = NULL;
static G_LOCK_DEFINE(current_allocator);
void
g_list_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_list_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -58,13 +65,22 @@ g_list_push_allocator (GAllocator *allocator)
}
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 +90,7 @@ g_list_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
GList*
@ -81,9 +98,15 @@ g_list_alloc (void)
{
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 +126,7 @@ g_list_alloc (void)
current_allocator->free_lists = list->next;
}
}
g_unlock (current_allocator);
list->next = NULL;
list->prev = NULL;
@ -112,23 +136,31 @@ g_list_alloc (void)
void
g_list_free (GList *list)
{
#if 0
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);
}
#endif
}
void
g_list_free_1 (GList *list)
{
#if 0
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);
}
#endif
}
GList*

158
gmain.c
View File

@ -20,9 +20,14 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include "config.h"
/* Types */
@ -65,9 +70,12 @@ struct _GPollRec {
/* Forward declarations */
static void g_main_poll (gint timeout,
gboolean use_priority,
gint priority);
static void g_main_poll (gint timeout,
gboolean use_priority,
gint priority);
static void g_main_poll_add_unlocked (gint priority,
GPollFD *fd);
static gboolean g_timeout_prepare (gpointer source_data,
GTimeVal *current_time,
gint *timeout);
@ -90,6 +98,11 @@ static gboolean g_idle_dispatch (gpointer source_data,
static GSList *pending_dispatches = NULL;
static GHookList source_list = { 0 };
/* The following lock is used for both the list of sources
* and the list of poll records
*/
static G_LOCK_DEFINE (main_loop);
static GSourceFuncs timeout_funcs = {
g_timeout_prepare,
g_timeout_check,
@ -104,6 +117,17 @@ static GSourceFuncs idle_funcs = {
(GDestroyNotify)g_free
};
static GPollRec *poll_records = NULL;
static GPollRec *poll_free_list = NULL;
static GMemChunk *poll_chunk;
static guint n_poll_records = 0;
/* this pipe is used to wake up the main loop when a source is added.
*/
static gint wake_up_pipe[2] = { -1, -1 };
static GPollFD wake_up_rec;
static gboolean poll_waiting = FALSE;
#ifdef HAVE_POLL
static GPollFunc poll_func = (GPollFunc)poll;
#else
@ -205,8 +229,11 @@ g_source_add (gint priority,
gpointer user_data,
GDestroyNotify notify)
{
guint return_val;
GSource *source;
g_lock (main_loop);
if (!source_list.is_setup)
g_hook_list_init (&source_list, sizeof(GSource));
@ -224,31 +251,55 @@ g_source_add (gint priority,
if (can_recurse)
source->hook.flags |= G_SOURCE_CAN_RECURSE;
return source->hook.hook_id;
return_val = source->hook.hook_id;
/* Now wake up the main loop if it is waiting in the poll() */
if (poll_waiting)
{
poll_waiting = FALSE;
write (wake_up_pipe[1], "A", 1);
}
g_unlock (main_loop);
return return_val;
}
void
g_source_remove (guint tag)
{
GHook *hook = g_hook_get (&source_list, tag);
GHook *hook;
g_lock (main_loop);
hook = g_hook_get (&source_list, tag);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
void
g_source_remove_by_user_data (gpointer user_data)
{
GHook *hook = g_hook_find_data (&source_list, TRUE, user_data);
GHook *hook;
g_lock (main_loop);
hook = g_hook_find_data (&source_list, TRUE, user_data);
if (hook)
{
GSource *source = (GSource *)hook;
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
static gboolean
@ -262,7 +313,11 @@ g_source_find_source_data (GHook *hook,
void
g_source_remove_by_source_data (gpointer source_data)
{
GHook *hook = g_hook_find (&source_list, TRUE,
GHook *hook;
g_lock (main_loop);
hook = g_hook_find (&source_list, TRUE,
g_source_find_source_data, source_data);
if (hook)
{
@ -270,6 +325,8 @@ g_source_remove_by_source_data (gpointer source_data)
((GSourceFuncs *)source->hook.func)->destroy (source->source_data);
g_hook_destroy_link (&source_list, hook);
}
g_unlock (main_loop);
}
void g_get_current_time (GTimeVal *result)
@ -279,6 +336,7 @@ void g_get_current_time (GTimeVal *result)
/* Running the main loop */
/* HOLDS: main_loop_lock */
static void
g_main_dispatch (GTimeVal *current_time)
{
@ -294,10 +352,20 @@ g_main_dispatch (GTimeVal *current_time)
if (G_HOOK_IS_VALID (source))
{
gboolean (*dispatch) (gpointer, GTimeVal *, gpointer);
gpointer hook_data = source->hook.data;
gpointer source_data = source->source_data;
dispatch = ((GSourceFuncs *)source->hook.func)->dispatch;
source->hook.flags |= G_HOOK_FLAG_IN_CALL;
need_destroy = !((GSourceFuncs *)source->hook.func)->dispatch (source->source_data,
current_time,
source->hook.data);
g_unlock (main_loop);
need_destroy = ! dispatch(source_data,
current_time,
hook_data);
g_lock (main_loop);
source->hook.flags &= ~G_HOOK_FLAG_IN_CALL;
if (need_destroy)
@ -320,10 +388,13 @@ g_main_iterate (gboolean block, gboolean dispatch)
gint nready = 0;
gint current_priority = 0;
gint timeout;
gboolean retval = FALSE;
g_return_val_if_fail (!block || dispatch, FALSE);
g_get_current_time (&current_time);
g_lock (main_loop);
/* If recursing, finish up current dispatch, before starting over */
if (pending_dispatches)
@ -331,6 +402,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (dispatch)
g_main_dispatch (&current_time);
g_unlock (main_loop);
return TRUE;
}
@ -362,6 +434,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
if (!dispatch)
{
g_hook_unref (&source_list, hook);
g_unlock (main_loop);
return TRUE;
}
else
@ -426,6 +499,7 @@ g_main_iterate (gboolean block, gboolean dispatch)
else
{
g_hook_unref (&source_list, hook);
g_unlock (main_loop);
return TRUE;
}
}
@ -442,10 +516,12 @@ g_main_iterate (gboolean block, gboolean dispatch)
{
pending_dispatches = g_slist_reverse (pending_dispatches);
g_main_dispatch (&current_time);
return TRUE;
retval = TRUE;
}
else
return FALSE;
g_unlock (main_loop);
return retval;
}
/* See if any events are pending
@ -494,11 +570,7 @@ g_main_destroy (GMainLoop *loop)
g_free (loop);
}
static GPollRec *poll_records = NULL;
static GPollRec *poll_free_list = NULL;
static GMemChunk *poll_chunk;
static guint n_poll_records = 0;
/* HOLDS: main_loop_lock */
static void
g_main_poll (gint timeout, gboolean use_priority, gint priority)
{
@ -508,6 +580,17 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
gint i;
gint npoll;
if (wake_up_pipe[0] < 0)
{
if (pipe (wake_up_pipe) < 0)
g_error ("Cannot create pipe main loop wake-up: %s\n",
g_strerror(errno));
wake_up_rec.fd = wake_up_pipe[0];
wake_up_rec.events = G_IO_IN;
g_main_poll_add_unlocked (0, &wake_up_rec);
}
pollrec = poll_records;
i = 0;
while (pollrec && (!use_priority || priority >= pollrec->priority))
@ -520,8 +603,20 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
i++;
}
poll_waiting = TRUE;
g_unlock (main_loop);
npoll = i;
(*poll_func) (fd_array, npoll, timeout);
g_lock (main_loop);
if (!poll_waiting)
{
gchar c;
read (wake_up_pipe[0], &c, 1);
}
else
poll_waiting = FALSE;
pollrec = poll_records;
i = 0;
@ -538,13 +633,29 @@ g_main_poll (gint timeout, gboolean use_priority, gint priority)
void
g_main_poll_add (gint priority,
GPollFD *fd)
{
g_lock (main_loop);
g_main_poll_add_unlocked (priority, fd);
g_unlock (main_loop);
}
static void
g_main_poll_add_unlocked (gint priority,
GPollFD *fd)
{
GPollRec *lastrec, *pollrec, *newrec;
if (!poll_chunk)
poll_chunk = g_mem_chunk_create (GPollRec, 32, G_ALLOC_ONLY);
newrec = g_chunk_new (GPollRec, poll_chunk);
if (poll_free_list)
{
newrec = poll_free_list;
poll_free_list = newrec->next;
}
else
newrec = g_chunk_new (GPollRec, poll_chunk);
newrec->fd = fd;
newrec->priority = priority;
@ -564,6 +675,8 @@ g_main_poll_add (gint priority,
newrec->next = pollrec;
n_poll_records++;
g_unlock (main_loop);
}
void
@ -571,6 +684,8 @@ g_main_poll_remove (GPollFD *fd)
{
GPollRec *pollrec, *lastrec;
g_lock (main_loop);
lastrec = NULL;
pollrec = poll_records;
@ -585,12 +700,15 @@ g_main_poll_remove (GPollFD *fd)
pollrec->next = poll_free_list;
poll_free_list = pollrec;
n_poll_records--;
break;
}
lastrec = pollrec;
pollrec = pollrec->next;
}
n_poll_records--;
g_unlock (main_loop);
}
void

89
gmem.c
View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -48,8 +52,12 @@
*/
#if defined(ENABLE_MEM_PROFILE) && defined(ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS)
#define ENTER_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk++
#define LEAVE_MEM_CHUNK_ROUTINE() allocating_for_mem_chunk--
#define ENTER_MEM_CHUNK_ROUTINE() \
g_static_set (allocating_for_mem_chunk, \
g_static_get (allocating_for_mem_chunk) + 1)
#define ENTER_MEM_CHUNK_ROUTINE() \
g_static_set (allocating_for_mem_chunk, \
g_static_get (allocating_for_mem_chunk) - 1)
#else
#define ENTER_MEM_CHUNK_ROUTINE()
#define LEAVE_MEM_CHUNK_ROUTINE()
@ -117,13 +125,19 @@ static gint g_mem_chunk_area_search (GMemArea *a,
gchar *addr);
/* here we can't use StaticMutexes, as they depend upon a working
* g_malloc, the same holds true for StaticPrivate */
static GMutex* mem_chunks_lock = NULL;
static GRealMemChunk *mem_chunks = NULL;
#ifdef ENABLE_MEM_PROFILE
static GMutex* mem_profile_lock;
static gulong allocations[MEM_PROFILE_TABLE_SIZE] = { 0 };
static gulong allocated_mem = 0;
static gulong freed_mem = 0;
static gint allocating_for_mem_chunk = 0;
static GPrivate* allocating_for_mem_chunk = NULL;
#define IS_IN_MEM_CHUNK_ROUTINE() \
GPOINTER_TO_UINT (g_static_get (allocating_for_mem_chunk))
#endif /* ENABLE_MEM_PROFILE */
@ -174,8 +188,9 @@ g_malloc (gulong size)
*t = size;
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= MEM_PROFILE_TABLE_SIZE - 1)
allocations[size-1] += 1;
@ -185,6 +200,7 @@ g_malloc (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -237,8 +253,9 @@ g_malloc0 (gulong size)
*t = size;
# ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
# endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@ -248,8 +265,9 @@ g_malloc0 (gulong size)
# ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
# endif
g_mutex_unlock (mem_profile_lock);
# endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
return p;
@ -286,7 +304,9 @@ g_realloc (gpointer mem,
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile);
freed_mem += *t;
g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -321,8 +341,9 @@ g_realloc (gpointer mem,
*t = size;
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile_lock);
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
if(!allocating_for_mem_chunk) {
if(!IS_IN_MEM_CHUNK_ROUTINE()) {
#endif
if (size <= (MEM_PROFILE_TABLE_SIZE - 1))
allocations[size-1] += 1;
@ -332,6 +353,7 @@ g_realloc (gpointer mem,
#ifdef ENABLE_MEM_PROFILE_EXCLUDES_MEM_CHUNKS
}
#endif
g_mutex_unlock (mem_profile_lock);
#endif /* ENABLE_MEM_PROFILE */
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -352,8 +374,10 @@ g_free (gpointer mem)
#if defined(ENABLE_MEM_PROFILE) || defined(ENABLE_MEM_CHECK)
t = (gulong*) ((guchar*) mem - SIZEOF_LONG);
size = *t;
#ifdef ENABLE_MEM_PROFILE
#ifdef ENABLE_MEM_PROFILE
g_mutex_lock (mem_profile);
freed_mem += size;
g_mutex_unlock (mem_profile);
#endif /* ENABLE_MEM_PROFILE */
mem = t;
#endif /* ENABLE_MEM_PROFILE || ENABLE_MEM_CHECK */
@ -380,19 +404,29 @@ g_mem_profile (void)
{
#ifdef ENABLE_MEM_PROFILE
gint i;
gulong local_allocations[MEM_PROFILE_TABLE_SIZE];
gulong local_allocated_mem;
gulong local_freed_mem;
g_mutex_lock (mem_profile);
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
if (allocations[i] > 0)
local_allocations[i] = allocations[i];
local_allocated_mem = allocated_mem;
local_freed_mem = freed_mem;
g_mutex_unlock (mem_profile);
for (i = 0; i < (MEM_PROFILE_TABLE_SIZE - 1); i++)
if (local_allocations[i] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
"%lu allocations of %d bytes\n", allocations[i], i + 1);
"%lu allocations of %d bytes\n", local_allocations[i], i + 1);
if (allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
if (local_allocations[MEM_PROFILE_TABLE_SIZE - 1] > 0)
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO,
"%lu allocations of greater than %d bytes\n",
allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", allocated_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", freed_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", allocated_mem - freed_mem);
local_allocations[MEM_PROFILE_TABLE_SIZE - 1], MEM_PROFILE_TABLE_SIZE - 1);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes allocated\n", local_allocated_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes freed\n", local_freed_mem);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%lu bytes in use\n", local_allocated_mem - local_freed_mem);
#endif /* ENABLE_MEM_PROFILE */
}
@ -460,11 +494,13 @@ g_mem_chunk_new (gchar *name,
mem_chunk->area_size += mem_chunk->atom_size - (mem_chunk->area_size % mem_chunk->atom_size);
*/
g_mutex_lock (mem_chunks_lock);
mem_chunk->next = mem_chunks;
mem_chunk->prev = NULL;
if (mem_chunks)
mem_chunks->prev = mem_chunk;
mem_chunks = mem_chunk;
g_mutex_unlock (mem_chunks_lock);
LEAVE_MEM_CHUNK_ROUTINE();
@ -497,8 +533,10 @@ g_mem_chunk_destroy (GMemChunk *mem_chunk)
if (rmem_chunk->prev)
rmem_chunk->prev->next = rmem_chunk->next;
g_mutex_lock (mem_chunks_lock);
if (rmem_chunk == mem_chunks)
mem_chunks = mem_chunks->next;
g_mutex_unlock (mem_chunks_lock);
if (rmem_chunk->type == G_ALLOC_AND_FREE)
g_tree_destroy (rmem_chunk->mem_tree);
@ -826,21 +864,26 @@ g_mem_chunk_info (void)
gint count;
count = 0;
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
while (mem_chunk)
{
count += 1;
mem_chunk = mem_chunk->next;
}
g_mutex_unlock (mem_chunks_lock);
g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "%d mem chunks\n", count);
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
g_mutex_unlock (mem_chunks_lock);
while (mem_chunk)
{
g_mem_chunk_print ((GMemChunk*) mem_chunk);
mem_chunk = mem_chunk->next;
}
}
}
void
@ -848,7 +891,9 @@ g_blow_chunks (void)
{
GRealMemChunk *mem_chunk;
g_mutex_lock (mem_chunks_lock);
mem_chunk = mem_chunks;
g_mutex_unlock (mem_chunks_lock);
while (mem_chunk)
{
g_mem_chunk_clean ((GMemChunk*) mem_chunk);
@ -940,3 +985,13 @@ g_allocator_free (GAllocator *allocator)
g_free (allocator);
}
void
g_mem_init (void)
{
mem_chunks_lock = g_mutex_new();
#ifdef ENABLE_MEM_PROFILE
mem_profile_lock = g_mutex_new();
allocating_for_mem_chunk = g_private_new(NULL);
#endif
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -31,7 +35,7 @@
#endif
#ifdef NATIVE_WIN32
/* Just use stdio. If we're out of memroy, we're hosed anyway. */
/* Just use stdio. If we're out of memory, we're hosed anyway. */
#undef write
static inline int
@ -67,6 +71,9 @@ struct _GLogHandler
/* --- variables --- */
static GMutex* g_messages_lock = NULL;
const gchar *g_log_domain_glib = "GLib";
static GLogDomain *g_log_domains = NULL;
static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK;
@ -76,20 +83,27 @@ static GErrorFunc glib_error_func = NULL;
static GWarningFunc glib_warning_func = NULL;
static GPrintFunc glib_message_func = NULL;
static GPrivate* g_log_depth = NULL;
/* --- functions --- */
static inline GLogDomain*
g_log_find_domain (const gchar *log_domain)
{
register GLogDomain *domain;
g_mutex_lock (g_messages_lock);
domain = g_log_domains;
while (domain)
{
if (strcmp (domain->log_domain, log_domain) == 0)
return domain;
{
g_mutex_unlock (g_messages_lock);
return domain;
}
domain = domain->next;
}
g_mutex_unlock (g_messages_lock);
return NULL;
}
@ -102,8 +116,11 @@ g_log_domain_new (const gchar *log_domain)
domain->log_domain = g_strdup (log_domain);
domain->fatal_mask = G_LOG_FATAL_MASK;
domain->handlers = NULL;
g_mutex_lock (g_messages_lock);
domain->next = g_log_domains;
g_log_domains = domain;
g_mutex_unlock (g_messages_lock);
return domain;
}
@ -116,7 +133,9 @@ g_log_domain_check_free (GLogDomain *domain)
{
register GLogDomain *last, *work;
last = NULL;
last = NULL;
g_mutex_lock (g_messages_lock);
work = g_log_domains;
while (work)
{
@ -131,7 +150,8 @@ g_log_domain_check_free (GLogDomain *domain)
break;
}
work = work->next;
}
}
g_mutex_unlock (g_messages_lock);
}
}
@ -170,8 +190,10 @@ g_log_set_always_fatal (GLogLevelFlags fatal_mask)
/* remove bogus flag */
fatal_mask &= ~G_LOG_FLAG_FATAL;
g_mutex_lock (g_messages_lock);
old_mask = g_log_always_fatal;
g_log_always_fatal = fatal_mask;
g_mutex_unlock (g_messages_lock);
return old_mask;
}
@ -223,7 +245,9 @@ g_log_set_handler (const gchar *log_domain,
domain = g_log_domain_new (log_domain);
handler = g_new (GLogHandler, 1);
g_mutex_lock (g_messages_lock);
handler->id = ++handler_id;
g_mutex_unlock (g_messages_lock);
handler->log_level = log_levels;
handler->log_func = log_func;
handler->data = user_data;
@ -311,19 +335,25 @@ g_logv (const gchar *log_domain,
test_level = 1 << i;
if (log_level & test_level)
{
static guint g_log_depth = 0;
guint depth = GPOINTER_TO_UINT (g_private_get (g_log_depth));
GLogDomain *domain;
GLogFunc log_func;
gpointer data = NULL;
domain = g_log_find_domain (log_domain ? log_domain : "");
if (g_log_depth++)
if (depth)
test_level |= G_LOG_FLAG_RECURSION;
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) | g_log_always_fatal) &
test_level) != 0)
test_level |= G_LOG_FLAG_FATAL;
depth++;
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
g_mutex_lock (g_messages_lock);
if ((((domain ? domain->fatal_mask : G_LOG_FATAL_MASK) |
g_log_always_fatal) & test_level) != 0)
test_level |= G_LOG_FLAG_FATAL;
g_mutex_unlock (g_messages_lock);
log_func = g_log_domain_get_handler (domain, test_level, &data);
log_func (log_domain, test_level, buffer, data);
@ -332,7 +362,8 @@ g_logv (const gchar *log_domain,
if (test_level & G_LOG_FLAG_FATAL)
abort ();
g_log_depth--;
depth--;
g_private_set (g_log_depth, GUINT_TO_POINTER (depth));
}
}
}
@ -362,8 +393,11 @@ g_log_default_handler (const gchar *log_domain,
gint fd;
#endif
gboolean in_recursion;
gboolean is_fatal;
gboolean is_fatal;
GErrorFunc local_glib_error_func;
GWarningFunc local_glib_warning_func;
GPrintFunc local_glib_message_func;
in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
log_level &= G_LOG_LEVEL_MASK;
@ -380,13 +414,19 @@ g_log_default_handler (const gchar *log_domain,
fd = (log_level >= G_LOG_LEVEL_MESSAGE) ? 1 : 2;
#endif
g_mutex_lock (g_messages_lock);
local_glib_error_func = glib_error_func;
local_glib_warning_func = glib_warning_func;
local_glib_message_func = glib_message_func;
g_mutex_unlock (g_messages_lock);
switch (log_level)
{
case G_LOG_LEVEL_ERROR:
if (!log_domain && glib_error_func)
if (!log_domain && local_glib_error_func)
{
/* compatibility code */
glib_error_func (message);
local_glib_error_func (message);
return;
}
/* use write(2) for output, in case we are out of memeory */
@ -428,10 +468,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_WARNING:
if (!log_domain && glib_warning_func)
if (!log_domain && local_glib_warning_func)
{
/* compatibility code */
glib_warning_func (message);
local_glib_warning_func (message);
return;
}
if (log_domain)
@ -453,10 +493,10 @@ g_log_default_handler (const gchar *log_domain,
write (fd, "\n", 1);
break;
case G_LOG_LEVEL_MESSAGE:
if (!log_domain && glib_message_func)
if (!log_domain && local_glib_message_func)
{
/* compatibility code */
glib_message_func (message);
local_glib_message_func (message);
return;
}
if (log_domain)
@ -553,8 +593,10 @@ g_set_print_handler (GPrintFunc func)
{
GPrintFunc old_print_func;
g_mutex_lock (g_messages_lock);
old_print_func = glib_print_func;
glib_print_func = func;
g_mutex_unlock (g_messages_lock);
return old_print_func;
}
@ -565,6 +607,7 @@ g_print (const gchar *format,
{
va_list args;
gchar *string;
GPrintFunc local_glib_print_func;
g_return_if_fail (format != NULL);
@ -572,8 +615,12 @@ g_print (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
if (glib_print_func)
glib_print_func (string);
g_mutex_lock (g_messages_lock);
local_glib_print_func = glib_print_func;
g_mutex_unlock (g_messages_lock);
if (local_glib_print_func)
local_glib_print_func (string);
else
{
fputs (string, stdout);
@ -587,8 +634,10 @@ g_set_printerr_handler (GPrintFunc func)
{
GPrintFunc old_printerr_func;
g_mutex_lock (g_messages_lock);
old_printerr_func = glib_printerr_func;
glib_printerr_func = func;
g_mutex_unlock (g_messages_lock);
return old_printerr_func;
}
@ -599,6 +648,7 @@ g_printerr (const gchar *format,
{
va_list args;
gchar *string;
GPrintFunc local_glib_printerr_func;
g_return_if_fail (format != NULL);
@ -606,8 +656,12 @@ g_printerr (const gchar *format,
string = g_strdup_vprintf (format, args);
va_end (args);
if (glib_printerr_func)
glib_printerr_func (string);
g_mutex_lock (g_messages_lock);
local_glib_printerr_func = glib_printerr_func;
g_mutex_unlock (g_messages_lock);
if (local_glib_printerr_func)
local_glib_printerr_func (string);
else
{
fputs (string, stderr);
@ -622,9 +676,11 @@ g_set_error_handler (GErrorFunc func)
{
GErrorFunc old_error_func;
g_mutex_lock (g_messages_lock);
old_error_func = glib_error_func;
glib_error_func = func;
g_mutex_unlock (g_messages_lock);
return old_error_func;
}
@ -634,8 +690,10 @@ g_set_warning_handler (GWarningFunc func)
{
GWarningFunc old_warning_func;
g_mutex_lock (g_messages_lock);
old_warning_func = glib_warning_func;
glib_warning_func = func;
g_mutex_unlock (g_messages_lock);
return old_warning_func;
}
@ -646,8 +704,17 @@ g_set_message_handler (GPrintFunc func)
{
GPrintFunc old_message_func;
g_mutex_lock (g_messages_lock);
old_message_func = glib_message_func;
glib_message_func = func;
g_mutex_unlock (g_messages_lock);
return old_message_func;
}
void
g_messages_init (void)
{
g_messages_lock = g_mutex_new();
g_log_depth = g_private_new(NULL);
}

View File

@ -1,3 +1,8 @@
1998-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gmodule.c: Made it MT safe, the g_module_error() is now thread
specific.
Fri Nov 20 14:43:44 1998 Tim Janik <timj@gtk.org>
* gmodule.c (_g_module_build_path): added empty default imlementation

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <dlfcn.h>
/* Perl includes <nlist.h> and <link.h> instead of <dlfcn.h> on some systmes? */

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <dl.h>

View File

@ -17,6 +17,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <stdio.h>
#include <windows.h>

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "gmodule.h"
#include "gmoduleconf.h"
#include <errno.h>
@ -59,10 +64,11 @@ static inline GModule* g_module_find_by_name (const gchar *name);
/* --- variables --- */
const char *g_log_domain_gmodule = "GModule";
static GModule *modules = NULL;
static GModule *main_module = NULL;
static gchar *module_error = NULL;
static G_LOCK_DEFINE (g_module_global);
const char *g_log_domain_gmodule = "GModule";
static GModule *modules = NULL;
static GModule *main_module = NULL;
static GStaticPrivate module_error_private = G_STATIC_PRIVATE_INIT;
/* --- inline functions --- */
@ -70,30 +76,45 @@ static inline GModule*
g_module_find_by_handle (gpointer handle)
{
GModule *module;
GModule *retval = NULL;
g_lock (g_module_global);
if (main_module && main_module->handle == handle)
return main_module;
for (module = modules; module; module = module->next)
if (handle == module->handle)
return module;
return NULL;
retval = main_module;
else
for (module = modules; module; module = module->next)
if (handle == module->handle)
{
retval = module;
break;
}
g_unlock (g_module_global);
return retval;
}
static inline GModule*
g_module_find_by_name (const gchar *name)
{
GModule *module;
GModule *retval = NULL;
g_lock (g_module_global);
for (module = modules; module; module = module->next)
if (strcmp (name, module->file_name) == 0)
return module;
return NULL;
{
retval = module;
break;
}
g_unlock (g_module_global);
return retval;
}
static inline void
g_module_set_error (const gchar *error)
{
gchar* module_error = g_static_private_get (&module_error_private);
if (module_error)
g_free (module_error);
if (error)
@ -101,6 +122,7 @@ g_module_set_error (const gchar *error)
else
module_error = NULL;
errno = 0;
g_static_private_set (&module_error_private, module_error, g_free);
}
@ -175,7 +197,8 @@ g_module_open (const gchar *file_name,
CHECK_ERROR (NULL);
if (!file_name)
{
{
g_lock (g_module_global);
if (!main_module)
{
handle = _g_module_self ();
@ -190,7 +213,8 @@ g_module_open (const gchar *file_name,
main_module->next = NULL;
}
}
g_unlock (g_module_global);
return main_module;
}
@ -222,8 +246,8 @@ g_module_open (const gchar *file_name,
return module;
}
saved_error = module_error;
module_error = NULL;
saved_error = g_module_error();
g_static_private_set (&module_error_private, NULL, NULL);
g_module_set_error (NULL);
module = g_new (GModule, 1);
@ -232,8 +256,10 @@ g_module_open (const gchar *file_name,
module->ref_count = 1;
module->is_resident = FALSE;
module->unload = NULL;
g_lock (g_module_global);
module->next = modules;
modules = module;
g_unlock (g_module_global);
/* check initialization */
if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
@ -286,6 +312,8 @@ g_module_close (GModule *module)
GModule *node;
last = NULL;
g_lock (g_module_global);
node = modules;
while (node)
{
@ -301,6 +329,7 @@ g_module_close (GModule *module)
node = last->next;
}
module->next = NULL;
g_unlock (g_module_global);
_g_module_close (module->handle, FALSE);
g_free (module->file_name);
@ -308,7 +337,7 @@ g_module_close (GModule *module)
g_free (module);
}
return module_error == NULL;
return g_module_error() == NULL;
}
void
@ -322,7 +351,7 @@ g_module_make_resident (GModule *module)
gchar*
g_module_error (void)
{
return module_error;
return g_static_private_get (&module_error_private);
}
gboolean
@ -330,6 +359,7 @@ g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer *symbol)
{
gchar *module_error;
if (symbol)
*symbol = NULL;
CHECK_ERROR (FALSE);
@ -350,7 +380,7 @@ g_module_symbol (GModule *module,
*symbol = _g_module_symbol (module->handle, symbol_name);
#endif /* !G_MODULE_NEED_USCORE */
if (module_error)
if ((module_error = g_module_error()))
{
gchar *error;

176
gmutex.c Normal file
View File

@ -0,0 +1,176 @@
/* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
#include "glib.h"
typedef struct _GStaticPrivateNode GStaticPrivateNode;
struct _GStaticPrivateNode {
gpointer data;
GDestroyNotify destroy;
};
static void g_static_private_free_data (gpointer data);
static void g_thread_fail (void);
/* Global variables */
gboolean g_thread_use_default_impl = TRUE;
gboolean g_thread_supported = FALSE;
GThreadFunctions 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 */
};
/* Local data */
static GMutex *g_mutex_protect_static_mutex_allocation = NULL;
static GMutex *g_thread_specific_mutex = NULL;
static GPrivate *g_thread_specific_private = NULL;
/* This must be called only once, before any threads are created.
* It will only be called from g_thread_init() in -lgthread.
*/
void
g_mutex_init (void)
{
/* We let the main thread (the one that calls g_thread_init) inherit
the data, that it set before calling g_thread_init */
gpointer private_old = g_thread_specific_private;
g_thread_specific_private = g_private_new (g_static_private_free_data);
/* we can not use g_private_set here, as g_thread_supported is not
yet set TRUE, whereas the private_set function is already set. */
g_thread_functions_for_glib_use.private_set (g_thread_specific_private,
private_old);
g_mutex_protect_static_mutex_allocation = g_mutex_new();
g_thread_specific_mutex = g_mutex_new();
}
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;
}
gpointer
g_static_private_get (GStaticPrivate *private)
{
GArray *array;
array = g_private_get (g_thread_specific_private);
if (!array)
return NULL;
if (!private->index)
return NULL;
else if (private->index <= array->len)
return g_array_index (array, GStaticPrivateNode, (private->index - 1)).data;
else
return NULL;
}
void
g_static_private_set (GStaticPrivate *private,
gpointer data,
GDestroyNotify notify)
{
GArray *array;
static guint next_index = 0;
array = g_private_get (g_thread_specific_private);
if (!array)
{
array = g_array_new (FALSE, FALSE, sizeof(GStaticPrivateNode));
g_private_set (g_thread_specific_private, array);
}
if (!private->index)
{
g_mutex_lock (g_thread_specific_mutex);
if (!private->index)
private->index = ++next_index;
g_mutex_unlock (g_thread_specific_mutex);
}
if (private->index > array->len)
g_array_set_size (array, private->index);
g_array_index (array, GStaticPrivateNode, (private->index - 1)).data = data;
g_array_index (array, GStaticPrivateNode, (private->index - 1)).destroy = notify;
}
static void
g_static_private_free_data (gpointer data)
{
if (data)
{
GArray* array = data;
guint i;
for (i = 0; i < array->len; i++ )
{
GStaticPrivateNode *node = &g_array_index (array, GStaticPrivateNode, i);
if (node->data && node->destroy)
node->destroy (node->data);
}
}
}
static void
g_thread_fail (void)
{
g_error ("The thread system is not yet initialized.");
}

36
gnode.c
View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
/* node allocation
@ -34,10 +39,12 @@ struct _GAllocator /* from gmem.c */
GNode *free_nodes; /* implementation specific */
};
static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
void
g_node_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_node_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -62,13 +69,22 @@ g_node_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
}
void
g_node_push_allocator (GAllocator *allocator)
{
g_node_validate_allocator ( allocator );
g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
g_unlock (current_allocator);
}
void
g_node_pop_allocator (void)
{
g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@ -78,6 +94,7 @@ g_node_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
@ -87,9 +104,15 @@ g_node_new (gpointer data)
{
GNode *node;
g_lock (current_allocator);
if (!current_allocator)
g_node_push_allocator (g_allocator_new ("GLib default GNode allocator", 1024));
{
GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
1024);
g_node_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_nodes)
node = g_chunk_new (GNode, current_allocator->mem_chunk);
else
@ -97,6 +120,7 @@ g_node_new (gpointer data)
node = current_allocator->free_nodes;
current_allocator->free_nodes = node->next;
}
g_unlock (current_allocator);
node->data = data;
node->next = NULL;
@ -122,9 +146,11 @@ g_nodes_free (GNode *node)
else
break;
}
g_lock (current_allocator);
parent->next = current_allocator->free_nodes;
current_allocator->free_nodes = node;
g_unlock (current_allocator);
}
void

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
static const guint g_primes[] =

5
grel.c
View File

@ -15,6 +15,11 @@
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* MT safe
*/
#include "glib.h"
#include <stdarg.h>
#include <string.h>

View File

@ -19,6 +19,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#define __gscanner_c__
#ifdef HAVE_CONFIG_H

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
@ -30,10 +35,12 @@ struct _GAllocator /* from gmem.c */
GSList *free_lists; /* implementation specific */
};
static G_LOCK_DEFINE(current_allocator);
static GAllocator *current_allocator = NULL;
void
g_slist_push_allocator (GAllocator *allocator)
/* HOLDS: current_allocator_lock */
static void
g_slist_validate_allocator (GAllocator *allocator)
{
g_return_if_fail (allocator != NULL);
g_return_if_fail (allocator->is_unused == TRUE);
@ -58,13 +65,22 @@ g_slist_push_allocator (GAllocator *allocator)
}
allocator->is_unused = FALSE;
}
void
g_slist_push_allocator (GAllocator *allocator)
{
g_slist_validate_allocator (allocator);
g_lock (current_allocator);
allocator->last = current_allocator;
current_allocator = allocator;
g_unlock (current_allocator);
}
void
g_slist_pop_allocator (void)
{
g_lock (current_allocator);
if (current_allocator)
{
GAllocator *allocator;
@ -74,6 +90,7 @@ g_slist_pop_allocator (void)
allocator->last = NULL;
allocator->is_unused = TRUE;
}
g_unlock (current_allocator);
}
GSList*
@ -81,9 +98,15 @@ g_slist_alloc (void)
{
GSList *list;
g_lock (current_allocator);
if (!current_allocator)
g_slist_push_allocator (g_allocator_new ("GLib default GSList allocator", 1024));
{
GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
1024);
g_slist_validate_allocator (allocator);
allocator->last = NULL;
current_allocator = allocator;
}
if (!current_allocator->free_lists)
{
list = g_chunk_new (GSList, current_allocator->mem_chunk);
@ -103,6 +126,8 @@ g_slist_alloc (void)
current_allocator->free_lists = list->next;
}
}
g_unlock (current_allocator);
list->next = NULL;
return list;
@ -114,8 +139,10 @@ g_slist_free (GSList *list)
if (list)
{
list->data = list->next;
g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
g_unlock (current_allocator);
}
}
@ -125,8 +152,10 @@ g_slist_free_1 (GSList *list)
if (list)
{
list->data = NULL;
g_lock (current_allocator);
list->next = current_allocator->free_lists;
current_allocator->free_lists = list;
g_unlock (current_allocator);
}
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -208,7 +212,8 @@ g_strtod (const gchar *nptr,
gchar*
g_strerror (gint errnum)
{
static char msg[64];
static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
char *msg;
#ifdef HAVE_STRERROR
return strerror (errnum);
@ -634,7 +639,14 @@ g_strerror (gint errnum)
if ((errnum > 0) && (errnum <= sys_nerr))
return sys_errlist [errnum];
#endif /* NO_SYS_ERRLIST */
msg = g_static_private_get (&msg_private);
if( !msg )
{
msg = g_new( gchar, 64 );
g_static_private_set (&msg_private, msg, g_free);
}
sprintf (msg, "unknown error (%d)", errnum);
return msg;
}
@ -642,7 +654,8 @@ g_strerror (gint errnum)
gchar*
g_strsignal (gint signum)
{
static char msg[64];
static GStaticPrivate msg_private = G_STATIC_PRIVATE_INIT;
char *msg;
#ifdef HAVE_STRSIGNAL
extern char *strsignal (int sig);
@ -748,6 +761,13 @@ g_strsignal (gint signum)
extern char *sys_siglist[];
return sys_siglist [signum];
#endif /* NO_SYS_SIGLIST */
msg = g_static_private_get (&msg_private);
if( !msg )
{
msg = g_new( gchar, 64 );
g_static_private_set (&msg_private, msg, g_free);
}
sprintf (msg, "unknown signal (%d)", signum);
return msg;

View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
@ -43,7 +48,7 @@ struct _GRealString
gint alloc;
};
static G_LOCK_DEFINE(string_mem_chunk);
static GMemChunk *string_mem_chunk = NULL;
/* Hash Functions.
@ -202,12 +207,14 @@ g_string_sized_new (guint dfl_size)
{
GRealString *string;
g_lock (string_mem_chunk);
if (!string_mem_chunk)
string_mem_chunk = g_mem_chunk_new ("string mem chunk",
sizeof (GRealString),
1024, G_ALLOC_AND_FREE);
string = g_chunk_new (GRealString, string_mem_chunk);
g_unlock (string_mem_chunk);
string->alloc = 0;
string->len = 0;
@ -241,7 +248,9 @@ g_string_free (GString *string,
if (free_segment)
g_free (string->str);
g_lock (string_mem_chunk);
g_mem_chunk_free (string_mem_chunk, string);
g_unlock (string_mem_chunk);
}
GString*

8
gthread/.cvsignore Normal file
View File

@ -0,0 +1,8 @@
Makefile.in
Makefile
.deps
*.lo
*.o
.libs
*.la
testgthread

21
gthread/Makefile.am Normal file
View File

@ -0,0 +1,21 @@
## Process this file with automake to produce Makefile.in
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gthread -DG_LOG_DOMAIN=g_log_domain_gthread
EXTRA_DIST = \
gthread-posix.c
libglib = $(top_builddir)/libglib.la # -lglib
lib_LTLIBRARIES = libgthread.la
libgthread_la_SOURCES = gthread.c
libgthread_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
-release $(LT_RELEASE)
libgthread_la_LIBADD = \
@G_THREAD_LIBS@
noinst_PROGRAMS = testgthread
testgthread_LDADD = ../libglib.la libgthread.la

28
gthread/gthread-none.c Normal file
View File

@ -0,0 +1,28 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* gthread.c: fallback 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
static GThreadFunctions
g_mutex_functions_for_glib_use_default; /* is NULLified */

218
gthread/gthread-nspr.c Normal file
View File

@ -0,0 +1,218 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* gthread.c: nspr 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
#include <prpdce.h>
#include <prthread.h>
#include <stdlib.h>
#ifdef G_DISABLE_ASSERT
#define STDERR_ASSERT(expr)
#else /* G_DISABLE_ASSERT */
#define STDERR_ASSERT(expr) G_STMT_START{ \
if (!(expr)) \
g_log (G_LOG_DOMAIN, \
G_LOG_LEVEL_ERROR, \
"file %s: line %d: assertion failed: (%s)", \
__FILE__, \
__LINE__, \
#expr); }G_STMT_END
#endif /* G_DISABLE_ASSERT */
/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
functions from gmem.c and gmessages.c; */
static gboolean
g_mutex_trylock_nspr_impl (GMutex * mutex)
{
PRStatus status = PRP_TryLock ((PRLock *) mutex);
if (status == PR_SUCCESS)
{
return TRUE;
}
return FALSE;
}
static void
g_cond_wait_nspr_impl (GCond * cond,
GMutex * entered_mutex)
{
PRStatus status = PRP_NakedWait ((PRCondVar *) cond,
(PRLock *) entered_mutex,
PR_INTERVAL_NO_TIMEOUT);
g_assert (status == PR_SUCCESS);
}
#define G_MICROSEC 1000000
static gboolean
g_cond_timed_wait_nspr_impl (GCond * cond,
GMutex * entered_mutex,
GTimeVal * abs_time)
{
PRStatus status;
PRIntervalTime interval;
GTimeVal current_time;
glong microsecs;
g_return_val_if_fail (cond != NULL, FALSE);
g_return_val_if_fail (entered_mutex != NULL, FALSE);
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))
return FALSE;
interval = PR_SecondsToInterval (abs_time->tv_sec - current_time.tv_sec);
microsecs = abs_time->tv_usec - current_time.tv_usec;
if (microsecs < 0)
interval -= PR_MicrosecondsToInterval (-microsecs);
else
interval += PR_MicrosecondsToInterval (microsecs);
status = PRP_NakedWait ((PRCondVar *) cond, (PRLock *) entered_mutex,
interval);
g_assert (status == PR_SUCCESS);
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))
return FALSE;
return TRUE;
}
typedef struct _GPrivateNSPRData GPrivateNSPRData;
struct _GPrivateNSPRData
{
gpointer data;
GDestroyNotify destructor;
};
typedef struct _GPrivateNSPR GPrivateNSPR;
struct _GPrivateNSPR
{
PRUintn private;
GDestroyNotify destructor;
};
static GPrivateNSPRData *
g_private_nspr_data_constructor (GDestroyNotify destructor, gpointer data)
{
/* we can not use g_new and friends, as they might use private data by
themself */
GPrivateNSPRData *private = malloc (sizeof (GPrivateNSPRData));
g_assert (private);
private->data = data;
private->destructor = destructor;
return private;
}
static void
g_private_nspr_data_destructor (gpointer data)
{
GPrivateNSPRData *private = data;
if (private->destructor && private->data)
(*private->destructor) (private->data);
free (private);
}
static GPrivate *
g_private_new_nspr_impl (GDestroyNotify destructor)
{
GPrivateNSPR *result = g_new (GPrivateNSPR, 1);
PRStatus status = PR_NewThreadPrivateIndex (&result->private,
g_private_nspr_data_destructor);
g_assert (status == PR_SUCCESS);
result->destructor = destructor;
return (GPrivate *) result;
}
/* NOTE: the functions g_private_get and g_private_set may not use
functions from gmem.c and gmessages.c */
static GPrivateNSPRData *
g_private_nspr_data_get (GPrivateNSPR * private)
{
GPrivateNSPRData *data;
STDERR_ASSERT (private);
data = PR_GetThreadPrivate (private->private);
if (!data)
{
data = g_private_nspr_data_constructor (private->destructor, NULL);
STDERR_ASSERT (PR_SetThreadPrivate (private->private, data)
== PR_SUCCESS);
}
return data;
}
static void
g_private_set_nspr_impl (GPrivate * private, gpointer value)
{
if (!private)
return;
g_private_nspr_data_get ((GPrivateNSPR *) private)->data = value;
}
static gpointer
g_private_get_nspr_impl (GPrivate * private)
{
if (!private)
return NULL;
return g_private_nspr_data_get ((GPrivateNSPR *) private)->data;
}
static GThreadFunctions g_thread_functions_for_glib_use_default =
{
(GMutex * (*)())PR_NewLock,
(void (*)(GMutex *)) PR_Lock,
g_mutex_trylock_nspr_impl,
(void (*)(GMutex *)) PR_Unlock,
(void (*)(GMutex *)) PR_DestroyLock,
(GCond * (*)())PRP_NewNakedCondVar,
(void (*)(GCond *)) PRP_NakedNotify,
(void (*)(GCond *)) PRP_NakedBroadcast,
g_cond_wait_nspr_impl,
g_cond_timed_wait_nspr_impl,
(void (*)(GCond *)) PRP_DestroyNakedCondVar,
g_private_new_nspr_impl,
g_private_get_nspr_impl,
g_private_set_nspr_impl
};

176
gthread/gthread-posix.c Normal file
View File

@ -0,0 +1,176 @@
/* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/time.h>
#define posix_print_error( name, num ) \
g_error( "file %s: line %d (%s): error %s during %s", \
__FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION, \
g_strerror((num)), #name )
#define posix_check_for_error( what ) G_STMT_START{ \
int error = (what); \
if( error ) { posix_print_error( what, error ); } \
}G_STMT_END
static GMutex *
g_mutex_new_posix_impl (void)
{
GMutex *result = (GMutex *) g_new (pthread_mutex_t, 1);
posix_check_for_error (pthread_mutex_init ((pthread_mutex_t *) result, NULL));
return result;
}
static void
g_mutex_free_posix_impl (GMutex * mutex)
{
posix_check_for_error (pthread_mutex_destroy ((pthread_mutex_t *) mutex));
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_for_error (result);
return TRUE;
}
static GCond *
g_cond_new_posix_impl (void)
{
GCond *result = (GCond *) g_new (pthread_cond_t, 1);
posix_check_for_error (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
therfore. */
#define G_MICROSEC 1000000
#define G_NANOSEC 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)
{
g_cond_wait (cond, entered_mutex);
return TRUE;
}
end_time.tv_sec = abs_time->tv_sec;
end_time.tv_nsec = abs_time->tv_usec * (G_NANOSEC / G_MICROSEC);
g_assert (end_time.tv_nsec < G_NANOSEC);
result = pthread_cond_timedwait ((pthread_cond_t *) cond,
(pthread_mutex_t *) entered_mutex,
&end_time);
timed_out = (result == ETIMEDOUT);
if (!timed_out)
posix_check_for_error (result);
return !timed_out;
}
static void
g_cond_free_posix_impl (GCond * cond)
{
posix_check_for_error (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_for_error (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, gpointer value)
{
if (!private)
return;
pthread_setspecific (*(pthread_key_t *) private, value);
}
static gpointer
g_private_get_posix_impl (GPrivate * private)
{
if (!private)
return NULL;
return pthread_getspecific (*(pthread_key_t *) private);
}
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
};

177
gthread/gthread-solaris.c Normal file
View File

@ -0,0 +1,177 @@
/* 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 Sebastian Wilhelmi; University of Karlsruhe
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
#include <thread.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#define solaris_print_error( name, num ) \
g_error( "file %s: line %d (%s): error %s during %s", \
__FILE__, __LINE__, G_GNUC_PRETTY_FUNCTION, \
g_strerror((num)), #name )
#define solaris_check_for_error( what ) G_STMT_START{ \
int error = (what); \
if( error ) { solaris_print_error( what, error ); } \
}G_STMT_END
static GMutex *
g_mutex_new_solaris_impl (void)
{
GMutex *result = (GMutex *) g_new (mutex_t, 1);
solaris_check_for_error (mutex_init ((mutex_t *) result, USYNC_PROCESS, 0));
return result;
}
static void
g_mutex_free_solaris_impl (GMutex * mutex)
{
solaris_check_for_error (mutex_destroy ((mutex_t *) mutex));
free (mutex);
}
/* NOTE: the functions g_mutex_lock and g_mutex_unlock may not use
functions from gmem.c and gmessages.c; */
/* mutex_lock, 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_solaris_impl (GMutex * mutex)
{
int result;
result = mutex_trylock ((mutex_t *) mutex);
if (result == EBUSY)
return FALSE;
solaris_check_for_error (result);
return TRUE;
}
static GCond *
g_cond_new_solaris_impl ()
{
GCond *result = (GCond *) g_new (cond_t, 1);
solaris_check_for_error (cond_init ((cond_t *) result, USYNC_THREAD, 0));
return result;
}
/* cond_signal, cond_broadcast and cond_wait
can be taken directly, as signature and semantic are right, but
without error check then!!!!, we might want to change this
therfore. */
#define G_MICROSEC 1000000
#define G_NANOSEC 1000000000
static gboolean
g_cond_timed_wait_solaris_impl (GCond * cond,
GMutex * entered_mutex,
GTimeVal * abs_time)
{
int result;
timestruc_t 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)
{
g_cond_wait (cond, entered_mutex);
return TRUE;
}
end_time.tv_sec = abs_time->tv_sec;
end_time.tv_nsec = abs_time->tv_usec * (G_NANOSEC / G_MICROSEC);
g_assert (end_time.tv_nsec < G_NANOSEC);
result = cond_timedwait ((cond_t *) cond, (mutex_t *) entered_mutex,
&end_time);
timed_out = (result == ETIME);
if (!timed_out)
solaris_check_for_error (result);
return !timed_out;
}
static void
g_cond_free_solaris_impl (GCond * cond)
{
solaris_check_for_error (cond_destroy ((cond_t *) cond));
g_free (cond);
}
static GPrivate *
g_private_new_solaris_impl (GDestroyNotify destructor)
{
GPrivate *result = (GPrivate *) g_new (thread_key_t,1);
solaris_check_for_error (thr_keycreate ((thread_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_solaris_impl (GPrivate * private, gpointer value)
{
if (!private)
return;
thr_setspecific (*(thread_key_t *) private, value);
}
static gpointer
g_private_get_solaris_impl (GPrivate * private)
{
gpointer result;
if (!private)
return NULL;
thr_getspecific (*(thread_key_t *) private, &result);
return result;
}
static GThreadFunctions g_thread_functions_for_glib_use_default =
{
g_mutex_new_solaris_impl,
(void (*)(GMutex *)) mutex_lock,
g_mutex_trylock_solaris_impl,
(void (*)(GMutex *)) mutex_unlock,
g_mutex_free_solaris_impl,
g_cond_new_solaris_impl,
(void (*)(GCond *)) cond_signal,
(void (*)(GCond *)) cond_broadcast,
(void (*)(GCond *, GMutex *)) cond_wait,
g_cond_timed_wait_solaris_impl,
g_cond_free_solaris_impl,
g_private_new_solaris_impl,
g_private_get_solaris_impl,
g_private_set_solaris_impl
};

101
gthread/gthread.c Normal file
View File

@ -0,0 +1,101 @@
/* GLIB - Library of useful routines for C programming
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* gthread.c: thread related functions
* 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 Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library 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.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib.h>
static const char *g_log_domain_gthread = "GThread";
static gboolean thread_system_already_initialized = FALSE;
#include G_THREAD_SOURCE
void g_mutex_init (void);
void g_mem_init (void);
void g_messages_init (void);
void
g_thread_init(GThreadFunctions* init)
{
gboolean supported;
if (thread_system_already_initialized)
g_error ("the glib thread system may only be initialized once.");
thread_system_already_initialized = TRUE;
if (init == NULL)
init = &g_thread_functions_for_glib_use_default;
else
g_thread_use_default_impl = FALSE;
g_thread_functions_for_glib_use = *init;
/* It is important, that g_thread_supported is not set before the
thread initialization functions of the different modules are
called */
supported =
init->mutex_new &&
init->mutex_lock &&
init->mutex_trylock &&
init->mutex_unlock &&
init->mutex_free &&
init->cond_new &&
init->cond_signal &&
init->cond_broadcast &&
init->cond_wait &&
init->cond_timed_wait &&
init->cond_free &&
init->private_new &&
init->private_get &&
init->private_get;
/* if somebody is calling g_thread_init (), it means that he wants to
have thread support, so check this */
if (!supported)
{
if (g_thread_use_default_impl)
g_error ("Threads are not supported on this platform.");
else
g_error ("The supplied thread function vector is invalid.");
}
/* now call the thread initialization functions of the different
glib modules. BTW: order does matter, g_mutex_init MUST be first */
g_mutex_init ();
g_mem_init ();
g_messages_init ();
/* now we can set g_thread_supported and thus enable all the thread
functions */
g_thread_supported = TRUE;
}

200
gthread/testgthread.c Normal file
View File

@ -0,0 +1,200 @@
#include <stdlib.h>
#define main testglib_main
#include <testglib.c>
#undef main
#define TEST_PRIVATE_THREADS 9
#define TEST_PRIVATE_ROUNDS 5
void
test_mutexes ()
{
GMutex *mutex = NULL;
GCond *cond = NULL;
GStaticMutex static_mutex = G_STATIC_MUTEX_INIT;
G_LOCK_DEFINE (test_me);
if (g_thread_supported)
{
mutex = g_mutex_new ();
cond = g_cond_new ();
}
g_mutex_lock (mutex);
g_mutex_unlock (mutex);
g_static_mutex_lock (static_mutex);
g_static_mutex_unlock (static_mutex);
g_cond_signal (cond);
g_cond_broadcast (cond);
g_lock (test_me);
g_unlock (test_me);
if (g_thread_supported)
{
g_cond_free (cond);
g_mutex_free (mutex);
}
}
#if defined(NSPR) /* we are using nspr threads */
/* this option must be specified by hand during compile of
testgthread. also note, that you have to link with whatever library
nspr is building upon, it might otherwise (as on solaris) lead to
run time failure, as the mutex functions are defined in libc, but
as noops, that will make some nspr assertions fail. */
#include <prthread.h>
gpointer
new_thread (GHookFunc func, gpointer data)
{
PRThread *thread = PR_CreateThread (PR_SYSTEM_THREAD, func, data,
PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
PR_JOINABLE_THREAD, 0);
return thread;
}
#define join_thread(thread) PR_JoinThread (thread)
#define self_thread() PR_GetCurrentThread ()
#elif defined(DEFAULTMUTEX) /* we are using solaris threads */
gpointer
new_thread (GHookFunc func, gpointer data)
{
thread_t thread;
thr_create (NULL, 0, (void *(*)(void *)) func, data, THR_BOUND, &thread);
return GUINT_TO_POINTER (thread);
}
#define join_thread(thread) \
thr_join ((thread_t)GPOINTER_TO_UINT (thread), NULL, NULL)
#define self_thread() GUINT_TO_POINTER (thr_self ())
#elif defined(PTHREAD_MUTEX_INITIALIZER) /* we are using posix threads */
gpointer
new_thread(GHookFunc func, gpointer data)
{
pthread_t thread;
pthread_attr_t pthread_attr;
pthread_attr_init (&pthread_attr);
pthread_attr_setdetachstate (&pthread_attr, PTHREAD_CREATE_JOINABLE);
pthread_create (&thread, &pthread_attr, (void *(*)(void *)) func, data);
return GUINT_TO_POINTER (thread);
}
#define join_thread(thread) \
pthread_join ((pthread_t)GPOINTER_TO_UINT (thread), NULL)
#define self_thread() GUINT_TO_POINTER (pthread_self ())
#else /* we are not having a thread implementation, do nothing */
#define new_thread(func,data) (NULL)
#define join_thread(thread) ((void)0)
#define self_thread() NULL
#endif
#define G_MICROSEC 1000000
void
wait_thread (double seconds)
{
GMutex *mutex;
GCond *cond;
GTimeVal current_time;
g_get_current_time (&current_time);
mutex = g_mutex_new ();
cond = g_cond_new ();
current_time.tv_sec += (guint) seconds;
seconds -= (guint) seconds;
current_time.tv_usec += (guint) (seconds * G_MICROSEC);
while (current_time.tv_usec >= G_MICROSEC)
{
current_time.tv_usec -= G_MICROSEC;
current_time.tv_sec++;
}
g_mutex_lock (mutex);
g_cond_timed_wait (cond, mutex, &current_time);
g_mutex_unlock (mutex);
g_mutex_free (mutex);
g_cond_free (cond);
}
gpointer
private_constructor ()
{
gpointer *result = g_new (gpointer, 2);
result[0] = 0;
result[1] = self_thread ();
g_print ("allocating data for the thread %p.\n", result[1]);
return result;
}
void
private_destructor (gpointer data)
{
gpointer *real = data;
g_print ("freeing data for the thread %p.\n", real[1]);
g_free (real);
}
GStaticPrivate private;
void
test_private_func (void *data)
{
guint i = 0;
wait_thread (1);
while (i < TEST_PRIVATE_ROUNDS)
{
guint random_value = rand () % 10000;
guint *data = g_static_private_get (&private);
if (!data)
{
data = private_constructor ();
g_static_private_set (&private, data, private_destructor);
}
*data = random_value;
wait_thread (.2);
g_assert (*(guint *) g_static_private_get (&private) == random_value);
i++;
}
}
void
test_private ()
{
int i;
gpointer threads[TEST_PRIVATE_THREADS];
for (i = 0; i < TEST_PRIVATE_THREADS; i++)
{
threads[i] = new_thread (test_private_func, (gpointer) i);
}
for (i = 0; i < TEST_PRIVATE_THREADS; i++)
{
join_thread (threads[i]);
}
g_print ("\n");
}
int
main ()
{
test_mutexes ();
g_thread_init (NULL);
test_mutexes ();
test_private ();
/* later we might want to start n copies of that */
testglib_main (0, NULL);
return 0;
}

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

18
gtree.c
View File

@ -16,6 +16,11 @@
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe
*/
#include "glib.h"
@ -78,6 +83,7 @@ static GTreeNode* g_tree_node_rotate_right (GTreeNode *node);
static void g_tree_node_check (GTreeNode *node);
static G_LOCK_DEFINE(g_tree_global);
static GMemChunk *node_mem_chunk = NULL;
static GTreeNode *node_free_list = NULL;
@ -88,6 +94,7 @@ g_tree_node_new (gpointer key,
{
GTreeNode *node;
g_lock (g_tree_global);
if (node_free_list)
{
node = node_free_list;
@ -102,7 +109,8 @@ g_tree_node_new (gpointer key,
G_ALLOC_ONLY);
node = g_chunk_new (GTreeNode, node_mem_chunk);
}
}
g_unlock (g_tree_global);
node->balance = 0;
node->left = NULL;
@ -120,9 +128,11 @@ g_tree_node_destroy (GTreeNode *node)
{
g_tree_node_destroy (node->right);
g_tree_node_destroy (node->left);
g_lock (g_tree_global);
node->right = node_free_list;
node_free_list = node;
}
g_unlock (g_tree_global);
}
}
@ -375,9 +385,11 @@ g_tree_node_remove (GTreeNode *node,
node = g_tree_node_restore_right_balance (new_root, old_balance);
}
g_lock (g_tree_global);
garbage->right = node_free_list;
node_free_list = garbage;
}
g_unlock (g_tree_global);
}
else if (cmp < 0)
{
if (node->left)

View File

@ -17,6 +17,10 @@
* Boston, MA 02111-1307, USA.
*/
/*
* MT safe for the unix part, FIXME: make the win32 part MT safe as well.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -367,11 +371,14 @@ g_getenv (const gchar *variable)
#endif
}
static G_LOCK_DEFINE(g_utils_global);
static gchar *g_tmp_dir = NULL;
static gchar *g_user_name = NULL;
static gchar *g_real_name = NULL;
static gchar *g_home_dir = NULL;
/* HOLDS: g_utils_global_lock */
static void
g_get_any_init (void)
{
@ -442,14 +449,16 @@ g_get_any_init (void)
g_home_dir = NULL;
# endif /* !NATIVE_WIN32 */
#endif /* !HAVE_PWD_H */
}
}
}
gchar*
g_get_user_name (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_user_name;
}
@ -457,9 +466,11 @@ g_get_user_name (void)
gchar*
g_get_real_name (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_real_name;
}
@ -472,8 +483,10 @@ g_get_real_name (void)
gchar*
g_get_home_dir (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_home_dir;
}
@ -488,8 +501,10 @@ g_get_home_dir (void)
gchar*
g_get_tmp_dir (void)
{
g_lock (g_utils_global);
if (!g_tmp_dir)
g_get_any_init ();
g_unlock (g_utils_global);
return g_tmp_dir;
}
@ -499,16 +514,25 @@ static gchar *g_prgname = NULL;
gchar*
g_get_prgname (void)
{
return g_prgname;
gchar* retval;
g_lock (g_utils_global);
retval = g_prgname;
g_unlock (g_utils_global);
return retval;
}
void
g_set_prgname (const gchar *prgname)
{
gchar *c = g_prgname;
gchar *c;
g_lock (g_utils_global);
c = g_prgname;
g_prgname = g_strdup (prgname);
g_free (c);
g_unlock (g_utils_global);
}
guint