diff -r 61e9400fe245 -r 0cb2248d0edc apicompatanamdw/bcdrivers/os/ossrv/glib/tests/mainloop-test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/apicompatanamdw/bcdrivers/os/ossrv/glib/tests/mainloop-test.c Thu Apr 22 17:15:08 2010 +0530 @@ -0,0 +1,515 @@ +/* +* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ +#undef G_DISABLE_ASSERT +#undef G_LOG_DOMAIN + + +#include +#include + +#ifdef G_OS_UNIX +#include +#endif +#include +#include + +#ifdef G_OS_WIN32 +#include /* For _O_BINARY used by pipe() macro */ +#include /* for _pipe() */ +#endif + + + +#ifdef SYMBIAN +#include +#include "mrt2_glib2_test.h" +#endif /*SYMBIAN*/ + + +#define ITERS 10 +#define INCREMENT 10 +#define NTHREADS 4 +#define NCRAWLERS 4 +#define CRAWLER_TIMEOUT_RANGE 40 +#define RECURSER_TIMEOUT 50 + +/* The partial ordering between the context array mutex and + * crawler array mutex is that the crawler array mutex cannot + * be locked while the context array mutex is locked + */ +GPtrArray *context_array; +GMutex *context_array_mutex; +GCond *context_array_cond; + +GMainLoop *main_loop; + +G_LOCK_DEFINE_STATIC (crawler_array_lock); +GPtrArray *crawler_array; + +typedef struct _AddrData AddrData; +typedef struct _TestData TestData; + +struct _AddrData +{ + GMainLoop *loop; + GIOChannel *dest; + gint count; +}; + +struct _TestData +{ + gint current_val; + gint iters; + GIOChannel *in; +}; + +static void cleanup_crawlers (GMainContext *context); + +gboolean +read_all (GIOChannel *channel, char *buf, gsize len) +{ + gsize bytes_read = 0; + gsize count; + GIOError err; + + while (bytes_read < len) + { + err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count); + if (err) + { + if (err != G_IO_ERROR_AGAIN) + g_assert(FALSE && "mainloop-test failed"); + return FALSE; + } + else if (count == 0) + return FALSE; + + bytes_read += count; + } + + return TRUE; +} + +gboolean +write_all (GIOChannel *channel, char *buf, gsize len) +{ + gsize bytes_written = 0; + gsize count; + GIOError err; + + while (bytes_written < len) + { + err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count); + if (err && err != G_IO_ERROR_AGAIN) + return FALSE; + + bytes_written += count; + } + + return TRUE; +} + +gboolean +adder_callback (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + char buf1[32]; + char buf2[32]; + + char result[32]; + + AddrData *addr_data = data; + + if (!read_all (source, buf1, 32) || + !read_all (source, buf2, 32)) + { + g_main_loop_quit (addr_data->loop); + return FALSE; + } + + sprintf (result, "%d", atoi(buf1) + atoi(buf2)); + write_all (addr_data->dest, result, 32); + + return TRUE; +} + +gboolean +timeout_callback (gpointer data) +{ + AddrData *addr_data = data; + + addr_data->count++; + + return TRUE; +} + +gpointer +adder_thread (gpointer data) +{ + GMainContext *context; + GSource *adder_source; + GSource *timeout_source; + + GIOChannel **channels = data; + AddrData addr_data; + + context = g_main_context_new (); + + g_assert(context != NULL); + + g_mutex_lock (context_array_mutex); + + g_ptr_array_add (context_array, context); + + if (context_array->len == NTHREADS) + g_cond_broadcast (context_array_cond); + + g_mutex_unlock (context_array_mutex); + + addr_data.dest = channels[1]; + addr_data.loop = g_main_loop_new (context, FALSE); + addr_data.count = 0; + + adder_source = g_io_create_watch (channels[0], G_IO_IN | G_IO_HUP); + + g_assert(adder_source != NULL); + + g_source_set_callback (adder_source, (GSourceFunc)adder_callback, &addr_data, NULL); + g_source_attach (adder_source, context); + g_source_unref (adder_source); + + timeout_source = g_timeout_source_new (10); + + g_assert(timeout_source != NULL); + + g_source_set_callback (timeout_source, (GSourceFunc)timeout_callback, &addr_data, NULL); + g_source_set_priority (timeout_source, G_PRIORITY_HIGH); + g_source_attach (timeout_source, context); + g_source_unref (timeout_source); + + g_main_loop_run (addr_data.loop); + + g_io_channel_unref (channels[0]); + g_io_channel_unref (channels[1]); + + g_free (channels); + + g_main_loop_unref (addr_data.loop); + +#ifdef VERBOSE + g_print ("Timeout run %d times\n", addr_data.count); +#endif + + g_mutex_lock (context_array_mutex); + g_ptr_array_remove (context_array, context); + if (context_array->len == 0) + g_main_loop_quit (main_loop); + g_mutex_unlock (context_array_mutex); + + cleanup_crawlers (context); + + return NULL; +} + + +void +io_pipe (GIOChannel **channels) +{ + gint fds[2]; + + if (pipe(fds) < 0) + { + g_warning ("Cannot create pipe %s\n", g_strerror (errno)); + + g_assert(FALSE && "mainloop-test failed"); + + exit (1); + } + + channels[0] = g_io_channel_unix_new (fds[0]); + channels[1] = g_io_channel_unix_new (fds[1]); + + g_io_channel_set_close_on_unref (channels[0], TRUE); + g_io_channel_set_close_on_unref (channels[1], TRUE); +} + +void +do_add (GIOChannel *in, gint a, gint b) +{ + char buf1[32]; + char buf2[32]; + + sprintf (buf1, "%d", a); + sprintf (buf2, "%d", b); + + write_all (in, buf1, 32); + write_all (in, buf2, 32); +} + +gboolean +adder_response (GIOChannel *source, + GIOCondition condition, + gpointer data) +{ + char result[32]; + TestData *test_data = data; + + if (!read_all (source, result, 32)) + return FALSE; + + test_data->current_val = atoi (result); + test_data->iters--; + + if (test_data->iters == 0) + { + if (test_data->current_val != ITERS * INCREMENT) + { + g_print ("Addition failed: %d != %d\n", + test_data->current_val, ITERS * INCREMENT); + + g_assert(FALSE && "mainloop-test failed"); + + exit (1); + } + + g_io_channel_unref (source); + g_io_channel_unref (test_data->in); + + g_free (test_data); + + return FALSE; + } + + do_add (test_data->in, test_data->current_val, INCREMENT); + + return TRUE; +} + +void +create_adder_thread (void) +{ + GError *err = NULL; + TestData *test_data; + GThread *thread; + + GIOChannel *in_channels[2]; + GIOChannel *out_channels[2]; + + GIOChannel **sub_channels; + + sub_channels = g_new (GIOChannel *, 2); + + io_pipe (in_channels); + io_pipe (out_channels); + + sub_channels[0] = in_channels[0]; + sub_channels[1] = out_channels[1]; + + g_thread_create (adder_thread, sub_channels, FALSE, &err); + + if (err) + { + g_warning ("Cannot create thread: %s", err->message); + + g_assert(FALSE && "mainloop-test failed"); + + exit (1); + } + + test_data = g_new (TestData, 1); + test_data->in = in_channels[1]; + test_data->current_val = 0; + test_data->iters = ITERS; + + g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP, + adder_response, test_data); + + do_add (test_data->in, test_data->current_val, INCREMENT); +} + +static void create_crawler (void); + +static void +remove_crawler (void) +{ + GSource *other_source; + + if (crawler_array->len > 0) + { + other_source = crawler_array->pdata[g_random_int_range (0, crawler_array->len)]; + g_source_destroy (other_source); + g_assert (g_ptr_array_remove_fast (crawler_array, other_source)); + } +} + +static gint +crawler_callback (gpointer data) +{ + GSource *source = data; + + G_LOCK (crawler_array_lock); + + if (!g_ptr_array_remove_fast (crawler_array, source)) + remove_crawler(); + + remove_crawler(); + G_UNLOCK (crawler_array_lock); + + create_crawler(); + //create_crawler(); + + return FALSE; +} + +static void +create_crawler (void) +{ + GSource *source = g_timeout_source_new (g_random_int_range (0, CRAWLER_TIMEOUT_RANGE)); + + g_assert(source != NULL); + + g_source_set_callback (source, (GSourceFunc)crawler_callback, source, NULL); + + G_LOCK (crawler_array_lock); + g_ptr_array_add (crawler_array, source); + + g_mutex_lock (context_array_mutex); + if(context_array->len == 0) + g_source_attach (source, context_array->pdata[0]); + else + g_source_attach (source, context_array->pdata[g_random_int_range (0, context_array->len)]); + g_source_unref (source); + g_mutex_unlock (context_array_mutex); + + G_UNLOCK (crawler_array_lock); +} + +static void +cleanup_crawlers (GMainContext *context) +{ + gint i; + + G_LOCK (crawler_array_lock); + for (i=0; i < crawler_array->len; i++) + { + if (g_source_get_context (crawler_array->pdata[i]) == context) + { + g_source_destroy (g_ptr_array_remove_index (crawler_array, i)); + i--; + } + } + G_UNLOCK (crawler_array_lock); +} + +static gboolean +recurser_idle (gpointer data) +{ + GMainContext *context = data; + gint i; + + for (i = 0; i < 10; i++) + g_main_context_iteration (context, FALSE); + + return FALSE; +} + +static gboolean +recurser_start (gpointer data) +{ + GMainContext *context; + GSource *source; + + g_mutex_lock (context_array_mutex); + + if(context_array->len == 0) + context = context_array->pdata[0]; + else + context = context_array->pdata[g_random_int_range (0, context_array->len)]; + source = g_idle_source_new (); + g_source_set_callback (source, recurser_idle, context, NULL); + g_source_attach (source, context); + g_source_unref (source); + g_mutex_unlock (context_array_mutex); + + return TRUE; +} + +int +main (int argc, + char *argv[]) +{ + /* Only run the test, if threads are enabled and a default thread + implementation is available */ +#if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE) + gint i; + + #ifdef SYMBIAN + 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); + g_set_print_handler(mrtPrintHandler); + #endif /*SYMBIAN*/ +#if 0 + g_thread_init (NULL); + + context_array = g_ptr_array_new (); + + g_assert(context_array != NULL); + + context_array_mutex = g_mutex_new (); + + g_assert(context_array_mutex != NULL); + + context_array_cond = g_cond_new (); + + g_assert(context_array_cond != NULL); + + crawler_array = g_ptr_array_new (); + + g_assert(crawler_array != NULL); + + main_loop = g_main_loop_new (NULL, FALSE); + + g_assert(main_loop != NULL); + + for (i = 0; i < NTHREADS; i++) + create_adder_thread (); + + /* Wait for all threads to start + */ + g_mutex_lock (context_array_mutex); + + if (context_array->len < NTHREADS) + g_cond_wait (context_array_cond, context_array_mutex); + + g_mutex_unlock (context_array_mutex); + + for (i = 0; i < NCRAWLERS; i++) + create_crawler (); + + g_timeout_add (RECURSER_TIMEOUT, recurser_start, NULL); + + g_main_loop_run (main_loop); + g_main_loop_unref (main_loop); +#endif +#endif + + #ifdef SYMBIAN + testResultXml("mainloop-test"); + #endif /* EMULATOR */ + + return 0; +}