1/* This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 *
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 *
11 * You should have received a copy of the GNU Lesser General Public
12 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
13 *
14 * Copyright 2012 Red Hat, Inc
15 */
16
17#undef G_DISABLE_ASSERT
18#undef G_LOG_DOMAIN
19
20#include <glib.h>
21
22#define NSOURCES 50000
23
24static gboolean
25callback (gpointer user_data)
26{
27 g_assert_not_reached ();
28 return FALSE;
29}
30
31static void
32shuffle (GSource **sources, int num)
33{
34 int i, a, b;
35 GSource *tmp;
36
37 for (i = 0; i < num * 10; i++)
38 {
39 a = g_random_int_range (begin: 0, end: num);
40 b = g_random_int_range (begin: 0, end: num);
41 tmp = sources[a];
42 sources[a] = sources[b];
43 sources[b] = tmp;
44 }
45}
46
47static void
48thread_pool_attach_func (gpointer data,
49 gpointer user_data)
50{
51 GMainContext *context = user_data;
52 GSource *source = data;
53
54 g_source_attach (source, context);
55 g_source_unref (source);
56}
57
58static void
59thread_pool_destroy_func (gpointer data,
60 gpointer user_data)
61{
62 GSource *source = data;
63
64 g_source_destroy (source);
65}
66
67int
68main (int argc, char **argv)
69{
70 int i;
71 gint64 start;
72 gint64 end;
73 GMainContext *context;
74 GSource **sources;
75 GThreadPool *pool;
76 GError *error = NULL;
77
78 context = g_main_context_default ();
79 sources = g_new0 (GSource *, NSOURCES);
80
81 start = g_get_monotonic_time ();
82 for (i = 0; i < NSOURCES; i++)
83 {
84 sources[i] = g_idle_source_new ();
85 g_source_set_callback (source: sources[i], func: callback, NULL, NULL);
86 g_source_attach (source: sources[i], context);
87 }
88 end = g_get_monotonic_time ();
89 g_print (format: "Add same-priority sources: %" G_GINT64_FORMAT "\n",
90 (end - start) / 1000);
91
92#ifdef SLOW
93 start = g_get_monotonic_time ();
94 for (i = 0; i < NSOURCES; i++)
95 g_assert (sources[i] == g_main_context_find_source_by_id (context, g_source_get_id (sources[i])));
96 end = g_get_monotonic_time ();
97 g_print ("Find each source: %" G_GINT64_FORMAT "\n",
98 (end - start) / 1000);
99#endif
100
101 shuffle (sources, NSOURCES);
102
103 start = g_get_monotonic_time ();
104 for (i = 0; i < NSOURCES; i++)
105 {
106 g_source_destroy (source: sources[i]);
107 g_source_unref (source: sources[i]);
108 }
109 end = g_get_monotonic_time ();
110 g_print (format: "Remove in random order: %" G_GINT64_FORMAT "\n",
111 (end - start) / 1000);
112
113 /* Make sure they really did get removed */
114 g_main_context_iteration (context, FALSE);
115
116 start = g_get_monotonic_time ();
117 for (i = 0; i < NSOURCES; i++)
118 {
119 sources[i] = g_idle_source_new ();
120 g_source_set_callback (source: sources[i], func: callback, NULL, NULL);
121 g_source_set_priority (source: sources[i], priority: i % 100);
122 g_source_attach (source: sources[i], context);
123 }
124 end = g_get_monotonic_time ();
125 g_print (format: "Add different-priority sources: %" G_GINT64_FORMAT "\n",
126 (end - start) / 1000);
127
128#ifdef SLOW
129 start = g_get_monotonic_time ();
130 for (i = 0; i < NSOURCES; i++)
131 g_assert (sources[i] == g_main_context_find_source_by_id (context, g_source_get_id (sources[i])));
132 end = g_get_monotonic_time ();
133 g_print ("Find each source: %" G_GINT64_FORMAT "\n",
134 (end - start) / 1000);
135#endif
136
137 shuffle (sources, NSOURCES);
138
139 start = g_get_monotonic_time ();
140 for (i = 0; i < NSOURCES; i++)
141 {
142 g_source_destroy (source: sources[i]);
143 g_source_unref (source: sources[i]);
144 }
145 end = g_get_monotonic_time ();
146 g_print (format: "Remove in random order: %" G_GINT64_FORMAT "\n",
147 (end - start) / 1000);
148
149 /* Make sure they really did get removed */
150 g_main_context_iteration (context, FALSE);
151
152 pool = g_thread_pool_new (func: thread_pool_attach_func, user_data: context,
153 max_threads: 20, TRUE, NULL);
154 start = g_get_monotonic_time ();
155 for (i = 0; i < NSOURCES; i++)
156 {
157 sources[i] = g_idle_source_new ();
158 g_source_set_callback (source: sources[i], func: callback, NULL, NULL);
159 g_thread_pool_push (pool, data: sources[i], error: &error);
160 g_assert_no_error (error);
161 }
162 g_thread_pool_free (pool, FALSE, TRUE);
163 end = g_get_monotonic_time ();
164 g_print (format: "Add sources from threads: %" G_GINT64_FORMAT "\n",
165 (end - start) / 1000);
166
167 pool = g_thread_pool_new (func: thread_pool_destroy_func, user_data: context,
168 max_threads: 20, TRUE, NULL);
169 start = g_get_monotonic_time ();
170 for (i = 0; i < NSOURCES; i++)
171 {
172 g_thread_pool_push (pool, data: sources[i], error: &error);
173 g_assert_no_error (error);
174 }
175 g_thread_pool_free (pool, FALSE, TRUE);
176 end = g_get_monotonic_time ();
177 g_print (format: "Remove sources from threads: %" G_GINT64_FORMAT "\n",
178 (end - start) / 1000);
179
180 /* Make sure they really did get removed */
181 g_main_context_iteration (context, FALSE);
182
183 g_free (mem: sources);
184 return 0;
185}
186

source code of gtk/subprojects/glib/tests/sources.c