1 /* 2 * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org> 3 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 #include <stdio.h> 20 #include <string.h> 21 #include <stdlib.h> 22 #include <libgda/libgda.h> 23 #include <thread-wrapper/gda-thread-wrapper.h> 24 #include "dummy-object.h" 25 #include <stdarg.h> 26 27 #define NTHREADS 10 28 #define NCALLS 10 29 #define PRINT_CALLS 30 #undef PRINT_CALLS 31 32 static gint test1 (void); 33 static gint test2 (void); 34 35 GdaThreadWrapper *wrapper; /* global object */ 36 37 int 38 main (int argc, char** argv) 39 { 40 gint failures = 0; 41 42 gda_init (); 43 44 failures += test1 (); 45 failures += test2 (); 46 47 g_print ("Threads COUNT: %d, CALLS per thread:%d\n", NTHREADS, NCALLS*2 + 1); 48 g_print ("FAILURES: %d\n", failures); 49 50 return failures != 0 ? 1 : 0; 51 } 52 53 54 55 /* 56 * This test creates a single GdaThreadWrapper and runs NTHREADS threads which use the 57 * same GdaThreadWrapper object (each thread executes 2*NCALLS function calls plus a random 58 * number of function calls which return void). 59 * 60 * No signal is handled in this test 61 */ 62 static gpointer main_thread_func (gpointer int_id); 63 static gpointer exec_in_wrapped_thread (gpointer int_in, GError **error); 64 static gchar *exec_in_wrapped_thread2 (gchar *str, GError **error); 65 static void exec_in_wrapped_thread_v (gchar *str, GError **error); 66 static gint 67 test1 (void) 68 { 69 gint failures = 0; 70 gint i; 71 GSList *threads = NULL; 72 73 wrapper = gda_thread_wrapper_new (); 74 75 /* use GdaThreadWrapper from several threads */ 76 for (i = 0; i < NTHREADS; i++) { 77 GThread *th; 78 th = g_thread_new ("th", main_thread_func, GINT_TO_POINTER (i)); 79 if (!th) { 80 g_print ("Can't create thread %d (not part of the test)\n", i); 81 exit (1); 82 } 83 threads = g_slist_prepend (threads, th); 84 } 85 86 /* join the threads */ 87 GSList *list; 88 for (list = threads; list; list = list->next) 89 failures += GPOINTER_TO_INT (g_thread_join ((GThread*) list->data)); 90 g_slist_free (threads); 91 92 g_object_unref (wrapper); 93 return failures; 94 } 95 96 static gpointer 97 exec_in_wrapped_thread (gpointer int_in, GError **error) 98 { 99 g_print ("function_1 (%d)\n", GPOINTER_TO_INT (int_in)); 100 return int_in; 101 } 102 103 static gchar * 104 exec_in_wrapped_thread2 (gchar *str, GError **error) 105 { 106 g_print ("function_2 (%s)\n", str); 107 return g_strdup (str); 108 } 109 110 static void 111 exec_in_wrapped_thread_v (gchar *str, GError **error) 112 { 113 g_print ("function_VOID (%s)\n", str); 114 } 115 116 static void 117 free_arg (gchar *str) 118 { 119 g_print ("\tFreeing: %s\n", str); 120 g_free (str); 121 } 122 123 static gpointer 124 main_thread_func (gpointer int_id) 125 { 126 gint i; 127 guint *ids; 128 gchar *estr; 129 130 gint total_jobs = 0; 131 gint nfailed = 0; 132 133 g_print ("NEW thread %p <=> %d\n", g_thread_self(), GPOINTER_TO_INT (int_id)); 134 135 ids = g_new0 (guint, 2*NCALLS); 136 for (i = 0; i < NCALLS; i++) { 137 guint id; 138 GError *error = NULL; 139 140 /* func1 */ 141 id = gda_thread_wrapper_execute (wrapper, (GdaThreadWrapperFunc) exec_in_wrapped_thread, 142 GINT_TO_POINTER (i + GPOINTER_TO_INT (int_id) * 1000), NULL, &error); 143 if (id == 0) { 144 g_print ("Error in %s() for thread %d: %s\n", __FUNCTION__, GPOINTER_TO_INT (int_id), 145 error && error->message ? error->message : "No detail"); 146 if (error) 147 g_error_free (error); 148 return GINT_TO_POINTER (1); 149 } 150 ids[2*i] = id; 151 #ifdef PRINT_CALLS 152 g_print ("--> Thread %d jobID %u arg %d\n", GPOINTER_TO_INT (int_id), id, i + GPOINTER_TO_INT (int_id) * 1000); 153 #endif 154 if (rand () >= RAND_MAX / 2.) 155 g_thread_yield (); 156 157 158 if (rand () >= RAND_MAX / 2.) { 159 id = gda_thread_wrapper_execute_void (wrapper, (GdaThreadWrapperVoidFunc) exec_in_wrapped_thread_v, 160 g_strdup_printf ("perturbator %d.%d", GPOINTER_TO_INT (int_id), i), 161 (GDestroyNotify) free_arg, &error); 162 if (id == 0) { 163 g_print ("Error in %s() for thread %d: %s\n", __FUNCTION__, GPOINTER_TO_INT (int_id), 164 error && error->message ? error->message : "No detail"); 165 if (error) 166 g_error_free (error); 167 return GINT_TO_POINTER (1); 168 } 169 total_jobs ++; 170 } 171 if (rand () >= RAND_MAX / 2.) 172 g_thread_yield (); 173 174 /* func2 */ 175 id = gda_thread_wrapper_execute (wrapper, (GdaThreadWrapperFunc) exec_in_wrapped_thread2, 176 g_strdup_printf ("Hello %d.%d", GPOINTER_TO_INT (int_id), i), 177 (GDestroyNotify) free_arg, &error); 178 if (id == 0) { 179 g_print ("Error in %s() for thread %d: %s\n", __FUNCTION__, GPOINTER_TO_INT (int_id), 180 error && error->message ? error->message : "No detail"); 181 if (error) 182 g_error_free (error); 183 return GINT_TO_POINTER (1); 184 } 185 ids[2*i+1] = id; 186 estr = g_strdup_printf ("Hello %d.%d", GPOINTER_TO_INT (int_id), i); 187 #ifdef PRINT_CALLS 188 g_print ("--> Thread %d jobID %u arg %s\n", GPOINTER_TO_INT (int_id), id, estr); 189 #endif 190 g_free (estr); 191 if (rand () >= RAND_MAX / 2.) 192 g_thread_yield (); 193 } 194 total_jobs += 2*NCALLS; 195 g_thread_yield (); 196 197 /* pick up results */ 198 for (i = 0; i < NCALLS; i++) { 199 gpointer res; 200 res = gda_thread_wrapper_fetch_result (wrapper, TRUE, ids[2*i], NULL); 201 if (GPOINTER_TO_INT (res) != i + GPOINTER_TO_INT (int_id) * 1000) { 202 g_print ("Error in %s() for thread %d: sub thread's exec result is wrong\n", 203 __FUNCTION__, GPOINTER_TO_INT (int_id)); 204 nfailed ++; 205 } 206 #ifdef PRINT_CALLS 207 g_print ("<-- Thread %d jobID %u arg %d\n", GPOINTER_TO_INT (int_id), id, i + GPOINTER_TO_INT (int_id) * 1000); 208 #endif 209 if (rand () >= RAND_MAX / 2.) 210 g_thread_yield (); 211 212 gchar *str; 213 estr = g_strdup_printf ("Hello %d.%d", GPOINTER_TO_INT (int_id), i); 214 str = gda_thread_wrapper_fetch_result (wrapper, TRUE, ids[2*i+1], NULL); 215 if (!str || strcmp (str, estr)) { 216 g_print ("Error in %s() for thread %d: sub thread's exec result is wrong: got %s, exp: %s\n", 217 __FUNCTION__, GPOINTER_TO_INT (int_id), str, estr); 218 nfailed ++; 219 } 220 g_free (estr); 221 #ifdef PRINT_CALLS 222 g_print ("<-- Thread %d jobID %u arg %s\n", GPOINTER_TO_INT (int_id), id, str); 223 #endif 224 g_free (str); 225 if (rand () >= RAND_MAX / 2.) 226 g_thread_yield (); 227 } 228 g_free (ids); 229 230 return GINT_TO_POINTER (nfailed); 231 } 232 233 234 /* 235 * This test creates a single #GdaThreadWrapper object and a single dummy object (DummyObject) which is 236 * used to emit signals by functions executed in sub threads. 237 */ 238 typedef struct { 239 DummyObject *dummy; 240 GSList *signals_sent; /* list of TestSignal structures */ 241 GMutex mutex; 242 } t2ExecData; 243 static void add_to_signals_sent (t2ExecData *data, gpointer what_to_add); 244 static gpointer t2_main_thread_func (DummyObject *dummy); 245 static gpointer t2_exec_in_wrapped_thread (t2ExecData *data, GError **error); 246 static void t2_exec_in_wrapped_thread_v (t2ExecData *data, GError **error); 247 #define INT_TOKEN 1034 248 249 static void 250 add_to_signals_sent (t2ExecData *data, gpointer what_to_add) 251 { 252 g_mutex_lock (&data->mutex); 253 data->signals_sent = g_slist_append (data->signals_sent, what_to_add); 254 g_mutex_unlock (&data->mutex); 255 } 256 257 static gint 258 test2 (void) 259 { 260 gint failures = 0; 261 gint i; 262 GSList *threads = NULL; 263 DummyObject *dummy; 264 265 wrapper = gda_thread_wrapper_new (); 266 dummy = dummy_object_new (); 267 268 /* use GdaThreadWrapper from several threads */ 269 for (i = 0; i < NTHREADS; i++) { 270 GThread *th; 271 th = g_thread_new ("th", (GThreadFunc) t2_main_thread_func, dummy); 272 if (!th) { 273 g_print ("Can't create thread %d (not part of the test)\n", i); 274 exit (1); 275 } 276 threads = g_slist_prepend (threads, th); 277 } 278 279 /* join the threads */ 280 GSList *list; 281 for (list = threads; list; list = list->next) { 282 g_signal_emit_by_name (dummy, "sig0", NULL); /* this signal should be ignored */ 283 failures += GPOINTER_TO_INT (g_thread_join ((GThread*) list->data)); 284 } 285 g_slist_free (threads); 286 287 g_object_unref (wrapper); 288 g_object_unref (dummy); 289 290 return failures; 291 } 292 293 /* 294 * structure to hold information about either a signal sent or received 295 */ 296 typedef struct { 297 gchar *name; 298 guint n_param_values; 299 GValue *param_values; /* array of GValue structures */ 300 } TestSignal; 301 302 /* 303 * ... is a list of GType and value as native type (there must be exactly @n_param_values pairs) 304 */ 305 static TestSignal * 306 test_signal_new (const gchar *signame, guint n_param_values, ...) 307 { 308 TestSignal *ts; 309 va_list ap; 310 guint i; 311 312 ts = g_new0 (TestSignal, 1); 313 ts->name = g_strdup (signame); 314 ts->n_param_values = n_param_values; 315 ts->param_values = g_new0 (GValue, n_param_values); 316 317 va_start (ap, n_param_values); 318 for (i = 0; i < n_param_values; i++) { 319 GValue *value; 320 GType type; 321 type = va_arg (ap, GType); 322 323 value = ts->param_values + i; 324 g_value_init (value, type); 325 if (type == G_TYPE_INT) { 326 gint v; 327 v = va_arg (ap, gint); 328 g_value_set_int (value, v); 329 } 330 else if (type == G_TYPE_STRING) { 331 gchar *v; 332 v = va_arg (ap, gchar *); 333 g_value_set_string (value, v); 334 } 335 else 336 g_assert_not_reached (); 337 } 338 va_end (ap); 339 340 return ts; 341 } 342 343 /* 344 * Returns: TRUE if lists are equal 345 */ 346 static gboolean 347 compare_signals_lists (GSList *explist, GSList *gotlist) 348 { 349 GSList *elist, *glist; 350 for (elist = explist, glist = gotlist; 351 elist && glist; 352 elist = elist->next, glist = glist->next) { 353 TestSignal *es = (TestSignal*) elist->data; 354 TestSignal *gs = (TestSignal*) glist->data; 355 356 if (strcmp (es->name, gs->name)) { 357 g_print ("Error: expected signal '%s', got signal '%s'\n", es->name, gs->name); 358 return FALSE; 359 } 360 if (es->n_param_values != gs->n_param_values) { 361 g_print ("Error: expected %d arguments in '%s', got %d\n", es->n_param_values, 362 es->name, gs->n_param_values); 363 return FALSE; 364 } 365 guint i; 366 for (i = 0; i < es->n_param_values; i++) { 367 GValue *ev, *gv; 368 ev = es->param_values + i; 369 gv = gs->param_values + i; 370 if (gda_value_differ (ev, gv)) { 371 g_print ("Error: expected value %s in '%s', got %s\n", 372 gda_value_stringify (ev), es->name, gda_value_stringify (gv)); 373 return FALSE; 374 } 375 } 376 /*g_print ("Checked signal %s\n", es->name);*/ 377 } 378 379 if (elist) { 380 g_print ("Error: Some signals have not been received:\n"); 381 for (; elist; elist = elist->next) { 382 TestSignal *es = (TestSignal*) elist->data; 383 guint i; 384 g_print ("\tSignal: %s", es->name); 385 for (i = 0; i < es->n_param_values; i++) 386 g_print (" %s", gda_value_stringify (es->param_values + i)); 387 g_print ("\n"); 388 } 389 return FALSE; 390 } 391 392 if (glist) { 393 g_print ("Error: Received too many signals:\n"); 394 for (; glist; glist = glist->next) { 395 TestSignal *gs = (TestSignal*) glist->data; 396 guint i; 397 g_print ("\tSignal: %s", gs->name); 398 for (i = 0; i < gs->n_param_values; i++) 399 g_print (" %s", gda_value_stringify (gs->param_values + i)); 400 g_print ("\n"); 401 } 402 return FALSE; 403 } 404 405 return TRUE; 406 } 407 408 static gpointer 409 t2_exec_in_wrapped_thread (t2ExecData *data, GError **error) 410 { 411 #ifdef PRINT_CALLS 412 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 413 #endif 414 g_signal_emit_by_name (data->dummy, "sig0", NULL); 415 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 416 417 #ifdef PRINT_CALLS 418 g_print ("TH %p ** emit sig1 (dummy=>%p, i=>123)\n", g_thread_self (), data->dummy); 419 #endif 420 g_signal_emit_by_name (data->dummy, "sig1", 123, NULL); 421 add_to_signals_sent (data, test_signal_new ("sig1", 1, G_TYPE_INT, 123)); 422 423 #ifdef PRINT_CALLS 424 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 425 #endif 426 g_signal_emit_by_name (data->dummy, "sig0", NULL); 427 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 428 429 #ifdef PRINT_CALLS 430 g_print ("TH %p ** emit sig2 (dummy=>%p, i=>456 str=>Hello)\n", g_thread_self (), data->dummy); 431 #endif 432 g_signal_emit_by_name (data->dummy, "sig2", 456, "Hello", NULL); 433 add_to_signals_sent (data, test_signal_new ("sig2", 2, G_TYPE_INT, 456, G_TYPE_STRING, "Hello")); 434 435 #ifdef PRINT_CALLS 436 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 437 #endif 438 g_signal_emit_by_name (data->dummy, "sig0", NULL); 439 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 440 441 #ifdef PRINT_CALLS 442 g_print ("TH %p ** emit sig1 (dummy=>%p, i=>789)\n", g_thread_self (), data->dummy); 443 #endif 444 g_signal_emit_by_name (data->dummy, "sig1", 789, NULL); 445 add_to_signals_sent (data, test_signal_new ("sig1", 1, G_TYPE_INT, 789)); 446 447 #ifdef PRINT_CALLS 448 g_print ("TH %p ** emit sig2 (dummy=>%p, i=>32 str=>World)\n", g_thread_self (), data->dummy); 449 #endif 450 g_signal_emit_by_name (data->dummy, "sig2", 32, "World", NULL); 451 add_to_signals_sent (data, test_signal_new ("sig2", 2, G_TYPE_INT, 32, G_TYPE_STRING, "World")); 452 453 return GINT_TO_POINTER (INT_TOKEN); 454 } 455 456 static void 457 t2_exec_in_wrapped_thread_v (t2ExecData *data, GError **error) 458 { 459 #ifdef PRINT_CALLS 460 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 461 #endif 462 g_signal_emit_by_name (data->dummy, "sig0", NULL); 463 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 464 465 #ifdef PRINT_CALLS 466 g_print ("TH %p ** emit sig1 (dummy=>%p, i=>321)\n", g_thread_self (), data->dummy); 467 #endif 468 g_signal_emit_by_name (data->dummy, "sig1", 321, NULL); 469 add_to_signals_sent (data, test_signal_new ("sig1", 1, G_TYPE_INT, 321)); 470 471 #ifdef PRINT_CALLS 472 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 473 #endif 474 g_signal_emit_by_name (data->dummy, "sig0", NULL); 475 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 476 477 #ifdef PRINT_CALLS 478 g_print ("TH %p ** emit sig2 (dummy=>%p, i=>654 str=>Thread)\n", g_thread_self (), data->dummy); 479 #endif 480 g_signal_emit_by_name (data->dummy, "sig2", 654, "Thread", NULL); 481 add_to_signals_sent (data, test_signal_new ("sig2", 2, G_TYPE_INT, 654, G_TYPE_STRING, "Thread")); 482 483 #ifdef PRINT_CALLS 484 g_print ("TH %p ** emit sig0 (dummy=>%p)\n", g_thread_self (), data->dummy); 485 #endif 486 g_signal_emit_by_name (data->dummy, "sig0", NULL); 487 add_to_signals_sent (data, test_signal_new ("sig0", 0)); 488 489 #ifdef PRINT_CALLS 490 g_print ("TH %p ** emit sig1 (dummy=>%p, i=>987)\n", g_thread_self (), data->dummy); 491 #endif 492 g_signal_emit_by_name (data->dummy, "sig1", 987, NULL); 493 add_to_signals_sent (data, test_signal_new ("sig1", 1, G_TYPE_INT, 987)); 494 495 #ifdef PRINT_CALLS 496 g_print ("TH %p ** emit sig2 (dummy=>%p, i=>23 str=>Thread)\n", g_thread_self (), data->dummy); 497 #endif 498 g_signal_emit_by_name (data->dummy, "sig2", 23, "Thread", NULL); 499 add_to_signals_sent (data, test_signal_new ("sig2", 2, G_TYPE_INT, 23, G_TYPE_STRING, "Thread")); 500 } 501 502 static void 503 wrapper_callback (GdaThreadWrapper *wrapper, gpointer instance, const gchar *signame, 504 gint n_param_values, const GValue *param_values, gpointer gda_reserved, GSList **sig_list) 505 { 506 gint i; 507 /* 508 g_print ("RECEIVED signal '%s' on thread %p\n", signame, g_thread_self ()); 509 for (i = 0; i < n_param_values; i++) { 510 gchar *str = gda_value_stringify (param_values + i); 511 g_print ("\tParam %d: %s\n", i, str); 512 g_free (str); 513 } 514 */ 515 516 TestSignal *ts; 517 518 ts = g_new0 (TestSignal, 1); 519 ts->name = g_strdup (signame); 520 ts->n_param_values = n_param_values; 521 ts->param_values = g_new0 (GValue, n_param_values); 522 for (i = 0; i < n_param_values; i++) { 523 GValue *dest = ts->param_values + i; 524 const GValue *src = param_values + i; 525 g_value_init (dest, G_VALUE_TYPE (src)); 526 g_value_copy (src, dest); 527 } 528 *sig_list = g_slist_append (*sig_list, ts); 529 } 530 531 static gpointer 532 t2_main_thread_func (DummyObject *dummy) 533 { 534 gint i; 535 guint *ids; 536 537 gint total_jobs = 0; 538 gint nfailed = 0; 539 540 gulong sigid[3]; 541 t2ExecData edata; 542 GSList *received_list = NULL; 543 544 /*g_print ("NEW test thread: %p\n", g_thread_self());*/ 545 sigid[0] = gda_thread_wrapper_connect_raw (wrapper, dummy, "sig0", TRUE, TRUE, 546 (GdaThreadWrapperCallback) wrapper_callback, 547 &received_list); 548 sigid[1] = gda_thread_wrapper_connect_raw (wrapper, dummy, "sig1", TRUE, TRUE, 549 (GdaThreadWrapperCallback) wrapper_callback, 550 &received_list); 551 sigid[2] = gda_thread_wrapper_connect_raw (wrapper, dummy, "sig2", TRUE, TRUE, 552 (GdaThreadWrapperCallback) wrapper_callback, 553 &received_list); 554 555 edata.dummy = dummy; 556 edata.signals_sent = NULL; 557 g_mutex_init (&edata.mutex); 558 559 ids = g_new0 (guint, NCALLS); 560 for (i = 0; i < NCALLS; i++) { 561 guint id; 562 GError *error = NULL; 563 564 /* func1 */ 565 id = gda_thread_wrapper_execute (wrapper, 566 (GdaThreadWrapperFunc) t2_exec_in_wrapped_thread, 567 &edata, NULL, &error); 568 if (id == 0) { 569 g_print ("Error in %s() for thread %p: %s\n", __FUNCTION__, g_thread_self (), 570 error && error->message ? error->message : "No detail"); 571 if (error) 572 g_error_free (error); 573 return GINT_TO_POINTER (1); 574 } 575 ids[i] = id; 576 #ifdef PRINT_CALLS 577 g_print ("--> Thread %p jobID %u\n", g_thread_self (), id); 578 #endif 579 if (rand () >= RAND_MAX / 2.) 580 g_thread_yield (); 581 582 583 if (rand () >= RAND_MAX / 2.) { 584 id = gda_thread_wrapper_execute_void (wrapper, 585 (GdaThreadWrapperVoidFunc) t2_exec_in_wrapped_thread_v, 586 &edata, 587 NULL, &error); 588 if (id == 0) { 589 g_print ("Error in %s() for thread %p: %s\n", __FUNCTION__, g_thread_self (), 590 error && error->message ? error->message : "No detail"); 591 if (error) 592 g_error_free (error); 593 return GINT_TO_POINTER (1); 594 } 595 total_jobs ++; 596 } 597 if (rand () >= RAND_MAX / 2.) 598 g_thread_yield (); 599 } 600 total_jobs += NCALLS; 601 g_thread_yield (); 602 603 /* pick up results */ 604 for (i = 0; i < NCALLS; i++) { 605 gpointer res; 606 607 g_signal_emit_by_name (dummy, "sig0", NULL); /* this signal should be ignored */ 608 609 res = gda_thread_wrapper_fetch_result (wrapper, TRUE, ids[i], NULL); 610 if (GPOINTER_TO_INT (res) != INT_TOKEN) { 611 g_print ("Error in %s() for thread %p: sub thread's exec result is wrong\n", 612 __FUNCTION__, g_thread_self ()); 613 nfailed ++; 614 } 615 #ifdef PRINT_CALLS 616 g_print ("<-- Thread %p jobID %u arg %d\n", g_thread_self (), ids[i], INT_TOKEN); 617 #endif 618 if (rand () >= RAND_MAX / 2.) 619 g_thread_yield (); 620 g_signal_emit_by_name (dummy, "sig1", 666, NULL); /* this signal should be ignored */ 621 } 622 623 while (gda_thread_wrapper_get_waiting_size (wrapper) > 0) { 624 gda_thread_wrapper_iterate (wrapper, FALSE); 625 g_usleep (10000); 626 } 627 628 g_mutex_lock (&edata.mutex); 629 if (! compare_signals_lists (edata.signals_sent, received_list)) 630 nfailed++; 631 g_mutex_unlock (&edata.mutex); 632 633 634 #ifdef PRINT_CALLS 635 g_print ("Disconnecting signals\n"); 636 #endif 637 gda_thread_wrapper_disconnect (wrapper, sigid[0]); 638 gda_thread_wrapper_disconnect (wrapper, sigid[1]); 639 gda_thread_wrapper_disconnect (wrapper, sigid[2]); 640 641 g_free (ids); 642 643 /* we don't care about mem leaks here... */ 644 received_list = NULL; 645 guint id; 646 GError *error = NULL; 647 id = gda_thread_wrapper_execute_void (wrapper, 648 (GdaThreadWrapperVoidFunc) t2_exec_in_wrapped_thread_v, 649 &edata, 650 NULL, &error); 651 if (id == 0) { 652 g_print ("Error in %s() for thread %p: %s\n", __FUNCTION__, g_thread_self (), 653 error && error->message ? error->message : "No detail"); 654 if (error) 655 g_error_free (error); 656 return GINT_TO_POINTER (1); 657 } 658 total_jobs ++; 659 660 while (gda_thread_wrapper_get_waiting_size (wrapper) > 0) { 661 gda_thread_wrapper_iterate (wrapper, FALSE); 662 g_usleep (10000); 663 } 664 g_mutex_clear (&edata.mutex); 665 666 if (received_list) { 667 g_print ("Error: signals should not be received anymore...\n"); 668 nfailed ++; 669 } 670 671 return GINT_TO_POINTER (nfailed); 672 } 673