os/ossrv/glib/tsrc/BC/tests/mainloop-test.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/glib/tsrc/BC/tests/mainloop-test.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,500 @@
     1.4 +/* Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.*/
     1.5 +#undef G_DISABLE_ASSERT
     1.6 +#undef G_LOG_DOMAIN
     1.7 +
     1.8 +
     1.9 +#include <errno.h>
    1.10 +#include <glib.h>
    1.11 +
    1.12 +#ifdef G_OS_UNIX
    1.13 +#include <unistd.h>
    1.14 +#endif
    1.15 +#include <stdio.h>
    1.16 +#include <stdlib.h>
    1.17 +
    1.18 +#ifdef G_OS_WIN32
    1.19 +#include <fcntl.h>		/* For _O_BINARY used by pipe() macro */
    1.20 +#include <io.h>			/* for _pipe() */
    1.21 +#endif
    1.22 +
    1.23 +
    1.24 +
    1.25 +#ifdef SYMBIAN
    1.26 +#include <glib_global.h>
    1.27 +#include "mrt2_glib2_test.h"
    1.28 +#endif /*SYMBIAN*/
    1.29 +
    1.30 +
    1.31 +#define ITERS 10
    1.32 +#define INCREMENT 10
    1.33 +#define NTHREADS 4
    1.34 +#define NCRAWLERS 4
    1.35 +#define CRAWLER_TIMEOUT_RANGE 40
    1.36 +#define RECURSER_TIMEOUT 50
    1.37 +
    1.38 +/* The partial ordering between the context array mutex and
    1.39 + * crawler array mutex is that the crawler array mutex cannot
    1.40 + * be locked while the context array mutex is locked
    1.41 + */
    1.42 +GPtrArray *context_array;
    1.43 +GMutex *context_array_mutex;
    1.44 +GCond *context_array_cond;
    1.45 +
    1.46 +GMainLoop *main_loop;
    1.47 +
    1.48 +G_LOCK_DEFINE_STATIC (crawler_array_lock);
    1.49 +GPtrArray *crawler_array;
    1.50 +
    1.51 +typedef struct _AddrData AddrData;
    1.52 +typedef struct _TestData TestData;
    1.53 +
    1.54 +struct _AddrData
    1.55 +{
    1.56 +  GMainLoop *loop;
    1.57 +  GIOChannel *dest;
    1.58 +  gint count;
    1.59 +};
    1.60 +
    1.61 +struct _TestData
    1.62 +{
    1.63 +  gint current_val;
    1.64 +  gint iters;
    1.65 +  GIOChannel *in;
    1.66 +};
    1.67 +
    1.68 +static void cleanup_crawlers (GMainContext *context);
    1.69 +
    1.70 +gboolean
    1.71 +read_all (GIOChannel *channel, char *buf, gsize len)
    1.72 +{
    1.73 +  gsize bytes_read = 0;
    1.74 +  gsize count;
    1.75 +  GIOError err;
    1.76 +
    1.77 +  while (bytes_read < len)
    1.78 +    {
    1.79 +      err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
    1.80 +      if (err)
    1.81 +	{
    1.82 +	  if (err != G_IO_ERROR_AGAIN)
    1.83 +	  g_assert(FALSE && "mainloop-test failed");
    1.84 +	    return FALSE;
    1.85 +	}
    1.86 +      else if (count == 0)
    1.87 +	return FALSE;
    1.88 +
    1.89 +      bytes_read += count;
    1.90 +    }
    1.91 +
    1.92 +  return TRUE;
    1.93 +}
    1.94 +
    1.95 +gboolean
    1.96 +write_all (GIOChannel *channel, char *buf, gsize len)
    1.97 +{
    1.98 +  gsize bytes_written = 0;
    1.99 +  gsize count;
   1.100 +  GIOError err;
   1.101 +
   1.102 +  while (bytes_written < len)
   1.103 +    {
   1.104 +      err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
   1.105 +      if (err && err != G_IO_ERROR_AGAIN)
   1.106 +	return FALSE;
   1.107 +
   1.108 +      bytes_written += count;
   1.109 +    }
   1.110 +
   1.111 +  return TRUE;
   1.112 +}
   1.113 +
   1.114 +gboolean
   1.115 +adder_callback (GIOChannel   *source,
   1.116 +		GIOCondition  condition,
   1.117 +		gpointer      data)
   1.118 +{
   1.119 +  char buf1[32];
   1.120 +  char buf2[32];
   1.121 +
   1.122 +  char result[32];
   1.123 +
   1.124 +  AddrData *addr_data = data;
   1.125 +
   1.126 +  if (!read_all (source, buf1, 32) ||
   1.127 +      !read_all (source, buf2, 32))
   1.128 +    {
   1.129 +      g_main_loop_quit (addr_data->loop);
   1.130 +      return FALSE;
   1.131 +    }
   1.132 +
   1.133 +  sprintf (result, "%d", atoi(buf1) + atoi(buf2));
   1.134 +  write_all (addr_data->dest, result, 32);
   1.135 +
   1.136 +  return TRUE;
   1.137 +}
   1.138 +
   1.139 +gboolean
   1.140 +timeout_callback (gpointer data)
   1.141 +{
   1.142 +  AddrData *addr_data = data;
   1.143 +
   1.144 +  addr_data->count++;
   1.145 +
   1.146 +  return TRUE;
   1.147 +}
   1.148 +
   1.149 +gpointer
   1.150 +adder_thread (gpointer data)
   1.151 +{
   1.152 +  GMainContext *context;
   1.153 +  GSource *adder_source;
   1.154 +  GSource *timeout_source;
   1.155 +
   1.156 +  GIOChannel **channels = data;
   1.157 +  AddrData addr_data;
   1.158 +
   1.159 +  context = g_main_context_new ();
   1.160 +
   1.161 +  g_assert(context != NULL);
   1.162 +
   1.163 +  g_mutex_lock (context_array_mutex);
   1.164 +
   1.165 +  g_ptr_array_add (context_array, context);
   1.166 +
   1.167 +  if (context_array->len == NTHREADS)
   1.168 +    g_cond_broadcast (context_array_cond);
   1.169 +
   1.170 +  g_mutex_unlock (context_array_mutex);
   1.171 +
   1.172 +  addr_data.dest = channels[1];
   1.173 +  addr_data.loop = g_main_loop_new (context, FALSE);
   1.174 +  addr_data.count = 0;
   1.175 +
   1.176 +  adder_source = g_io_create_watch (channels[0], G_IO_IN | G_IO_HUP);
   1.177 +
   1.178 +  g_assert(adder_source != NULL);
   1.179 +
   1.180 +  g_source_set_callback (adder_source, (GSourceFunc)adder_callback, &addr_data, NULL);
   1.181 +  g_source_attach (adder_source, context);
   1.182 +  g_source_unref (adder_source);
   1.183 +
   1.184 +  timeout_source = g_timeout_source_new (10);
   1.185 +
   1.186 +  g_assert(timeout_source != NULL);
   1.187 +
   1.188 +  g_source_set_callback (timeout_source, (GSourceFunc)timeout_callback, &addr_data, NULL);
   1.189 +  g_source_set_priority (timeout_source, G_PRIORITY_HIGH);
   1.190 +  g_source_attach (timeout_source, context);
   1.191 +  g_source_unref (timeout_source);
   1.192 +
   1.193 +  g_main_loop_run (addr_data.loop);
   1.194 +
   1.195 +  g_io_channel_unref (channels[0]);
   1.196 +  g_io_channel_unref (channels[1]);
   1.197 +
   1.198 +  g_free (channels);
   1.199 +
   1.200 +  g_main_loop_unref (addr_data.loop);
   1.201 +
   1.202 +#ifdef VERBOSE
   1.203 +  g_print ("Timeout run %d times\n", addr_data.count);
   1.204 +#endif
   1.205 +
   1.206 +  g_mutex_lock (context_array_mutex);
   1.207 +  g_ptr_array_remove (context_array, context);
   1.208 +  if (context_array->len == 0)
   1.209 +    g_main_loop_quit (main_loop);
   1.210 +  g_mutex_unlock (context_array_mutex);
   1.211 +
   1.212 +  cleanup_crawlers (context);
   1.213 +
   1.214 +  return NULL;
   1.215 +}
   1.216 +
   1.217 +
   1.218 +void
   1.219 +io_pipe (GIOChannel **channels)
   1.220 +{
   1.221 +  gint fds[2];
   1.222 +
   1.223 +  if (pipe(fds) < 0)
   1.224 +    {
   1.225 +      g_warning ("Cannot create pipe %s\n", g_strerror (errno));
   1.226 +
   1.227 +      g_assert(FALSE && "mainloop-test failed");
   1.228 +
   1.229 +      exit (1);
   1.230 +    }
   1.231 +
   1.232 +  channels[0] = g_io_channel_unix_new (fds[0]);
   1.233 +  channels[1] = g_io_channel_unix_new (fds[1]);
   1.234 +
   1.235 +  g_io_channel_set_close_on_unref (channels[0], TRUE);
   1.236 +  g_io_channel_set_close_on_unref (channels[1], TRUE);
   1.237 +}
   1.238 +
   1.239 +void
   1.240 +do_add (GIOChannel *in, gint a, gint b)
   1.241 +{
   1.242 +  char buf1[32];
   1.243 +  char buf2[32];
   1.244 +
   1.245 +  sprintf (buf1, "%d", a);
   1.246 +  sprintf (buf2, "%d", b);
   1.247 +
   1.248 +  write_all (in, buf1, 32);
   1.249 +  write_all (in, buf2, 32);
   1.250 +}
   1.251 +
   1.252 +gboolean
   1.253 +adder_response (GIOChannel   *source,
   1.254 +		GIOCondition  condition,
   1.255 +		gpointer      data)
   1.256 +{
   1.257 +  char result[32];
   1.258 +  TestData *test_data = data;
   1.259 +
   1.260 +  if (!read_all (source, result, 32))
   1.261 +    return FALSE;
   1.262 +
   1.263 +  test_data->current_val = atoi (result);
   1.264 +  test_data->iters--;
   1.265 +
   1.266 +  if (test_data->iters == 0)
   1.267 +    {
   1.268 +      if (test_data->current_val != ITERS * INCREMENT)
   1.269 +	{
   1.270 +	  g_print ("Addition failed: %d != %d\n",
   1.271 +		   test_data->current_val, ITERS * INCREMENT);
   1.272 +
   1.273 +	  g_assert(FALSE && "mainloop-test failed");
   1.274 +
   1.275 +	  exit (1);
   1.276 +	}
   1.277 +
   1.278 +      g_io_channel_unref (source);
   1.279 +      g_io_channel_unref (test_data->in);
   1.280 +
   1.281 +      g_free (test_data);
   1.282 +
   1.283 +      return FALSE;
   1.284 +    }
   1.285 +
   1.286 +  do_add (test_data->in, test_data->current_val, INCREMENT);
   1.287 +
   1.288 +  return TRUE;
   1.289 +}
   1.290 +
   1.291 +void
   1.292 +create_adder_thread (void)
   1.293 +{
   1.294 +  GError *err = NULL;
   1.295 +  TestData *test_data;
   1.296 +  GThread *thread;
   1.297 +
   1.298 +  GIOChannel *in_channels[2];
   1.299 +  GIOChannel *out_channels[2];
   1.300 +
   1.301 +  GIOChannel **sub_channels;
   1.302 +
   1.303 +  sub_channels = g_new (GIOChannel *, 2);
   1.304 +
   1.305 +  io_pipe (in_channels);
   1.306 +  io_pipe (out_channels);
   1.307 +
   1.308 +  sub_channels[0] = in_channels[0];
   1.309 +  sub_channels[1] = out_channels[1];
   1.310 +
   1.311 +  g_thread_create (adder_thread, sub_channels, FALSE, &err);
   1.312 +
   1.313 +  if (err)
   1.314 +    {
   1.315 +      g_warning ("Cannot create thread: %s", err->message);
   1.316 +
   1.317 +      g_assert(FALSE && "mainloop-test failed");
   1.318 +
   1.319 +      exit (1);
   1.320 +    }
   1.321 +
   1.322 +  test_data = g_new (TestData, 1);
   1.323 +  test_data->in = in_channels[1];
   1.324 +  test_data->current_val = 0;
   1.325 +  test_data->iters = ITERS;
   1.326 +
   1.327 +  g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
   1.328 +		  adder_response, test_data);
   1.329 +
   1.330 +  do_add (test_data->in, test_data->current_val, INCREMENT);
   1.331 +}
   1.332 +
   1.333 +static void create_crawler (void);
   1.334 +
   1.335 +static void
   1.336 +remove_crawler (void)
   1.337 +{
   1.338 +  GSource *other_source;
   1.339 +
   1.340 +  if (crawler_array->len > 0)
   1.341 +    {
   1.342 +      other_source = crawler_array->pdata[g_random_int_range (0, crawler_array->len)];
   1.343 +      g_source_destroy (other_source);
   1.344 +      g_assert (g_ptr_array_remove_fast (crawler_array, other_source));
   1.345 +    }
   1.346 +}
   1.347 +
   1.348 +static gint
   1.349 +crawler_callback (gpointer data)
   1.350 +{
   1.351 +  GSource *source = data;
   1.352 +
   1.353 +  G_LOCK (crawler_array_lock);
   1.354 +
   1.355 +  if (!g_ptr_array_remove_fast (crawler_array, source))
   1.356 +    remove_crawler();
   1.357 +
   1.358 +  remove_crawler();
   1.359 +  G_UNLOCK (crawler_array_lock);
   1.360 +
   1.361 +  create_crawler();
   1.362 +  //create_crawler();
   1.363 +
   1.364 +  return FALSE;
   1.365 +}
   1.366 +
   1.367 +static void
   1.368 +create_crawler (void)
   1.369 +{
   1.370 +  GSource *source = g_timeout_source_new (g_random_int_range (0, CRAWLER_TIMEOUT_RANGE));
   1.371 +
   1.372 +  g_assert(source != NULL);
   1.373 +
   1.374 +  g_source_set_callback (source, (GSourceFunc)crawler_callback, source, NULL);
   1.375 +
   1.376 +  G_LOCK (crawler_array_lock);
   1.377 +  g_ptr_array_add (crawler_array, source);
   1.378 +
   1.379 +  g_mutex_lock (context_array_mutex);
   1.380 +  if(context_array->len == 0)
   1.381 +  	g_source_attach (source, context_array->pdata[0]);
   1.382 +  else
   1.383 +  	g_source_attach (source, context_array->pdata[g_random_int_range (0, context_array->len)]);
   1.384 +  g_source_unref (source);
   1.385 +  g_mutex_unlock (context_array_mutex);
   1.386 +
   1.387 +  G_UNLOCK (crawler_array_lock);
   1.388 +}
   1.389 +
   1.390 +static void
   1.391 +cleanup_crawlers (GMainContext *context)
   1.392 +{
   1.393 +  gint i;
   1.394 +
   1.395 +  G_LOCK (crawler_array_lock);
   1.396 +  for (i=0; i < crawler_array->len; i++)
   1.397 +    {
   1.398 +      if (g_source_get_context (crawler_array->pdata[i]) == context)
   1.399 +	{
   1.400 +	  g_source_destroy (g_ptr_array_remove_index (crawler_array, i));
   1.401 +	  i--;
   1.402 +	}
   1.403 +    }
   1.404 +  G_UNLOCK (crawler_array_lock);
   1.405 +}
   1.406 +
   1.407 +static gboolean
   1.408 +recurser_idle (gpointer data)
   1.409 +{
   1.410 +  GMainContext *context = data;
   1.411 +  gint i;
   1.412 +
   1.413 +  for (i = 0; i < 10; i++)
   1.414 +    g_main_context_iteration (context, FALSE);
   1.415 +
   1.416 +  return FALSE;
   1.417 +}
   1.418 +
   1.419 +static gboolean
   1.420 +recurser_start (gpointer data)
   1.421 +{
   1.422 +  GMainContext *context;
   1.423 +  GSource *source;
   1.424 +
   1.425 +  g_mutex_lock (context_array_mutex);
   1.426 +
   1.427 +  if(context_array->len == 0)
   1.428 +  	context = context_array->pdata[0];
   1.429 +  else
   1.430 +  	context = context_array->pdata[g_random_int_range (0, context_array->len)];
   1.431 +  source = g_idle_source_new ();
   1.432 +  g_source_set_callback (source, recurser_idle, context, NULL);
   1.433 +  g_source_attach (source, context);
   1.434 +  g_source_unref (source);
   1.435 +  g_mutex_unlock (context_array_mutex);
   1.436 +
   1.437 +  return TRUE;
   1.438 +}
   1.439 +
   1.440 +int
   1.441 +main (int   argc,
   1.442 +      char *argv[])
   1.443 +{
   1.444 +  /* Only run the test, if threads are enabled and a default thread
   1.445 +     implementation is available */
   1.446 +#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
   1.447 +  gint i;
   1.448 +
   1.449 +  #ifdef SYMBIAN
   1.450 +  g_log_set_handler (NULL,  G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_INFO | G_LOG_LEVEL_DEBUG, &mrtLogHandler, NULL);
   1.451 +  g_set_print_handler(mrtPrintHandler);
   1.452 +  #endif /*SYMBIAN*/
   1.453 +#if 0
   1.454 +  g_thread_init (NULL);
   1.455 +
   1.456 +  context_array = g_ptr_array_new ();
   1.457 +
   1.458 +  g_assert(context_array != NULL);
   1.459 +
   1.460 +  context_array_mutex = g_mutex_new ();
   1.461 +
   1.462 +  g_assert(context_array_mutex != NULL);
   1.463 +
   1.464 +  context_array_cond = g_cond_new ();
   1.465 +
   1.466 +  g_assert(context_array_cond != NULL);
   1.467 +
   1.468 +  crawler_array = g_ptr_array_new ();
   1.469 +
   1.470 +  g_assert(crawler_array != NULL);
   1.471 +
   1.472 +  main_loop = g_main_loop_new (NULL, FALSE);
   1.473 +
   1.474 +  g_assert(main_loop != NULL);
   1.475 +
   1.476 +  for (i = 0; i < NTHREADS; i++)
   1.477 +    create_adder_thread ();
   1.478 +
   1.479 +  /* Wait for all threads to start
   1.480 +   */
   1.481 +  g_mutex_lock (context_array_mutex);
   1.482 +
   1.483 +  if (context_array->len < NTHREADS)
   1.484 +    g_cond_wait (context_array_cond, context_array_mutex);
   1.485 +
   1.486 +  g_mutex_unlock (context_array_mutex);
   1.487 +
   1.488 +  for (i = 0; i < NCRAWLERS; i++)
   1.489 +    create_crawler ();
   1.490 +
   1.491 +  g_timeout_add (RECURSER_TIMEOUT, recurser_start, NULL);
   1.492 +
   1.493 +  g_main_loop_run (main_loop);
   1.494 +  g_main_loop_unref (main_loop);
   1.495 +#endif
   1.496 +#endif
   1.497 +
   1.498 +  #ifdef SYMBIAN
   1.499 +  testResultXml("mainloop-test");
   1.500 +  #endif /* EMULATOR */
   1.501 +
   1.502 +  return 0;
   1.503 +}