1 #undef G_DISABLE_ASSERT
8 #define debug(...) g_printerr (__VA_ARGS__)
12 #define WAIT 5 /* seconds */
13 #define MAX_THREADS 10
15 /* if > 0 the test will run continously (since the test ends when
16 * thread count is 0), if -1 it means no limit to unused threads
17 * if 0 then no unused threads are possible */
18 #define MAX_UNUSED_THREADS -1
20 G_LOCK_DEFINE_STATIC (thread_counter_pools);
22 static gulong abs_thread_counter = 0;
23 static gulong running_thread_counter = 0;
24 static gulong leftover_task_counter = 0;
26 G_LOCK_DEFINE_STATIC (last_thread);
28 static guint last_thread_id = 0;
30 G_LOCK_DEFINE_STATIC (thread_counter_sort);
32 static gulong sort_thread_counter = 0;
34 static GThreadPool *idle_pool = NULL;
36 static GMainLoop *main_loop = NULL;
40 test_thread_pools_entry_func (gpointer data, gpointer user_data)
44 id = GPOINTER_TO_UINT (data);
46 debug("[pool] ---> [%3.3d] entered thread\n", id);
48 G_LOCK (thread_counter_pools);
50 running_thread_counter++;
51 G_UNLOCK (thread_counter_pools);
53 g_usleep (g_random_int_range (0, 4000));
55 G_LOCK (thread_counter_pools);
56 running_thread_counter--;
57 leftover_task_counter--;
59 g_print ("[pool] ---> [%3.3d] exiting thread (abs count:%ld, running count:%ld, left over:%ld)\n",
60 id, abs_thread_counter, running_thread_counter, leftover_task_counter);
61 G_UNLOCK (thread_counter_pools);
65 test_thread_pools (void)
67 GThreadPool *pool1, *pool2, *pool3;
70 pool1 = g_thread_pool_new ((GFunc)test_thread_pools_entry_func, NULL, 3, FALSE, NULL);
71 pool2 = g_thread_pool_new ((GFunc)test_thread_pools_entry_func, NULL, 5, TRUE, NULL);
72 pool3 = g_thread_pool_new ((GFunc)test_thread_pools_entry_func, NULL, 7, TRUE, NULL);
74 for (i = 0; i < RUNS; i++)
76 g_thread_pool_push (pool1, GUINT_TO_POINTER (i), NULL);
77 g_thread_pool_push (pool2, GUINT_TO_POINTER (i), NULL);
78 g_thread_pool_push (pool3, GUINT_TO_POINTER (i), NULL);
79 leftover_task_counter += 3;
82 g_thread_pool_free (pool1, TRUE, TRUE);
83 g_thread_pool_free (pool2, FALSE, TRUE);
84 g_thread_pool_free (pool3, FALSE, TRUE);
86 g_assert (RUNS * 3 == abs_thread_counter + leftover_task_counter);
87 g_assert (running_thread_counter == 0);
91 test_thread_sort_compare_func (gconstpointer a, gconstpointer b, gpointer user_data)
95 id1 = GPOINTER_TO_UINT (a);
96 id2 = GPOINTER_TO_UINT (b);
98 return (id1 > id2 ? +1 : id1 == id2 ? 0 : -1);
102 test_thread_sort_entry_func (gpointer data, gpointer user_data)
107 G_LOCK (last_thread);
109 thread_id = GPOINTER_TO_UINT (data);
110 is_sorted = GPOINTER_TO_INT (user_data);
112 debug("%s ---> entered thread:%2.2d, last thread:%2.2d\n",
113 is_sorted ? "[ sorted]" : "[unsorted]", thread_id, last_thread_id);
116 static gboolean last_failed = FALSE;
118 if (last_thread_id > thread_id) {
120 g_assert (last_thread_id <= thread_id);
123 /* here we remember one fail and if it concurrently fails, it
124 can not be sorted. the last thread id might be < this thread
125 id if something is added to the queue since threads were
132 last_thread_id = thread_id;
135 G_UNLOCK (last_thread);
137 g_usleep (WAIT * 1000);
141 test_thread_sort (gboolean sort)
147 pool = g_thread_pool_new (test_thread_sort_entry_func,
148 GINT_TO_POINTER (sort),
153 g_thread_pool_set_max_unused_threads (MAX_UNUSED_THREADS);
156 g_thread_pool_set_sort_function (pool,
157 test_thread_sort_compare_func,
158 GUINT_TO_POINTER (69));
161 for (i = 0; i < limit; i++) {
164 id = g_random_int_range (1, limit*2);
165 g_thread_pool_push (pool, GUINT_TO_POINTER (id), NULL);
168 g_assert (g_thread_pool_get_num_threads (pool) == g_thread_pool_get_max_threads (pool));
172 test_thread_idle_time_entry_func (gpointer data, gpointer user_data)
176 thread_id = GPOINTER_TO_UINT (data);
178 debug("[idle] ---> entered thread:%2.2d\n",
181 g_usleep (WAIT * 1000);
183 debug("[idle] <--- exiting thread:%2.2d\n",
188 test_thread_idle_timeout (gpointer data)
193 interval = GPOINTER_TO_UINT (data);
195 for (i = 0; i < 2; i++) {
196 g_thread_pool_push (idle_pool, GUINT_TO_POINTER (100 + i), NULL);
197 debug("[idle] ===> pushed new thread with id:%d, number of threads:%d, unprocessed:%d\n",
199 g_thread_pool_get_num_threads (idle_pool),
200 g_thread_pool_unprocessed (idle_pool));
208 test_thread_idle_time (guint idle_time)
211 guint interval = 10000;
214 idle_pool = g_thread_pool_new (test_thread_idle_time_entry_func,
220 g_thread_pool_set_max_unused_threads (MAX_UNUSED_THREADS);
221 g_thread_pool_set_max_idle_time (interval);
223 g_assert (g_thread_pool_get_max_unused_threads () == MAX_UNUSED_THREADS);
224 g_assert (g_thread_pool_get_max_idle_time () == interval);
226 for (i = 0; i < limit; i++) {
227 g_thread_pool_push (idle_pool, GUINT_TO_POINTER (i), NULL);
228 debug("[idle] ===> pushed new thread with id:%d, number of threads:%d, unprocessed:%d\n",
230 g_thread_pool_get_num_threads (idle_pool),
231 g_thread_pool_unprocessed (idle_pool));
234 g_timeout_add ((interval - 1000),
235 test_thread_idle_timeout,
236 GUINT_TO_POINTER (interval));
240 test_check_start_and_stop (gpointer user_data)
242 static guint test_number = 0;
243 static gboolean run_next = FALSE;
244 gboolean continue_timeout = TRUE;
245 gboolean quit = TRUE;
247 if (test_number == 0) {
249 debug("***** RUNNING TEST %2.2d *****\n", test_number);
255 switch (test_number) {
257 test_thread_pools ();
260 test_thread_sort (FALSE);
263 test_thread_sort (TRUE);
266 test_thread_idle_time (5);
269 debug("***** END OF TESTS *****\n");
270 g_main_loop_quit (main_loop);
271 continue_timeout = FALSE;
279 if (test_number == 1) {
280 G_LOCK (thread_counter_pools);
281 quit &= running_thread_counter <= 0;
282 debug("***** POOL RUNNING THREAD COUNT:%ld\n",
283 running_thread_counter);
284 G_UNLOCK (thread_counter_pools);
287 if (test_number == 2 || test_number == 3) {
288 G_LOCK (thread_counter_sort);
289 quit &= sort_thread_counter <= 0;
290 debug("***** POOL SORT THREAD COUNT:%ld\n",
291 sort_thread_counter);
292 G_UNLOCK (thread_counter_sort);
295 if (test_number == 4) {
298 idle = g_thread_pool_get_num_threads (idle_pool);
300 debug("***** POOL IDLE THREAD COUNT:%d, UNPROCESSED JOBS:%d\n",
301 idle, g_thread_pool_unprocessed (idle_pool));
308 return continue_timeout;
312 main (int argc, char *argv[])
314 /* Only run the test, if threads are enabled and a default thread
315 implementation is available */
317 #if defined(G_THREADS_ENABLED) && ! defined(G_THREADS_IMPL_NONE)
318 g_thread_init (NULL);
320 debug("Starting... (in one second)\n");
321 g_timeout_add (1000, test_check_start_and_stop, NULL);
323 main_loop = g_main_loop_new (NULL, FALSE);
324 g_main_loop_run (main_loop);