About GtkThread.sync, GtkThread.async and where do the GUI events live
"Stalkern 2 (Fastweb)" <[email protected]> Thu, 05 Feb 2009 11:46:10 +0100
| Newsgroups | gmane.comp.lang.ocaml.lib.gtk |
|---|---|
| Message-ID | <[email protected]> |
Hello to everybody!
I'm about to work with lablgtk-2.10.1 on a threaded application with
some GUI issues and I want to figure out correctly how does the GUI
manage the GUI events.
So, I've written a test program with two lasting threads and one
short-lived, that affects the materials for the others:
------------------------------------------------------------
buttonConfusedByThreads_v0.1.ml
------------------------------------------------------------
(**************************************************************************)
(* After the buttons.ml example packaged with lablgtk-2.10.1 *)
(* In this sample code three threads attempt to (conf)use an item that
was born in the very GUI thread.
* Will the GUI thread understand all the GUI events going on a GUI Item,
* just because the GUI Item itself is shared between threads?
*)
(*
* launch directly with
* $ lablgtk2 -thread buttonConfusedByThreads_v0.1.ml
* or compile with
* $ ocamlfind ocamlopt -thread -package "lablgtk2 unix threads"
-predicates "init threads" -linkpkg -I +lablgtk2 gtkThread.cmx -o
buttonConfusedByThreads_v0.1.opt buttonConfusedByThreads_v0.1.ml
*)
let prepare_gui () =
(
let window = GWindow.window ~title:"F.U.D." ~border_width:10 () in
let _id = window#connect#destroy ~callback:GtkMain.Main.quit in
let hbox = GPack.hbox ~packing:window#add () in
let button = GButton.button ~label:"?" ~packing:(hbox#pack
~padding:5) () in
let _id = button#connect#clicked ~callback:(fun () -> print_endline
(button#label)) in
(*go!*)
let () = window#show ()in
(*pass items over to the confusing threads*)
(hbox, button)
)
;;
let () =
(
let () = ignore (GtkMain.Main.init ()) (*set locale and the like*) in
(*start the main loop as a thread*)
let guiThread = GtkThread.start () in
(*We should now be inside the GUI Thread. Let's create some GUI*)
let hb,b = prepare_gui () in
let _confuserThread1 =
Thread.create
(
fun () ->
while true do
(
let () = print_endline ("YES!") in
let _testquery = b#label in
(b#set_label "YES!")
)
done
)
()
in
let _confuserThread2 =
Thread.create
(
fun () ->
while true do
(
let () = print_endline ("NO!") in
let _testquery = b#label in
(b#set_label "NO!")
)
done
)
()
in
let _confuserThread3 =
Thread.create
(
fun () ->
let () =
for i = 0 to 400 do
let () = print_endline ("MAYBE #"^(string_of_int i)) in
(b#set_label "MAYBE!")
done
in
(*attempt to be evil*)
(
List.iter
(hb#remove)
(hb#all_children)
)
)
()
in
let () =
Thread.join guiThread
in
()
)
;;
(*EOF*)
---------------------------------------------------------------------------
And I would expect to change the code like this to have all threads
refer to the main GUI thread loop for the GUI actions:
---------------------------------------------------------------------------
46,47c46,47
< let _testquery = b#label in
< (b#set_label "YES!")
---
> let _testquery = GtkThread.sync(*we need an answer*)
(fun () -> b#label) () in
> (GtkThread.async (fun () -> b#set_label "YES!") () )
61,62c61,62
< let _testquery = b#label in
< (b#set_label "NO!")
---
> let _testquery = GtkThread.sync(*we need an answer*)
(fun () -> b#label) () in
> (GtkThread.async (fun () -> b#set_label "NO!") () )
76c76
< (b#set_label "MAYBE!")
---
> (GtkThread.async (fun () -> b#set_label "MAYBE!") () )
81,83c81,90
< List.iter
< (hb#remove)
< (hb#all_children)
---
> GtkThread.async
> (
> fun () ->
> (
> List.iter
> (hb#remove)
> (hb#all_children)
> )
> )
> ()
96a104
>
---------------------------------------------------------------------------
Do I understand things correctly?
I think that I understand that the management of events on the button is
apart from the button itself, so sharing the button is not enough for
getting a well-designed system of threads.
BTW I am a bit puzzled by the possibility for the (surviving) threads of
requesting the label of a button that has been removed from its
container. Does that button then still exist (albeit unpacked), or not?
Here I hoped to get a plain segfault, actually.
Thank you for your advice.
Ernesto