1 #undef G_DISABLE_ASSERT 2 #undef G_LOG_DOMAIN 3 4 #include <glib.h> 5 6 /* GMutex */ 7 8 static GMutex* test_g_mutex_mutex = NULL; 9 static guint test_g_mutex_int = 0; 10 static gboolean test_g_mutex_thread_ready; 11 G_LOCK_DEFINE_STATIC (test_g_mutex); 12 13 static gpointer 14 test_g_mutex_thread (gpointer data) 15 { 16 g_assert (GPOINTER_TO_INT (data) == 42); 17 g_assert (g_mutex_trylock (test_g_mutex_mutex) == FALSE); 18 g_assert (G_TRYLOCK (test_g_mutex) == FALSE); 19 test_g_mutex_thread_ready = TRUE; 20 g_mutex_lock (test_g_mutex_mutex); 21 g_assert (test_g_mutex_int == 42); 22 g_mutex_unlock (test_g_mutex_mutex); 23 24 return GINT_TO_POINTER (41); 25 } 26 27 static void 28 test_g_mutex (void) 29 { 30 GThread *thread; 31 test_g_mutex_mutex = g_mutex_new (); 32 33 g_assert (g_mutex_trylock (test_g_mutex_mutex)); 34 g_assert (G_TRYLOCK (test_g_mutex)); 35 test_g_mutex_thread_ready = FALSE; 36 thread = g_thread_create (test_g_mutex_thread, GINT_TO_POINTER (42), 37 TRUE, NULL); 38 /* This busy wait is only for testing purposes and not an example of 39 * good code!*/ 40 while (!test_g_mutex_thread_ready) 41 g_usleep (G_USEC_PER_SEC / 5); 42 test_g_mutex_int = 42; 43 G_UNLOCK (test_g_mutex); 44 g_mutex_unlock (test_g_mutex_mutex); 45 g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 41); 46 g_mutex_free (test_g_mutex_mutex); 47 } 48 49 /* GStaticRecMutex */ 50 51 static GStaticRecMutex test_g_static_rec_mutex_mutex = G_STATIC_REC_MUTEX_INIT; 52 static guint test_g_static_rec_mutex_int = 0; 53 static gboolean test_g_static_rec_mutex_thread_ready; 54 55 static gpointer 56 test_g_static_rec_mutex_thread (gpointer data) 57 { 58 g_assert (GPOINTER_TO_INT (data) == 42); 59 g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex) 60 == FALSE); 61 test_g_static_rec_mutex_thread_ready = TRUE; 62 g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); 63 g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); 64 g_assert (test_g_static_rec_mutex_int == 42); 65 test_g_static_rec_mutex_thread_ready = FALSE; 66 g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); 67 g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); 68 69 g_thread_exit (GINT_TO_POINTER (43)); 70 71 g_assert_not_reached (); 72 return NULL; 73 } 74 75 static void 76 test_g_static_rec_mutex (void) 77 { 78 GThread *thread; 79 80 g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); 81 test_g_static_rec_mutex_thread_ready = FALSE; 82 thread = g_thread_create (test_g_static_rec_mutex_thread, 83 GINT_TO_POINTER (42), TRUE, NULL); 84 /* This busy wait is only for testing purposes and not an example of 85 * good code!*/ 86 while (!test_g_static_rec_mutex_thread_ready) 87 g_usleep (G_USEC_PER_SEC / 5); 88 89 g_assert (g_static_rec_mutex_trylock (&test_g_static_rec_mutex_mutex)); 90 test_g_static_rec_mutex_int = 41; 91 g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); 92 test_g_static_rec_mutex_int = 42; 93 g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); 94 95 /* This busy wait is only for testing purposes and not an example of 96 * good code!*/ 97 while (test_g_static_rec_mutex_thread_ready) 98 g_usleep (G_USEC_PER_SEC / 5); 99 100 g_static_rec_mutex_lock (&test_g_static_rec_mutex_mutex); 101 test_g_static_rec_mutex_int = 0; 102 g_static_rec_mutex_unlock (&test_g_static_rec_mutex_mutex); 103 104 g_assert (GPOINTER_TO_INT (g_thread_join (thread)) == 43); 105 } 106 107 /* GStaticPrivate */ 108 109 #define THREADS 10 110 111 static GStaticPrivate test_g_static_private_private1 = G_STATIC_PRIVATE_INIT; 112 static GStaticPrivate test_g_static_private_private2 = G_STATIC_PRIVATE_INIT; 113 static GStaticMutex test_g_static_private_mutex = G_STATIC_MUTEX_INIT; 114 static guint test_g_static_private_counter = 0; 115 static guint test_g_static_private_ready = 0; 116 117 static gpointer 118 test_g_static_private_constructor (void) 119 { 120 g_static_mutex_lock (&test_g_static_private_mutex); 121 test_g_static_private_counter++; 122 g_static_mutex_unlock (&test_g_static_private_mutex); 123 return g_new (guint,1); 124 } 125 126 static void 127 test_g_static_private_destructor (gpointer data) 128 { 129 g_static_mutex_lock (&test_g_static_private_mutex); 130 test_g_static_private_counter--; 131 g_static_mutex_unlock (&test_g_static_private_mutex); 132 g_free (data); 133 } 134 135 136 static gpointer 137 test_g_static_private_thread (gpointer data) 138 { 139 guint number = GPOINTER_TO_INT (data); 140 guint i; 141 guint *private1, *private2; 142 for (i = 0; i < 10; i++) 143 { 144 number = number * 11 + 1; /* A very simple and bad RNG ;-) */ 145 private1 = g_static_private_get (&test_g_static_private_private1); 146 if (!private1 || number % 7 > 3) 147 { 148 private1 = test_g_static_private_constructor (); 149 g_static_private_set (&test_g_static_private_private1, private1, 150 test_g_static_private_destructor); 151 } 152 *private1 = number; 153 private2 = g_static_private_get (&test_g_static_private_private2); 154 if (!private2 || number % 13 > 5) 155 { 156 private2 = test_g_static_private_constructor (); 157 g_static_private_set (&test_g_static_private_private2, private2, 158 test_g_static_private_destructor); 159 } 160 *private2 = number * 2; 161 g_usleep (G_USEC_PER_SEC / 5); 162 g_assert (number == *private1); 163 g_assert (number * 2 == *private2); 164 } 165 g_static_mutex_lock (&test_g_static_private_mutex); 166 test_g_static_private_ready++; 167 g_static_mutex_unlock (&test_g_static_private_mutex); 168 169 /* Busy wait is not nice but that's just a test */ 170 while (test_g_static_private_ready != 0) 171 g_usleep (G_USEC_PER_SEC / 5); 172 173 for (i = 0; i < 10; i++) 174 { 175 private2 = g_static_private_get (&test_g_static_private_private2); 176 number = number * 11 + 1; /* A very simple and bad RNG ;-) */ 177 if (!private2 || number % 13 > 5) 178 { 179 private2 = test_g_static_private_constructor (); 180 g_static_private_set (&test_g_static_private_private2, private2, 181 test_g_static_private_destructor); 182 } 183 *private2 = number * 2; 184 g_usleep (G_USEC_PER_SEC / 5); 185 g_assert (number * 2 == *private2); 186 } 187 188 return GINT_TO_POINTER (GPOINTER_TO_INT (data) * 3); 189 } 190 191 static void 192 test_g_static_private (void) 193 { 194 GThread *threads[THREADS]; 195 guint i; 196 197 test_g_static_private_ready = 0; 198 199 for (i = 0; i < THREADS; i++) 200 { 201 threads[i] = g_thread_create (test_g_static_private_thread, 202 GINT_TO_POINTER (i), TRUE, NULL); 203 } 204 205 /* Busy wait is not nice but that's just a test */ 206 while (test_g_static_private_ready != THREADS) 207 g_usleep (G_USEC_PER_SEC / 5); 208 209 /* Reuse the static private */ 210 g_static_private_free (&test_g_static_private_private2); 211 g_static_private_init (&test_g_static_private_private2); 212 213 test_g_static_private_ready = 0; 214 215 for (i = 0; i < THREADS; i++) 216 g_assert (GPOINTER_TO_INT (g_thread_join (threads[i])) == i * 3); 217 218 g_assert (test_g_static_private_counter == 0); 219 } 220 221 /* GStaticRWLock */ 222 223 /* -1 = writing; >0 = # of readers */ 224 static gint test_g_static_rw_lock_state = 0; 225 G_LOCK_DEFINE (test_g_static_rw_lock_state); 226 227 static gboolean test_g_static_rw_lock_run = TRUE; 228 static GStaticRWLock test_g_static_rw_lock_lock = G_STATIC_RW_LOCK_INIT; 229 230 static gpointer 231 test_g_static_rw_lock_thread (gpointer data) 232 { 233 while (test_g_static_rw_lock_run) 234 { 235 if (g_random_double() > .2) /* I'm a reader */ 236 { 237 238 if (g_random_double() > .2) /* I'll block */ 239 g_static_rw_lock_reader_lock (&test_g_static_rw_lock_lock); 240 else /* I'll only try */ 241 if (!g_static_rw_lock_reader_trylock (&test_g_static_rw_lock_lock)) 242 continue; 243 G_LOCK (test_g_static_rw_lock_state); 244 g_assert (test_g_static_rw_lock_state >= 0); 245 test_g_static_rw_lock_state++; 246 G_UNLOCK (test_g_static_rw_lock_state); 247 248 g_usleep (g_random_int_range (20,1000)); 249 250 G_LOCK (test_g_static_rw_lock_state); 251 test_g_static_rw_lock_state--; 252 G_UNLOCK (test_g_static_rw_lock_state); 253 254 g_static_rw_lock_reader_unlock (&test_g_static_rw_lock_lock); 255 } 256 else /* I'm a writer */ 257 { 258 259 if (g_random_double() > .2) /* I'll block */ 260 g_static_rw_lock_writer_lock (&test_g_static_rw_lock_lock); 261 else /* I'll only try */ 262 if (!g_static_rw_lock_writer_trylock (&test_g_static_rw_lock_lock)) 263 continue; 264 G_LOCK (test_g_static_rw_lock_state); 265 g_assert (test_g_static_rw_lock_state == 0); 266 test_g_static_rw_lock_state = -1; 267 G_UNLOCK (test_g_static_rw_lock_state); 268 269 g_usleep (g_random_int_range (20,1000)); 270 271 G_LOCK (test_g_static_rw_lock_state); 272 test_g_static_rw_lock_state = 0; 273 G_UNLOCK (test_g_static_rw_lock_state); 274 275 g_static_rw_lock_writer_unlock (&test_g_static_rw_lock_lock); 276 } 277 } 278 return NULL; 279 } 280 281 static void 282 test_g_static_rw_lock () 283 { 284 GThread *threads[THREADS]; 285 guint i; 286 for (i = 0; i < THREADS; i++) 287 { 288 threads[i] = g_thread_create (test_g_static_rw_lock_thread, 289 NULL, TRUE, NULL); 290 } 291 g_usleep (G_USEC_PER_SEC * 5); 292 test_g_static_rw_lock_run = FALSE; 293 for (i = 0; i < THREADS; i++) 294 { 295 g_thread_join (threads[i]); 296 } 297 g_assert (test_g_static_rw_lock_state == 0); 298 } 299 300 #define G_ONCE_SIZE 100 301 #define G_ONCE_THREADS 10 302 303 G_LOCK_DEFINE (test_g_once); 304 static guint test_g_once_guint_array[G_ONCE_SIZE]; 305 static GOnce test_g_once_array[G_ONCE_SIZE]; 306 307 static gpointer 308 test_g_once_init_func(gpointer arg) 309 { 310 guint *count = arg; 311 g_usleep (g_random_int_range (20,1000)); 312 (*count)++; 313 g_usleep (g_random_int_range (20,1000)); 314 return arg; 315 } 316 317 static gpointer 318 test_g_once_thread (gpointer ignore) 319 { 320 guint i; 321 G_LOCK (test_g_once); 322 /* Don't start before all threads are created */ 323 G_UNLOCK (test_g_once); 324 for (i = 0; i < 1000; i++) 325 { 326 guint pos = g_random_int_range (0, G_ONCE_SIZE); 327 gpointer ret = g_once (test_g_once_array + pos, test_g_once_init_func, 328 test_g_once_guint_array + pos); 329 g_assert (ret == test_g_once_guint_array + pos); 330 } 331 332 /* Make sure, that all counters are touched at least once */ 333 for (i = 0; i < G_ONCE_SIZE; i++) 334 { 335 gpointer ret = g_once (test_g_once_array + i, test_g_once_init_func, 336 test_g_once_guint_array + i); 337 g_assert (ret == test_g_once_guint_array + i); 338 } 339 340 return NULL; 341 } 342 343 static void 344 test_g_thread_once (void) 345 { 346 static GOnce once_init = G_ONCE_INIT; 347 GThread *threads[G_ONCE_THREADS]; 348 guint i; 349 for (i = 0; i < G_ONCE_SIZE; i++) 350 { 351 test_g_once_array[i] = once_init; 352 test_g_once_guint_array[i] = i; 353 } 354 G_LOCK (test_g_once); 355 for (i = 0; i < G_ONCE_THREADS; i++) 356 { 357 threads[i] = g_thread_create (test_g_once_thread, GUINT_TO_POINTER(i%2), 358 TRUE, NULL); 359 } 360 G_UNLOCK (test_g_once); 361 for (i = 0; i < G_ONCE_THREADS; i++) 362 { 363 g_thread_join (threads[i]); 364 } 365 366 for (i = 0; i < G_ONCE_SIZE; i++) 367 { 368 g_assert (test_g_once_guint_array[i] == i + 1); 369 } 370 } 371 372 /* run all the tests */ 373 void 374 run_all_tests() 375 { 376 test_g_mutex (); 377 test_g_static_rec_mutex (); 378 test_g_static_private (); 379 test_g_static_rw_lock (); 380 test_g_thread_once (); 381 } 382 383 int 384 main (int argc, 385 char *argv[]) 386 { 387 /* Only run the test, if threads are enabled and a default thread 388 implementation is available */ 389 #if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE) 390 g_thread_init (NULL); 391 run_all_tests (); 392 393 /* Now we rerun all tests, but this time we fool the system into 394 * thinking, that the available thread system is not native, but 395 * userprovided. */ 396 397 g_thread_use_default_impl = FALSE; 398 run_all_tests (); 399 400 #endif 401 return 0; 402 } 403