From 7618be2daff51e655abca4125f4266036ef9bfae Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Tue, 30 Apr 2002 15:58:51 +0000 Subject: [PATCH] half-finished docs on merging GTK with existing hunks of code (event loop 2002-04-30 Havoc Pennington * gtk/other_software.sgml: half-finished docs on merging GTK with existing hunks of code (event loop integration, using threads vs. processes, blah blah) --- docs/reference/ChangeLog | 6 + docs/reference/gtk/other_software.sgml | 207 +++++++++++++++++++++++++ 2 files changed, 213 insertions(+) create mode 100644 docs/reference/gtk/other_software.sgml diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index b35558764..77e4098d9 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +2002-04-30 Havoc Pennington + + * gtk/other_software.sgml: half-finished docs on merging GTK with + existing hunks of code (event loop integration, using threads + vs. processes, blah blah) + Thu Apr 25 22:37:58 2002 Owen Taylor * gdk/tmpl/{events,input_devices,region,x_interaction}.sgml: diff --git a/docs/reference/gtk/other_software.sgml b/docs/reference/gtk/other_software.sgml new file mode 100644 index 000000000..b81a94867 --- /dev/null +++ b/docs/reference/gtk/other_software.sgml @@ -0,0 +1,207 @@ + + +Mixing GTK+ with other software +3 +Mixing GTK+ with other software + + + +Mixing GTK+ with other software + +How to combine GTK+ with other code and event loops + + + + +Overview + + +Often people want to use GTK+ in combination with another library or existing +body of code that is not GTK+-aware. The general problem people encounter +is that the control flow of the other code does not return to GTK+, so +widgets do not repaint, mouse and keyboard events are ignored, and so forth. + + + +This section describes some approaches to solving this problem. The most +suitable approach depends on the code that's involved, the platforms you're +targetting, and your own familiarity with each approach. + + + + + +Periodically yield to GTK+ main loop + + +This is the simplest method, but requires you to modify the non-GTK+ code. +Say you have a function that does some kind of lengthy task: + + + void + do_lengthy_task (void) + { + int i; + for (i = 0; i < BIG_NUMBER; ++i) + { + do_small_part_of_task (); + } + } + + +You simply insert code into this function that processes pending main loop tasks, if any: + + + void + do_lengthy_task (void) + { + int i; + for (i = 0; i < BIG_NUMBER; ++i) + { + do_small_part_of_task (); + + /* allow main loop to process pending events; NULL + * means the default context. + */ + while (g_main_context_pending (NULL)) + g_main_context_iteration (NULL, FALSE); + } + } + + + + + +The primary disadvantage of this approach is that you have to trade off UI +responsiveness and the performance of the task. That is, if +do_small_part_of_task() does very little of the task, you'll spend lots of CPU +time on g_main_context_iteration(). While if +do_small_part_of_task() does a lot of work, the GUI will seem noticeably +"chunky" to the user. + + + +Another disadvantage to this approach is that you can't have more than one +lengthy task at the same time, unless you manually integrate them. + + + +The big advantage of this approach is that it's simple and straightforward, and +works fine for simple applications such as tossing up a progress bar during the +lengthy task. + + + + + +Run the other code as a slave of the GTK+ main loop + + +As a slightly cleaner solution, you can ask the main loop to run a small part of your +task whenever it isn't busy — that is, when it's idle. +GLib provides a function g_idle_add() that's useful +for this. An "idle handler" added with g_idle_add() +will be run continuously as long as it returns TRUE. However, +the main loop gives higher priority to GUI-related tasks, so will run those instead +when appropriate. + + + +Here's a simple example: + + + gboolean + my_idle_handler (gpointer user_data) + { + do_small_part_of_task (); + + if (task_complete) + return FALSE; /* removes the idle handler */ + else + return TRUE; /* runs the idle handler again */ + } + + g_idle_add (my_idle_handler, NULL); + + + + + +If your task involves reading data from the network, you should instead use +g_input_add(); this will allow the +main loop to sleep until data is available on a file descriptor, then +wake up to read that data. + + + +g_idle_add() returns a main loop source ID you can +use to remove the idle handler with g_source_remove(). +This is useful for cancelling a task, for example. Another approach is to keep a flag +variable and have the idle handler itself return FALSE when appropriate. + + + + + +Use multiple processes + + +If you can't break a task into small chunks — the +"do_small_part_of_task()" function in the above examples — you'll have to +separate your program into two parts, by spawning a child thread or process. +A process does not share the same address space (variables and data) with its parent. +A thread does share the same address space, so a change made to a variable in +one thread will be visible to other threads as well. + + + +This manual can't go into full detail on processes, threads, and other UNIX +programming topics. You may wish to get a book or two — two I'm familiar +with are Beginning Linux Programming (WROX Press) and Advanced Programming in +the UNIX Environment (by Richard Stevens. + + + +Those books also cover the central issue you'll need to address in order to have +a multi-process application: how to communicate between the processes. The +simplest solution is to use pipes; g_input_add() in combination with g_spawn_async_with_pipes() should make +this reasonably convenient. There are other possibilities, of course, such as +sockets, shared memory, and X Window System client message events, depending on +your needs. + + + + + + +Use multiple threads + + + + + + + + +Integrate the GTK+ main loop with another main loop + + + + + + + + +Things that won't work + + +signals + + + + + + -- 2.43.2