aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib/control.ml
diff options
context:
space:
mode:
authorGravatar Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr>2014-06-07 18:43:52 +0200
committerGravatar Pierre-Marie Pédrot <pierre-marie.pedrot@inria.fr>2014-06-08 15:28:32 +0200
commit81c8acb84510de54424330ee83e4852e7610e27b (patch)
treea752a2a32ab717841223632d5da447d02368502d /lib/control.ml
parent289b2b9a1c3d3ebc3c1975663d16c04e88b6329b (diff)
Timeout implementation for Windows based on threads.
Diffstat (limited to 'lib/control.ml')
-rw-r--r--lib/control.ml41
1 files changed, 40 insertions, 1 deletions
diff --git a/lib/control.ml b/lib/control.ml
index 8ce3334f5..40ffa17b1 100644
--- a/lib/control.ml
+++ b/lib/control.ml
@@ -45,9 +45,48 @@ let unix_timeout n f e =
restore_timeout ();
raise e
+let windows_timeout n f e =
+ let killed = ref false in
+ let exited = ref false in
+ let thread init =
+ while not !killed do
+ let cur = Unix.time () in
+ if float_of_int n <= cur -. init then begin
+ interrupt := true;
+ exited := true;
+ Thread.exit ()
+ end;
+ Thread.delay 0.5
+ done
+ in
+ let init = Unix.time () in
+ let id = Thread.create thread init in
+ try
+ let res = f () in
+ let () = killed := true in
+ let cur = Unix.time () in
+ (** The thread did not interrupt, but the computation took longer than
+ expected. *)
+ let () = if float_of_int n <= cur -. init then begin
+ exited := true;
+ raise Sys.Break
+ end in
+ res
+ with
+ | Sys.Break ->
+ (** Just in case, it could be a regular Ctrl+C *)
+ if not !exited then begin killed := true; raise Sys.Break end
+ else raise e
+ | e ->
+ let () = killed := true in
+ let e = Backtrace.add_backtrace e in
+ raise e
+
type timeout = { timeout : 'a. int -> (unit -> 'a) -> exn -> 'a }
-let timeout_fun = ref { timeout = unix_timeout }
+let timeout_fun = match Sys.os_type with
+| "Unix" | "Cygwin" -> ref { timeout = unix_timeout }
+| _ -> ref { timeout = windows_timeout }
let set_timeout f = timeout_fun := f