# HG changeset patch # User wenzelm # Date 1368805551 -7200 # Node ID 9362fcd0318c664361a33ca058017d04770df230 # Parent b40ed9dcf9034f794d473dbbb925c1aec352003e modernized TimeLimit.timeLimit using Event_Timer service -- based on more elementary version 11ae688e4e30; diff -r b40ed9dcf903 -r 9362fcd0318c src/Pure/Concurrent/time_limit.ML --- a/src/Pure/Concurrent/time_limit.ML Fri May 17 17:11:06 2013 +0200 +++ b/src/Pure/Concurrent/time_limit.ML Fri May 17 17:45:51 2013 +0200 @@ -1,14 +1,7 @@ (* Title: Pure/Concurrent/time_limit.ML Author: Makarius -Execution with time limit. - -Notes: - - * There is considerable overhead due to fork of watchdog thread. - - * In rare situations asynchronous interrupts might be mistaken as - timeout event, and turned into exception TimeOut accidentally. +Execution with time limit (relative timeout). *) signature TIME_LIMIT = @@ -22,27 +15,22 @@ exception TimeOut; -val wait_time = seconds 0.0001; - -fun timeLimit time f x = +fun timeLimit timeout f x = Multithreading.with_attributes Multithreading.no_interrupts (fn orig_atts => let - val main = Thread.self (); - val timeout = Unsynchronized.ref false; - val watchdog = Simple_Thread.fork true (fn () => - (OS.Process.sleep time; timeout := true; Simple_Thread.interrupt_unsynchronized main)); + val self = Thread.self (); + + val request = + Event_Timer.request (Time.+ (Time.now (), timeout)) + (fn () => Simple_Thread.interrupt_unsynchronized self); val result = Exn.capture (fn () => Multithreading.with_attributes orig_atts (fn _ => f x)) (); - val _ = Simple_Thread.interrupt_unsynchronized watchdog; - val _ = while Thread.isActive watchdog do OS.Process.sleep wait_time; - - val test = Exn.capture Multithreading.interrupted (); + val was_timeout = not (Event_Timer.cancel request); in - if ! timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test) + if was_timeout andalso Exn.is_interrupt_exn result then raise TimeOut - else if Exn.is_interrupt_exn test then Exn.interrupt () else Exn.release result end);