| author | wenzelm | 
| Mon, 22 Aug 2022 15:00:46 +0200 | |
| changeset 75959 | 4fe213c214f9 | 
| parent 74870 | d54b3c96ee50 | 
| child 78648 | 852ec09aef13 | 
| 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
 | 
| 
74870
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
17  | 
  val apply_physical: Time.time -> ('a -> 'b) -> 'a -> 'b
 | 
| 62519 | 18  | 
val print: Time.time -> string  | 
| 41710 | 19  | 
end;  | 
20  | 
||
| 62519 | 21  | 
structure Timeout: TIMEOUT =  | 
| 41710 | 22  | 
struct  | 
23  | 
||
| 62519 | 24  | 
exception TIMEOUT of Time.time;  | 
| 41710 | 25  | 
|
| 
73388
 
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
 
wenzelm 
parents: 
73387 
diff
changeset
 | 
26  | 
fun ignored timeout = timeout < Time.fromMilliseconds 1;  | 
| 
 
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
 
wenzelm 
parents: 
73387 
diff
changeset
 | 
27  | 
|
| 73387 | 28  | 
fun scale () = Options.default_real "timeout_scale";  | 
29  | 
fun scale_time t = Time.scale (scale ()) t;  | 
|
30  | 
||
31  | 
fun end_time timeout = Time.now () + scale_time timeout;  | 
|
32  | 
||
| 
74870
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
33  | 
fun apply' {physical, timeout} f x =
 | 
| 
73388
 
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
 
wenzelm 
parents: 
73387 
diff
changeset
 | 
34  | 
if ignored timeout then f x  | 
| 73387 | 35  | 
else  | 
36  | 
Thread_Attributes.with_attributes Thread_Attributes.no_interrupts (fn orig_atts =>  | 
|
37  | 
let  | 
|
38  | 
val self = Thread.self ();  | 
|
39  | 
val start = Time.now ();  | 
|
| 
52051
 
9362fcd0318c
modernized TimeLimit.timeLimit using Event_Timer service -- based on more elementary version 11ae688e4e30;
 
wenzelm 
parents: 
44112 
diff
changeset
 | 
40  | 
|
| 73387 | 41  | 
val request =  | 
| 
74870
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
42  | 
          Event_Timer.request {physical = physical} (start + scale_time timeout)
 | 
| 73387 | 43  | 
(fn () => Isabelle_Thread.interrupt_unsynchronized self);  | 
44  | 
val result =  | 
|
45  | 
Exn.capture (fn () => Thread_Attributes.with_attributes orig_atts (fn _ => f x)) ();  | 
|
| 41710 | 46  | 
|
| 73387 | 47  | 
val stop = Time.now ();  | 
48  | 
val was_timeout = not (Event_Timer.cancel request);  | 
|
49  | 
val test = Exn.capture Thread_Attributes.expose_interrupt ();  | 
|
50  | 
in  | 
|
51  | 
if was_timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test)  | 
|
52  | 
then raise TIMEOUT (stop - start)  | 
|
53  | 
else (Exn.release test; Exn.release result)  | 
|
54  | 
end);  | 
|
| 41710 | 55  | 
|
| 
74870
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
56  | 
fun apply timeout f x = apply' {physical = false, timeout = timeout} f x;
 | 
| 
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
57  | 
fun apply_physical timeout f x = apply' {physical = true, timeout = timeout} f x;
 | 
| 
 
d54b3c96ee50
more robust physical timeout (despite 1bea05713dde), especially relevant for quickcheck where large unary numerals may cause excessive heap allocations and resulting GC is better included in the timing;
 
wenzelm 
parents: 
73388 
diff
changeset
 | 
58  | 
|
| 
67000
 
1698e9ccef2d
more portable print_time, notably for occasional negative (!) elapsed time of theory_timing;
 
wenzelm 
parents: 
62924 
diff
changeset
 | 
59  | 
fun print t = "Timeout after " ^ Value.print_time t ^ "s";  | 
| 62519 | 60  | 
|
| 41710 | 61  | 
end;  |