author | wenzelm |
Sun, 28 Mar 2021 11:45:00 +0200 | |
changeset 73503 | eda1d95ef538 |
parent 73388 | a40e69fde2b4 |
child 74870 | d54b3c96ee50 |
permissions | -rw-r--r-- |
62519 | 1 |
(* Title: Pure/Concurrent/timeout.ML |
41710 | 2 |
Author: Makarius |
3 |
||
73387 | 4 |
Execution with relative timeout: |
5 |
- timeout specification < 1ms means no timeout |
|
6 |
- actual timeout is subject to system option "timeout_scale" |
|
41710 | 7 |
*) |
8 |
||
62519 | 9 |
signature TIMEOUT = |
41710 | 10 |
sig |
62519 | 11 |
exception TIMEOUT of Time.time |
73388
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
wenzelm
parents:
73387
diff
changeset
|
12 |
val ignored: Time.time -> bool |
73387 | 13 |
val scale: unit -> real |
14 |
val scale_time: Time.time -> Time.time |
|
15 |
val end_time: Time.time -> Time.time |
|
62519 | 16 |
val apply: Time.time -> ('a -> 'b) -> 'a -> 'b |
17 |
val print: Time.time -> string |
|
41710 | 18 |
end; |
19 |
||
62519 | 20 |
structure Timeout: TIMEOUT = |
41710 | 21 |
struct |
22 |
||
62519 | 23 |
exception TIMEOUT of Time.time; |
41710 | 24 |
|
73388
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
wenzelm
parents:
73387
diff
changeset
|
25 |
fun ignored timeout = timeout < Time.fromMilliseconds 1; |
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
wenzelm
parents:
73387
diff
changeset
|
26 |
|
73387 | 27 |
fun scale () = Options.default_real "timeout_scale"; |
28 |
fun scale_time t = Time.scale (scale ()) t; |
|
29 |
||
30 |
fun end_time timeout = Time.now () + scale_time timeout; |
|
31 |
||
62519 | 32 |
fun apply timeout f x = |
73388
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
wenzelm
parents:
73387
diff
changeset
|
33 |
if ignored timeout then f x |
73387 | 34 |
else |
35 |
Thread_Attributes.with_attributes Thread_Attributes.no_interrupts (fn orig_atts => |
|
36 |
let |
|
37 |
val self = Thread.self (); |
|
38 |
val start = Time.now (); |
|
52051
9362fcd0318c
modernized TimeLimit.timeLimit using Event_Timer service -- based on more elementary version 11ae688e4e30;
wenzelm
parents:
44112
diff
changeset
|
39 |
|
73387 | 40 |
val request = |
41 |
Event_Timer.request {physical = false} (start + scale_time timeout) |
|
42 |
(fn () => Isabelle_Thread.interrupt_unsynchronized self); |
|
43 |
val result = |
|
44 |
Exn.capture (fn () => Thread_Attributes.with_attributes orig_atts (fn _ => f x)) (); |
|
41710 | 45 |
|
73387 | 46 |
val stop = Time.now (); |
47 |
val was_timeout = not (Event_Timer.cancel request); |
|
48 |
val test = Exn.capture Thread_Attributes.expose_interrupt (); |
|
49 |
in |
|
50 |
if was_timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test) |
|
51 |
then raise TIMEOUT (stop - start) |
|
52 |
else (Exn.release test; Exn.release result) |
|
53 |
end); |
|
41710 | 54 |
|
67000
1698e9ccef2d
more portable print_time, notably for occasional negative (!) elapsed time of theory_timing;
wenzelm
parents:
62924
diff
changeset
|
55 |
fun print t = "Timeout after " ^ Value.print_time t ^ "s"; |
62519 | 56 |
|
41710 | 57 |
end; |