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; |