src/Pure/Concurrent/timeout.ML
changeset 73387 3b5196dac4c8
parent 71692 f8e52c0152fe
child 73388 a40e69fde2b4
equal deleted inserted replaced
73386:3fb201ca8fb5 73387:3b5196dac4c8
     1 (*  Title:      Pure/Concurrent/timeout.ML
     1 (*  Title:      Pure/Concurrent/timeout.ML
     2     Author:     Makarius
     2     Author:     Makarius
     3 
     3 
     4 Execution with (relative) timeout.
     4 Execution with relative timeout:
       
     5   - timeout specification < 1ms means no timeout
       
     6   - actual timeout is subject to system option "timeout_scale"
     5 *)
     7 *)
     6 
     8 
     7 signature TIMEOUT =
     9 signature TIMEOUT =
     8 sig
    10 sig
     9   exception TIMEOUT of Time.time
    11   exception TIMEOUT of Time.time
       
    12   val scale: unit -> real
       
    13   val scale_time: Time.time -> Time.time
       
    14   val end_time: Time.time -> Time.time
    10   val apply: Time.time -> ('a -> 'b) -> 'a -> 'b
    15   val apply: Time.time -> ('a -> 'b) -> 'a -> 'b
    11   val print: Time.time -> string
    16   val print: Time.time -> string
    12 end;
    17 end;
    13 
    18 
    14 structure Timeout: TIMEOUT =
    19 structure Timeout: TIMEOUT =
    15 struct
    20 struct
    16 
    21 
    17 exception TIMEOUT of Time.time;
    22 exception TIMEOUT of Time.time;
    18 
    23 
       
    24 fun scale () = Options.default_real "timeout_scale";
       
    25 fun scale_time t = Time.scale (scale ()) t;
       
    26 
       
    27 fun end_time timeout = Time.now () + scale_time timeout;
       
    28 
    19 fun apply timeout f x =
    29 fun apply timeout f x =
    20   Thread_Attributes.with_attributes Thread_Attributes.no_interrupts (fn orig_atts =>
    30   if timeout < Time.fromMilliseconds 1 then f x
    21     let
    31   else
    22       val self = Thread.self ();
    32     Thread_Attributes.with_attributes Thread_Attributes.no_interrupts (fn orig_atts =>
    23       val start = Time.now ();
    33       let
       
    34         val self = Thread.self ();
       
    35         val start = Time.now ();
    24 
    36 
    25       val request =
    37         val request =
    26         Event_Timer.request {physical = false} (start + timeout)
    38           Event_Timer.request {physical = false} (start + scale_time timeout)
    27           (fn () => Isabelle_Thread.interrupt_unsynchronized self);
    39             (fn () => Isabelle_Thread.interrupt_unsynchronized self);
    28       val result =
    40         val result =
    29         Exn.capture (fn () => Thread_Attributes.with_attributes orig_atts (fn _ => f x)) ();
    41           Exn.capture (fn () => Thread_Attributes.with_attributes orig_atts (fn _ => f x)) ();
    30 
    42 
    31       val stop = Time.now ();
    43         val stop = Time.now ();
    32       val was_timeout = not (Event_Timer.cancel request);
    44         val was_timeout = not (Event_Timer.cancel request);
    33       val test = Exn.capture Thread_Attributes.expose_interrupt ();
    45         val test = Exn.capture Thread_Attributes.expose_interrupt ();
    34     in
    46       in
    35       if was_timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test)
    47         if was_timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test)
    36       then raise TIMEOUT (stop - start)
    48         then raise TIMEOUT (stop - start)
    37       else (Exn.release test; Exn.release result)
    49         else (Exn.release test; Exn.release result)
    38     end);
    50       end);
    39 
    51 
    40 fun print t = "Timeout after " ^ Value.print_time t ^ "s";
    52 fun print t = "Timeout after " ^ Value.print_time t ^ "s";
    41 
    53 
    42 end;
    54 end;