sl@0: /* Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.*/
sl@0: #undef G_DISABLE_ASSERT
sl@0: #undef G_LOG_DOMAIN
sl@0: 
sl@0: #include <errno.h>
sl@0: #include <stdlib.h>
sl@0: #include <unistd.h>
sl@0: #include <stdio.h>
sl@0: #include <sys/time.h>
sl@0: #include <sys/resource.h>
sl@0: 
sl@0: #include <glib.h>
sl@0: 
sl@0: #ifdef SYMBIAN
sl@0: #include <glib_global.h>
sl@0: #include "mrt2_glib2_test.h"
sl@0: #endif /*SYMBIAN*/
sl@0: 
sl@0: 
sl@0: static int n_children = 4;
sl@0: static int n_active_children;
sl@0: static int n_iters = 5;
sl@0: static GMainLoop *loop;
sl@0: 
sl@0: static void
sl@0: io_pipe (GIOChannel **channels)
sl@0: {
sl@0:   int fds[2];
sl@0: 
sl@0:   if (pipe(fds) < 0)
sl@0:     {
sl@0:       g_print ("Cannot create pipe %s\n", g_strerror (errno));
sl@0:       g_assert(FALSE && "timeloop failed");  
sl@0:     
sl@0: #ifdef SYMBIAN
sl@0:   testResultXml("timeloop");
sl@0: #endif /* EMULATOR */
sl@0:       exit (1);
sl@0:     }
sl@0: 
sl@0:   channels[0] = g_io_channel_unix_new (fds[0]);
sl@0:   channels[1] = g_io_channel_unix_new (fds[1]);
sl@0: }
sl@0: 
sl@0: static gboolean
sl@0: read_all (GIOChannel *channel, char *buf, int len)
sl@0: {
sl@0:   gsize bytes_read = 0;
sl@0:   gsize count;
sl@0:   GIOError err;
sl@0: 
sl@0:   while (bytes_read < len)
sl@0:     {
sl@0:       err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
sl@0:       if (err)
sl@0: 	{
sl@0: 	  if (err != G_IO_ERROR_AGAIN)
sl@0: 	  {
sl@0: 	  	g_assert(FALSE && "timeloop failed");
sl@0: 	    return FALSE;
sl@0: 	  }
sl@0: 	}
sl@0:       else if (count == 0)
sl@0: 	return FALSE;
sl@0: 
sl@0:       bytes_read += count;
sl@0:     }
sl@0: 
sl@0:   return TRUE;
sl@0: }
sl@0: 
sl@0: static gboolean
sl@0: write_all (GIOChannel *channel, char *buf, int len)
sl@0: {
sl@0:   gsize bytes_written = 0;
sl@0:   gsize count;
sl@0:   GIOError err;
sl@0: 
sl@0:   while (bytes_written < len)
sl@0:     {
sl@0:       err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
sl@0:       if (err && err != G_IO_ERROR_AGAIN)
sl@0: 	return FALSE;
sl@0: 
sl@0:       bytes_written += count;
sl@0:     }
sl@0: 
sl@0:   return TRUE;
sl@0: }
sl@0: 
sl@0: gpointer
sl@0: run_child (gpointer data)
sl@0: {
sl@0:   int i;
sl@0:   int val = 1;
sl@0:   GIOChannel *in_channel,*out_channel;
sl@0:   GTimer *timer = g_timer_new();
sl@0:   
sl@0:   GIOChannel **channels = data;
sl@0:   
sl@0:   in_channel = channels[0];
sl@0:   out_channel = channels[1];
sl@0: 
sl@0:   for (i = 0; i < n_iters; i++)
sl@0:     {
sl@0:       write_all (out_channel, (char *)&val, sizeof (val));
sl@0:       read_all (in_channel, (char *)&val, sizeof (val));
sl@0:     }
sl@0: 
sl@0:   val = 0;
sl@0:   write_all (out_channel, (char *)&val, sizeof (val));
sl@0: 
sl@0:   val = g_timer_elapsed (timer, NULL) * 1000;
sl@0:   
sl@0:   write_all (out_channel, (char *)&val, sizeof (val));
sl@0:   g_timer_destroy (timer);
sl@0: 
sl@0:   return NULL;
sl@0: }
sl@0: 
sl@0: static gboolean
sl@0: input_callback (GIOChannel   *source,
sl@0: 		GIOCondition  condition,
sl@0: 		gpointer      data)
sl@0: {
sl@0:   int val;
sl@0:   GIOChannel *dest = (GIOChannel *)data;
sl@0:   
sl@0:   if (!read_all (source, (char *)&val, sizeof(val)))
sl@0:     {
sl@0:       g_print("Unexpected EOF\n");
sl@0:       g_assert(FALSE && "timeloop failed");
sl@0:     #ifdef SYMBIAN
sl@0:   testResultXml("timeloop");
sl@0: #endif /* EMULATOR */
sl@0:       exit (1);
sl@0:     }
sl@0: 
sl@0:   if (val)
sl@0:     {
sl@0:       write_all (dest, (char *)&val, sizeof(val));
sl@0:       
sl@0:       return TRUE;
sl@0:     }
sl@0:   else
sl@0:     {
sl@0:       g_io_channel_close (source);
sl@0:       g_io_channel_close (dest);
sl@0:       
sl@0:       g_io_channel_unref (source);
sl@0:       g_io_channel_unref (dest);
sl@0: 
sl@0:       n_active_children--;
sl@0:       if (n_active_children == 0)
sl@0: 	g_main_loop_quit (loop);
sl@0:       
sl@0:       return FALSE;
sl@0:     }
sl@0: }
sl@0: 
sl@0: static void
sl@0: create_child (void)
sl@0: {
sl@0:   GError *err = NULL;
sl@0:   GIOChannel *in_channels[2];
sl@0:   GIOChannel *out_channels[2];
sl@0:   
sl@0:   GIOChannel **sub_channels;
sl@0:   
sl@0:   sub_channels = g_new (GIOChannel *, 2);
sl@0:   
sl@0:   io_pipe (in_channels);
sl@0:   io_pipe (out_channels);
sl@0:   
sl@0:   sub_channels[0] = in_channels[0];
sl@0:   sub_channels[1] = out_channels[1];
sl@0: 
sl@0:   g_io_add_watch (out_channels[0], G_IO_IN | G_IO_HUP,
sl@0: 		      input_callback, in_channels[1]);
sl@0:   
sl@0:   g_thread_create(run_child,sub_channels,FALSE,&err);
sl@0: }
sl@0: 
sl@0: int 
sl@0: main (int argc, char **argv)
sl@0: {
sl@0:   int i;
sl@0:   
sl@0:   #ifdef SYMBIAN
sl@0:   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);
sl@0:   #endif /*SYMBIAN*/
sl@0: 	  
sl@0:   g_thread_init(NULL);
sl@0:   
sl@0:   if (argc > 1)
sl@0:     n_children = atoi(argv[1]);
sl@0: 
sl@0:   if (argc > 2)
sl@0:     n_iters = atoi(argv[2]);
sl@0: 
sl@0:   //printf ("Children: %d     Iters: %d\n", n_children, n_iters);
sl@0: 
sl@0:   n_active_children = n_children;
sl@0:   for (i = 0; i < n_children; i++)
sl@0:     create_child ();
sl@0: 
sl@0:   loop = g_main_loop_new (NULL, FALSE);
sl@0:   
sl@0:   g_assert(loop != NULL);
sl@0:   
sl@0:   g_main_loop_run (loop);
sl@0:   #ifdef SYMBIAN
sl@0:   testResultXml("timeloop");
sl@0:   #endif /* EMULATOR */
sl@0:   return 0;
sl@0: }