mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-06 16:08:43 +02:00
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.
201 lines
4.4 KiB
C
201 lines
4.4 KiB
C
#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 (¤t_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, ¤t_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;
|
|
}
|