diff options
author | Sebastian Wilhelmi <wilhelmi@ira.uka.de> | 1999-06-17 15:39:31 +0000 |
---|---|---|
committer | Sebastian Wilhelmi <wilhelmi@src.gnome.org> | 1999-06-17 15:39:31 +0000 |
commit | 90f6cc9bf2453e5da385b2d547704091dd8afbb8 (patch) | |
tree | 185b523416ce210680c328dc2dbeae90d349d731 /tests | |
parent | ed49525102be3f9db6300dae0d369a92c19b2e66 (diff) | |
download | glib-90f6cc9bf2453e5da385b2d547704091dd8afbb8.tar.gz |
Completed the thread support in GLib. Thread creation, prioritizing
1999-06-17 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* configure.in, acglib.m4, acconfig.h, glib.h, gthread.c:
Completed the thread support in GLib. Thread creation,
prioritizing threads, yielding, joining threads as well as
reader/writer locks and recursive mutexes are now in place. Please
test heavily on your platform. It is so far tested on
Linux/i386/pthreads, Solaris/Sparc/pthreads and
Solaris/Sparc/solaristhreads.
* gtimer.c, glib.h: Implement g_usleep (gulong microseconds) for
thread safe sleeping. (sleep() is not MT-safe at all!)
* gutils.c: Avoid compiler warning.
* tests/Makefile.am, tests/thread-test.c: New program to test some
aspects of the thread implementation.
* gthread.c, Makefile.am: Renamed from gmutex.c to reflect the
change of content.
* configure.in: Purged all appearances of nspr.
* gthread/gthread-posix.c, gthread-solaris.c: Added the native
implementations for the GLib's extended thread support.
* gthread/gthread-nspr.c: Removed for good. NSPR is nothing we
would want to build upon.
* gthread/gthread.c: Renamed to gthread-impl.c to avoid
confusion with ../gthread.c (Formerly known as the file called
gmutex.c)
* gthread/testgthread.c: Removed. The new and much extended
tests are in ../tests/thread-test.c.
* gthread/Makefile.am: Changed to reflect the changes above.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 5 | ||||
-rw-r--r-- | tests/thread-test.c | 238 |
2 files changed, 242 insertions, 1 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index b735dd97b..2abdb0ca9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,7 +20,8 @@ TESTS = \ string-test \ strfunc-test \ tree-test \ - type-test + type-test \ + thread-test noinst_PROGRAMS = $(TESTS) @@ -39,6 +40,8 @@ string_test_LDADD = $(top_builddir)/libglib.la strfunc_test_LDADD = $(top_builddir)/libglib.la tree_test_LDADD = $(top_builddir)/libglib.la type_test_LDADD = $(top_builddir)/libglib.la +thread_test_LDADD = $(top_builddir)/libglib.la \ + $(top_builddir)/gthread/libgthread.la @G_THREAD_LIBS@ makefile.msc: $(top_builddir)/config.status $(top_srcdir)/tests/makefile.msc.in cd $(top_builddir) && CONFIG_FILES=tests/$@ CONFIG_HEADERS= $(SHELL) ./config.status diff --git a/tests/thread-test.c b/tests/thread-test.c new file mode 100644 index 000000000..300e55e93 --- /dev/null +++ b/tests/thread-test.c @@ -0,0 +1,238 @@ +#include <glib.h> + +/* GMutex */ + +static GMutex* test_g_mutex_mutex = NULL; +static guint test_g_mutex_int = 0; + +static void +test_g_mutex_thread (gpointer data) +{ + g_assert (GPOINTER_TO_INT (data) == 42); + g_assert (g_mutex_trylock (test_g_mutex_mutex) == FALSE); + g_mutex_lock (test_g_mutex_mutex); + g_assert (test_g_mutex_int == 42); + g_mutex_unlock (test_g_mutex_mutex); +} + +static void +test_g_mutex (void) +{ + GThread *thread; + test_g_mutex_mutex = g_mutex_new (); + + g_assert (g_mutex_trylock (test_g_mutex_mutex)); + thread = g_thread_create (test_g_mutex_thread, + GINT_TO_POINTER (42), + 0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL); + g_usleep (G_MICROSEC); + test_g_mutex_int = 42; + g_mutex_unlock (test_g_mutex_mutex); + g_thread_join (thread); + g_mutex_free (test_g_mutex_mutex); +} + +/* GStaticRecMutex */ + +static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT; +static guint test_g_static_rec_mutex_int = 0; + +static void +test_g_static_rec_mutex_thread (gpointer data) +{ + g_assert (GPOINTER_TO_INT (data) == 42); + g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex) + == FALSE); + g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); + g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); + g_assert (test_g_static_rec_mutex_int == 42); + g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); + g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); +} + +static void +test_g_static_rec_mutex (void) +{ + GThread *thread; + + g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); + thread = g_thread_create (test_g_static_rec_mutex_thread, + GINT_TO_POINTER (42), + 0, TRUE, TRUE, G_THREAD_PRIORITY_NORMAL); + g_usleep (G_MICROSEC); + g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); + g_usleep (G_MICROSEC); + test_g_static_rec_mutex_int = 41; + g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); + test_g_static_rec_mutex_int = 42; + g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); + g_usleep (G_MICROSEC); + g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); + test_g_static_rec_mutex_int = 0; + g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); + g_thread_join (thread); +} + +/* GStaticPrivate */ + +#define THREADS 10 + +static GStaticPrivate test_g_static_private_private = G_STATIC_PRIVATE_INIT; +static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT; +static guint test_g_static_private_counter = 0; + +static gpointer +test_g_static_private_constructor (void) +{ + g_static_mutex_lock (&test_g_static_private_mutex); + test_g_static_private_counter++; + g_static_mutex_unlock (&test_g_static_private_mutex); + return g_new (guint,1); +} + +static void +test_g_static_private_destructor (gpointer data) +{ + g_static_mutex_lock (&test_g_static_private_mutex); + test_g_static_private_counter--; + g_static_mutex_unlock (&test_g_static_private_mutex); + g_free (data); +} + + +static void +test_g_static_private_thread (gpointer data) +{ + guint number = GPOINTER_TO_INT (data); + guint i; + guint* private; + for (i = 0; i < 10; i++) + { + number = number * 11 + 1; /* A very simple and bad RNG ;-) */ + private = g_static_private_get (&test_g_static_private_private); + if (!private || number % 7 > 3) + { + private = test_g_static_private_constructor (); + g_static_private_set (&test_g_static_private_private, private, + test_g_static_private_destructor); + } + *private = number; + g_usleep (G_MICROSEC / 5); + g_assert (number == *private); + } +} + +static void +test_g_static_private (void) +{ + GThread *threads[THREADS]; + guint i; + for (i = 0; i < THREADS; i++) + { + threads[i] = g_thread_create (test_g_static_private_thread, + GINT_TO_POINTER (i), + 0, TRUE, TRUE, + G_THREAD_PRIORITY_NORMAL); + } + for (i = 0; i < THREADS; i++) + { + g_thread_join (threads[i]); + } + g_assert (test_g_static_private_counter == 0); +} + +/* GStaticRWLock */ + +/* -1 = writing; >0 = # of readers */ +static gint test_g_static_rw_lock_state = 0; +G_LOCK_DEFINE (test_g_static_rw_lock_state); + +static gboolean test_g_static_rw_lock_run = TRUE; +static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT; + +static void +test_g_static_rw_lock_thread (gpointer data) +{ + while (test_g_static_rw_lock_run) + { + if (g_random_double() > .2) /* I'm a reader */ + { + + if (g_random_double() > .2) /* I'll block */ + g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock); + else /* I'll only try */ + if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock)) + continue; + G_LOCK (test_g_static_rw_lock_state); + g_assert (test_g_static_rw_lock_state >= 0); + test_g_static_rw_lock_state++; + G_UNLOCK (test_g_static_rw_lock_state); + + g_usleep (10); + + G_LOCK (test_g_static_rw_lock_state); + test_g_static_rw_lock_state--; + G_UNLOCK (test_g_static_rw_lock_state); + + g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock); + } + else /* I'm a writer */ + { + + if (g_random_double() > .2) /* I'll block */ + g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock); + else /* I'll only try */ + if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock)) + continue; + G_LOCK (test_g_static_rw_lock_state); + g_assert (test_g_static_rw_lock_state == 0); + test_g_static_rw_lock_state = -1; + G_UNLOCK (test_g_static_rw_lock_state); + + g_usleep (10); + + G_LOCK (test_g_static_rw_lock_state); + test_g_static_rw_lock_state = 0; + G_UNLOCK (test_g_static_rw_lock_state); + + g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock); + } + } +} + +static void +test_g_static_rw_lock () +{ + GThread *threads[THREADS]; + guint i; + for (i = 0; i < THREADS; i++) + { + threads[i] = g_thread_create (test_g_static_rw_lock_thread, + 0, 0, TRUE, TRUE, + G_THREAD_PRIORITY_NORMAL); + } + g_usleep (G_MICROSEC); + test_g_static_rw_lock_run = FALSE; + for (i = 0; i < THREADS; i++) + { + g_thread_join (threads[i]); + } + g_assert (test_g_static_rw_lock_state == 0); +} + +/* run all the tests */ +int +main (int argc, + char *argv[]) +{ + /* Only run the test, if threads are enabled and a default thread + implementation is available */ +#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE) + g_thread_init (NULL); + test_g_mutex (); + test_g_static_rec_mutex (); + test_g_static_private (); + test_g_static_rw_lock (); +#endif + return 0; +} |