author | wenzelm |
Wed, 10 Jan 2024 13:10:20 +0100 | |
changeset 79463 | 7d10708bbc32 |
parent 78787 | a7e4b412cc7c |
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 |
|
78648 | 38 |
val self = Isabelle_Thread.self (); |
73387 | 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) |
78787 | 43 |
(fn () => Isabelle_Thread.interrupt_thread self); |
73387 | 44 |
val result = |
78757 | 45 |
Exn.capture_body (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); |
|
78714 | 49 |
val test = Isabelle_Thread.expose_interrupt_result (); |
78766
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
wenzelm
parents:
78757
diff
changeset
|
50 |
val was_interrupt = |
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
wenzelm
parents:
78757
diff
changeset
|
51 |
Exn.is_interrupt_proper_exn result orelse |
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
wenzelm
parents:
78757
diff
changeset
|
52 |
Exn.is_interrupt_proper_exn test; |
73387 | 53 |
in |
78766
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
wenzelm
parents:
78757
diff
changeset
|
54 |
if was_timeout andalso was_interrupt |
73387 | 55 |
then raise TIMEOUT (stop - start) |
56 |
else (Exn.release test; Exn.release result) |
|
57 |
end); |
|
41710 | 58 |
|
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
|
59 |
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
|
60 |
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
|
61 |
|
67000
1698e9ccef2d
more portable print_time, notably for occasional negative (!) elapsed time of theory_timing;
wenzelm
parents:
62924
diff
changeset
|
62 |
fun print t = "Timeout after " ^ Value.print_time t ^ "s"; |
62519 | 63 |
|
41710 | 64 |
end; |