version bump to 1.1.8, binary age 0, interface age 0.
[platform/upstream/glib.git] / gthread / testgthread.c
1 #include <stdlib.h>
2
3 #define main testglib_main
4 #include <testglib.c>
5 #undef main
6
7 #define TEST_PRIVATE_THREADS 9
8 #define TEST_PRIVATE_ROUNDS 5
9
10 void
11 test_mutexes ()
12 {
13   GMutex *mutex = NULL;
14   GCond *cond = NULL;
15   GStaticMutex static_mutex = G_STATIC_MUTEX_INIT;
16   G_LOCK_DECLARE (test_me);
17
18   if (g_thread_supported ())
19     {
20       mutex = g_mutex_new ();
21       cond = g_cond_new ();
22     }
23
24   g_mutex_lock (mutex);
25   g_mutex_unlock (mutex);
26
27   g_static_mutex_lock (static_mutex);
28   g_static_mutex_unlock (static_mutex);
29
30   g_cond_signal (cond);
31   g_cond_broadcast (cond);
32
33   G_LOCK (test_me);
34   G_UNLOCK (test_me);
35
36   if (g_thread_supported ())
37     {
38       g_cond_free (cond);
39       g_mutex_free (mutex);
40     }
41 }
42
43 #if defined(NSPR)               /* we are using nspr threads */
44 /* this option must be specified by hand during compile of
45    testgthread. also note, that you have to link with whatever library
46    nspr is building upon, it might otherwise (as on solaris) lead to
47    run time failure, as the mutex functions are defined in libc, but
48    as noops, that will make some nspr assertions fail. */
49 #include <prthread.h>
50
51 gpointer
52 new_thread (GHookFunc func, gpointer data)
53 {
54   PRThread *thread = PR_CreateThread (PR_SYSTEM_THREAD, func, data,
55                                       PR_PRIORITY_NORMAL, PR_LOCAL_THREAD,
56                                       PR_JOINABLE_THREAD, 0);
57   return thread;
58 }
59 #define join_thread(thread) PR_JoinThread (thread)
60 #define self_thread() PR_GetCurrentThread ()
61
62 #elif defined(DEFAULTMUTEX)     /* we are using solaris threads */
63
64 gpointer
65 new_thread (GHookFunc func, gpointer data)
66 {
67   thread_t thread;
68   thr_create (NULL, 0, (void *(*)(void *)) func, data, THR_BOUND, &thread);
69   return GUINT_TO_POINTER (thread);
70 }
71 #define join_thread(thread) \
72   thr_join ((thread_t)GPOINTER_TO_UINT (thread), NULL, NULL)
73 #define self_thread()  GUINT_TO_POINTER (thr_self ())
74
75 #elif defined(PTHREAD_MUTEX_INITIALIZER) /* we are using posix threads */
76 gpointer
77 new_thread(GHookFunc func, gpointer data)
78 {
79   pthread_t thread;
80   pthread_attr_t pthread_attr;
81   pthread_attr_init (&pthread_attr);
82   pthread_attr_setdetachstate (&pthread_attr, PTHREAD_CREATE_JOINABLE);
83   pthread_create (&thread, &pthread_attr, (void *(*)(void *)) func, data);
84   return GUINT_TO_POINTER (thread);
85 }
86 #define join_thread(thread) \
87   pthread_join ((pthread_t)GPOINTER_TO_UINT (thread), NULL)
88 #define self_thread() GUINT_TO_POINTER (pthread_self ())
89
90 #else /* we are not having a thread implementation, do nothing */
91
92 #define new_thread(func,data) (NULL)
93 #define join_thread(thread) ((void)0)
94 #define self_thread() NULL
95
96 #endif
97
98 #define G_MICROSEC 1000000
99
100 void
101 wait_thread (double seconds)
102 {
103   GMutex *mutex;
104   GCond *cond;
105   GTimeVal current_time;
106
107   g_get_current_time (&current_time);
108   mutex = g_mutex_new ();
109   cond = g_cond_new ();
110
111   current_time.tv_sec += (guint) seconds;
112   seconds -= (guint) seconds;
113   current_time.tv_usec += (guint) (seconds * G_MICROSEC);
114   while (current_time.tv_usec >= G_MICROSEC)
115     {
116       current_time.tv_usec -= G_MICROSEC;
117       current_time.tv_sec++;
118     }
119
120   g_mutex_lock (mutex);
121   g_cond_timed_wait (cond, mutex, &current_time);
122   g_mutex_unlock (mutex);
123
124   g_mutex_free (mutex);
125   g_cond_free (cond);
126 }
127
128 gpointer
129 private_constructor ()
130 {
131   gpointer *result = g_new (gpointer, 2);
132   result[0] = 0;
133   result[1] = self_thread ();
134   g_print ("allocating data for the thread %p.\n", result[1]);
135   return result;
136 }
137
138 void
139 private_destructor (gpointer data)
140 {
141   gpointer *real = data;
142   g_print ("freeing data for the thread %p.\n", real[1]);
143   g_free (real);
144 }
145
146 GStaticPrivate private_key;
147
148 void
149 test_private_func (void *data)
150 {
151   guint i = 0;
152   wait_thread (1);
153   while (i < TEST_PRIVATE_ROUNDS)
154     {
155       guint random_value = rand () % 10000;
156       guint *data = g_static_private_get (&private_key);
157       if (!data)
158         {
159           data = private_constructor ();
160           g_static_private_set (&private_key, data, private_destructor);
161         }
162       *data = random_value;
163       wait_thread (.2);
164       g_assert (*(guint *) g_static_private_get (&private_key) == random_value);
165       i++;
166     }
167 }
168
169 void
170 test_private ()
171 {
172   int i;
173   gpointer threads[TEST_PRIVATE_THREADS];
174   for (i = 0; i < TEST_PRIVATE_THREADS; i++)
175     {
176       threads[i] = new_thread (test_private_func, GINT_TO_POINTER(i));
177     }
178   for (i = 0; i < TEST_PRIVATE_THREADS; i++)
179     {
180       join_thread (threads[i]);
181     }
182   g_print ("\n");
183 }
184
185 int
186 main ()
187 {
188   test_mutexes ();
189
190   g_thread_init (NULL);
191
192   test_mutexes ();
193
194   test_private ();
195
196   /* later we might want to start n copies of that */
197   testglib_main (0, NULL);
198
199   return 0;
200 }