mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-06 09:26:17 +01:00
8168836cd2
1999-02-15 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * glib.h, glibconfig.h.win32, configure.in: Changed signature of all g_static_mutex_* functions to take a pointer rather than the struct itself. This is not an issue at the moment, because those funcs are really macros, but is it un'G'ish and might fall on our feet in the future. * gthread/testgthread.c (test_mutexes): Use new signature of g_static_mutex* functions.
218 lines
4.7 KiB
C
218 lines
4.7 KiB
C
#include "config.h"
|
|
|
|
#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 (void)
|
|
{
|
|
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(G_THREADS_IMPL_NSPR)
|
|
#warning "note, that you have to link with whatever library"
|
|
#warning "nspr is building upon, it might otherwise (as on solaris) lead to"
|
|
#warning "run time failure, as the mutex functions are defined in libc, but"
|
|
#warning "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(G_THREADS_IMPL_SOLARIS)
|
|
#include <thread.h>
|
|
|
|
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(G_THREADS_IMPL_POSIX)
|
|
#include <pthread.h>
|
|
|
|
gpointer
|
|
new_thread(GHookFunc func, gpointer data)
|
|
{
|
|
pthread_t thread;
|
|
pthread_attr_t pthread_attr;
|
|
pthread_attr_init (&pthread_attr);
|
|
/* This is the default, it seems, so leave that out for now
|
|
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 (void)
|
|
{
|
|
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_key;
|
|
|
|
void
|
|
test_private_func (void *data)
|
|
{
|
|
guint i = 0;
|
|
static unsigned int seed = 0;
|
|
if (!seed)
|
|
{
|
|
GTimeVal now;
|
|
g_get_current_time (&now);
|
|
seed = now.tv_usec;
|
|
}
|
|
wait_thread (1);
|
|
while (i < TEST_PRIVATE_ROUNDS)
|
|
{
|
|
#ifdef HAVE_RAND_R
|
|
guint random_value = rand_r (&seed) % 10000;
|
|
#else
|
|
guint random_value = rand() % 10000;
|
|
#endif
|
|
guint *data = g_static_private_get (&private_key);
|
|
if (!data)
|
|
{
|
|
data = private_constructor ();
|
|
g_static_private_set (&private_key, data, private_destructor);
|
|
}
|
|
*data = random_value;
|
|
wait_thread (.2);
|
|
g_assert (*(guint *) g_static_private_get (&private_key) == random_value);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void
|
|
test_private (void)
|
|
{
|
|
int i;
|
|
gpointer threads[TEST_PRIVATE_THREADS];
|
|
for (i = 0; i < TEST_PRIVATE_THREADS; i++)
|
|
{
|
|
threads[i] = new_thread (test_private_func, GINT_TO_POINTER(i));
|
|
}
|
|
for (i = 0; i < TEST_PRIVATE_THREADS; i++)
|
|
{
|
|
join_thread (threads[i]);
|
|
}
|
|
g_print ("\n");
|
|
}
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
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;
|
|
}
|