ocaml/otherlibs/labltk/support/tkthread.ml

68 lines
2.3 KiB
OCaml

(***********************************************************************)
(* *)
(* LablTk, Tcl/Tk interface of Objective Caml *)
(* *)
(* Jacques Garrigue, Nagoya University Mathematics Dept. *)
(* *)
(* Copyright 2004 Institut National de Recherche en Informatique et *)
(* en Automatique and Kyoto University. All rights reserved. *)
(* This file is distributed under the terms of the GNU Library *)
(* General Public License, with the special exception on linking *)
(* described in file LICENSE found in the Objective Caml source tree. *)
(* *)
(***********************************************************************)
(* $Id$ *)
let jobs : (unit -> unit) Queue.t = Queue.create ()
let m = Mutex.create ()
let with_jobs f =
Mutex.lock m; let y = f jobs in Mutex.unlock m; y
let loop_id = ref None
let reset () = loop_id := None
let cannot_sync () =
match !loop_id with None -> true
| Some id -> Thread.id (Thread.self ()) = id
let gui_safe () =
not (Sys.os_type = "Win32") || !loop_id = Some(Thread.id (Thread.self ()))
let has_jobs () = not (with_jobs Queue.is_empty)
let n_jobs () = with_jobs Queue.length
let do_next_job () = with_jobs Queue.take ()
let async j x = with_jobs (Queue.add (fun () -> j x))
let sync f x =
if cannot_sync () then f x else
let m = Mutex.create () in
let res = ref None in
Mutex.lock m;
let c = Condition.create () in
let j x =
let y = f x in Mutex.lock m; res := Some y; Mutex.unlock m;
Condition.signal c
in
async j x;
Condition.wait c m;
match !res with Some y -> y | None -> assert false
let rec job_timer () =
Timer.set ~ms:10 ~callback:
(fun () -> for i = 1 to n_jobs () do do_next_job () done; job_timer())
let thread_main () =
try
ignore (Protocol.openTk());
job_timer();
loop_id := Some (Thread.id (Thread.self ()));
Protocol.mainLoop();
loop_id := None;
with exn ->
loop_id := None;
raise exn
let start () =
Thread.create thread_main ()
let top = Widget.default_toplevel