Merge branch 'test-ip_mreq_source-android-only' into 'master'
[glib.git] / tests / gobject / timeloop-closure.c
blobc904c2a45d7bc5aa4ef49f1972b1a9363c7788c8
1 #undef G_DISABLE_ASSERT
2 #undef G_LOG_DOMAIN
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 #include <stdio.h>
8 #include <sys/time.h>
9 #include <sys/resource.h>
11 #include <glib.h>
12 #include <glib-object.h>
14 static int n_children = 3;
15 static int n_active_children;
16 static int n_iters = 10000;
17 static GMainLoop *loop;
19 static void
20 io_pipe (GIOChannel **channels)
22 int fds[2];
24 if (pipe(fds) < 0)
26 int errsv = errno;
27 fprintf (stderr, "Cannot create pipe %s\n", g_strerror (errsv));
28 exit (1);
31 channels[0] = g_io_channel_unix_new (fds[0]);
32 channels[1] = g_io_channel_unix_new (fds[1]);
35 static gboolean
36 read_all (GIOChannel *channel, char *buf, int len)
38 gsize bytes_read = 0;
39 gsize count;
40 GIOError err;
42 while (bytes_read < len)
44 err = g_io_channel_read (channel, buf + bytes_read, len - bytes_read, &count);
45 if (err)
47 if (err != G_IO_ERROR_AGAIN)
48 return FALSE;
50 else if (count == 0)
51 return FALSE;
53 bytes_read += count;
56 return TRUE;
59 static gboolean
60 write_all (GIOChannel *channel, char *buf, int len)
62 gsize bytes_written = 0;
63 gsize count;
64 GIOError err;
66 while (bytes_written < len)
68 err = g_io_channel_write (channel, buf + bytes_written, len - bytes_written, &count);
69 if (err && err != G_IO_ERROR_AGAIN)
70 return FALSE;
72 bytes_written += count;
75 return TRUE;
78 static void
79 run_child (GIOChannel *in_channel, GIOChannel *out_channel)
81 int i;
82 int val = 1;
83 GTimer *timer = g_timer_new();
85 for (i = 0; i < n_iters; i++)
87 write_all (out_channel, (char *)&val, sizeof (val));
88 read_all (in_channel, (char *)&val, sizeof (val));
91 val = 0;
92 write_all (out_channel, (char *)&val, sizeof (val));
94 val = g_timer_elapsed (timer, NULL) * 1000;
96 write_all (out_channel, (char *)&val, sizeof (val));
97 g_timer_destroy (timer);
99 exit (0);
102 static gboolean
103 input_callback (GIOChannel *source,
104 GIOCondition condition,
105 gpointer data)
107 int val;
108 GIOChannel *dest = (GIOChannel *)data;
110 if (!read_all (source, (char *)&val, sizeof(val)))
112 fprintf (stderr, "Unexpected EOF\n");
113 exit (1);
116 if (val)
118 write_all (dest, (char *)&val, sizeof(val));
120 return TRUE;
122 else
124 g_io_channel_close (source);
125 g_io_channel_close (dest);
127 n_active_children--;
128 if (n_active_children == 0)
129 g_main_loop_quit (loop);
131 return FALSE;
135 static void
136 create_child (void)
138 int pid, errsv;
139 GIOChannel *in_channels[2];
140 GIOChannel *out_channels[2];
141 GSource *source;
143 io_pipe (in_channels);
144 io_pipe (out_channels);
146 pid = fork ();
147 errsv = errno;
149 if (pid > 0) /* Parent */
151 g_io_channel_close (in_channels[0]);
152 g_io_channel_close (out_channels[1]);
154 source = g_io_create_watch (out_channels[0], G_IO_IN | G_IO_HUP);
155 g_source_set_closure (source,
156 g_cclosure_new (G_CALLBACK (input_callback), in_channels[1],
157 (GClosureNotify)g_io_channel_unref));
158 g_source_attach (source, NULL);
159 g_source_unref (source);
161 g_io_channel_unref (in_channels[0]);
162 g_io_channel_unref (out_channels[0]);
163 g_io_channel_unref (out_channels[1]);
166 else if (pid == 0) /* Child */
168 g_io_channel_close (in_channels[1]);
169 g_io_channel_close (out_channels[0]);
171 setsid ();
173 run_child (in_channels[0], out_channels[1]);
175 else /* Error */
177 fprintf (stderr, "Cannot fork: %s\n", g_strerror (errsv));
178 exit (1);
182 static double
183 difftimeval (struct timeval *old, struct timeval *new)
185 return
186 (new->tv_sec - old->tv_sec) * 1000. + (new->tv_usec - old->tv_usec) / 1000;
189 int
190 main (int argc, char **argv)
192 int i;
193 struct rusage old_usage;
194 struct rusage new_usage;
196 if (argc > 1)
197 n_children = atoi(argv[1]);
199 if (argc > 2)
200 n_iters = atoi(argv[2]);
202 printf ("Children: %d Iters: %d\n", n_children, n_iters);
204 n_active_children = n_children;
205 for (i = 0; i < n_children; i++)
206 create_child ();
208 getrusage (RUSAGE_SELF, &old_usage);
209 loop = g_main_loop_new (NULL, FALSE);
210 g_main_loop_run (loop);
211 getrusage (RUSAGE_SELF, &new_usage);
213 printf ("Elapsed user: %g\n",
214 difftimeval (&old_usage.ru_utime, &new_usage.ru_utime));
215 printf ("Elapsed system: %g\n",
216 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
217 printf ("Elapsed total: %g\n",
218 difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
219 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime));
220 printf ("total / iteration: %g\n",
221 (difftimeval (&old_usage.ru_utime, &new_usage.ru_utime) +
222 difftimeval (&old_usage.ru_stime, &new_usage.ru_stime)) /
223 (n_iters * n_children));
225 g_main_loop_unref (loop);
227 return 0;