| author | haftmann | 
| Mon, 29 Jan 2024 19:35:07 +0000 | |
| changeset 79541 | 4f40225936d1 | 
| parent 78787 | a7e4b412cc7c | 
| child 82092 | 93195437fdee | 
| 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: 
73387diff
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: 
73388diff
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: 
73387diff
changeset | 26 | fun ignored timeout = timeout < Time.fromMilliseconds 1; | 
| 
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
 wenzelm parents: 
73387diff
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: 
73388diff
changeset | 33 | fun apply' {physical, timeout} f x =
 | 
| 73388 
a40e69fde2b4
clarified smt: support Timeout.ignored and Timeout.scale_time;
 wenzelm parents: 
73387diff
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: 
44112diff
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: 
73388diff
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: 
78757diff
changeset | 50 | val was_interrupt = | 
| 
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
 wenzelm parents: 
78757diff
changeset | 51 | Exn.is_interrupt_proper_exn result orelse | 
| 
5578341489cb
further clarification of Exn.is_interrupt_proper vs. overall Exn.is_interrupt;
 wenzelm parents: 
78757diff
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: 
78757diff
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: 
73388diff
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: 
73388diff
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: 
73388diff
changeset | 61 | |
| 67000 
1698e9ccef2d
more portable print_time, notably for occasional negative (!) elapsed time of theory_timing;
 wenzelm parents: 
62924diff
changeset | 62 | fun print t = "Timeout after " ^ Value.print_time t ^ "s"; | 
| 62519 | 63 | |
| 41710 | 64 | end; |