diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2011-10-13 10:38:36 +0100 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2011-10-13 10:38:36 +0100 |
commit | c58baf42ca38ca1aa059640b2b5348ea816a5d9a (patch) | |
tree | 9fb4840f17eb4381cdc903bd0fde821930ab4b57 | |
parent | e389240b2300d213ae6f7c2a3d9e1cab7706f705 (diff) | |
download | clutter-c58baf42ca38ca1aa059640b2b5348ea816a5d9a.tar.gz |
interactive/threads: Clean up
Add some comments explaining why we use idle handlers to update the UI,
and update to the newest API in GLib master.
-rw-r--r-- | tests/interactive/test-threads.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/tests/interactive/test-threads.c b/tests/interactive/test-threads.c index 450e2a732..01ca8a766 100644 --- a/tests/interactive/test-threads.c +++ b/tests/interactive/test-threads.c @@ -5,6 +5,7 @@ #undef CLUTTER_DISABLE_DEPRECATED #include <clutter/clutter.h> +/* our thread-specific data */ typedef struct { ClutterActor *stage; @@ -12,8 +13,6 @@ typedef struct ClutterActor *progress; ClutterTimeline *timeline; - - volatile gboolean cancelled; } TestThreadData; static TestThreadData * @@ -57,7 +56,22 @@ test_thread_done_idle (gpointer user_data) return FALSE; } -static GPrivate test_thread_data = G_PRIVATE_INIT (test_thread_data_free); +static void +test_thread_data_done (gpointer _data) +{ + TestThreadData *data = _data; + + /* since the TestThreadData structure references Clutter data structures + * we need to free it from within the same thread that called clutter_main() + * which means using an idle handler in the main loop. + * + * clutter_threads_add_idle() is guaranteed to run the callback passed to + * to it under the Big Clutter Lock. + */ + clutter_threads_add_idle (test_thread_done_idle, data); +} + +static GPrivate test_thread_data = G_PRIVATE_INIT (test_thread_data_done); typedef struct { @@ -73,7 +87,6 @@ update_label_idle (gpointer data) gchar *text; text = g_strdup_printf ("Count to %d", update->count); - clutter_text_set_text (CLUTTER_TEXT (update->thread_data->label), text); clutter_actor_set_width (update->thread_data->label, -1); @@ -99,8 +112,6 @@ do_something_very_slow (void) gint i; data = g_private_get (&test_thread_data); - if (data->cancelled) - return; for (i = 0; i < 100; i++) { @@ -108,13 +119,18 @@ do_something_very_slow (void) msecs = 1 + (int) (100.0 * rand () / ((RAND_MAX + 1.0) / 3)); - /* sleep for a while */ + /* sleep for a while, to emulate some work being done */ g_usleep (msecs * 1000); if ((i % 10) == 0) { TestUpdate *update; + /* update the UI from within the main loop, making sure that the + * Big Clutter Lock is held; only one thread at a time can call + * Clutter API, and it's better to do this from the same thread + * that called clutter_init()/clutter_main(). + */ update = g_new (TestUpdate, 1); update->count = i; update->thread_data = data; @@ -133,12 +149,9 @@ test_thread_func (gpointer user_data) g_private_set (&test_thread_data, data); + /* this function will block */ do_something_very_slow (); - clutter_threads_add_idle_full (G_PRIORITY_DEFAULT + 30, - test_thread_done_idle, - data, NULL); - return NULL; } @@ -167,7 +180,8 @@ on_key_press_event (ClutterStage *stage, data->progress = g_object_ref (progress_rect); data->timeline = g_object_ref (timeline); - g_thread_new ("counter", test_thread_func, data, FALSE, NULL); + /* start the thread that updates the counter and the progress bar */ + g_thread_new ("counter", test_thread_func, data); return TRUE; @@ -261,3 +275,9 @@ test_threads_main (int argc, char *argv[]) return EXIT_SUCCESS; } + +const char * +test_threads_describe (void) +{ + return "Multi-threading programming with Clutter"; +} |