author | bulwahn |
Mon, 02 Jul 2012 12:23:30 +0200 | |
changeset 48179 | 18461f745b4a |
parent 44112 | ef876972fdc1 |
child 52051 | 9362fcd0318c |
permissions | -rw-r--r-- |
41710 | 1 |
(* Title: Pure/Concurrent/time_limit.ML |
2 |
Author: Makarius |
|
3 |
||
41714
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
4 |
Execution with time limit. |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
5 |
|
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
6 |
Notes: |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
7 |
|
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
8 |
* There is considerable overhead due to fork of watchdog thread. |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
9 |
|
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
10 |
* In rare situations asynchronous interrupts might be mistaken as |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
11 |
timeout event, and turned into exception TimeOut accidentally. |
41710 | 12 |
*) |
13 |
||
14 |
signature TIME_LIMIT = |
|
15 |
sig |
|
16 |
exception TimeOut |
|
17 |
val timeLimit : Time.time -> ('a -> 'b) -> 'a -> 'b |
|
18 |
end; |
|
19 |
||
20 |
structure TimeLimit: TIME_LIMIT = |
|
21 |
struct |
|
22 |
||
23 |
exception TimeOut; |
|
24 |
||
41714
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
25 |
val wait_time = seconds 0.0001; |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
26 |
|
41712
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
27 |
fun timeLimit time f x = |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
28 |
Multithreading.with_attributes Multithreading.no_interrupts (fn orig_atts => |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
29 |
let |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
30 |
val main = Thread.self (); |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
31 |
val timeout = Unsynchronized.ref false; |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
32 |
val watchdog = Simple_Thread.fork true (fn () => |
44112
ef876972fdc1
more explicit Simple_Thread.interrupt_unsynchronized, to emphasize its meaning;
wenzelm
parents:
41714
diff
changeset
|
33 |
(OS.Process.sleep time; timeout := true; Simple_Thread.interrupt_unsynchronized main)); |
41712
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
34 |
|
41714
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
35 |
val result = |
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
36 |
Exn.capture (fn () => Multithreading.with_attributes orig_atts (fn _ => f x)) (); |
41710 | 37 |
|
44112
ef876972fdc1
more explicit Simple_Thread.interrupt_unsynchronized, to emphasize its meaning;
wenzelm
parents:
41714
diff
changeset
|
38 |
val _ = Simple_Thread.interrupt_unsynchronized watchdog; |
41714
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
39 |
val _ = while Thread.isActive watchdog do OS.Process.sleep wait_time; |
41710 | 40 |
|
41714
3bafa8ba51db
always test/clear Multithreading.interrupted, indepently of thread attributes;
wenzelm
parents:
41712
diff
changeset
|
41 |
val test = Exn.capture Multithreading.interrupted (); |
41712
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
42 |
in |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
43 |
if ! timeout andalso (Exn.is_interrupt_exn result orelse Exn.is_interrupt_exn test) |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
44 |
then raise TimeOut |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
45 |
else if Exn.is_interrupt_exn test then Exn.interrupt () |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
46 |
else Exn.release result |
82339c3fd74a
more robust TimeLimit: make double sure that watchdog has terminated and interrupts received during uninterruptible state are propagated (NB: Thread.testInterrupt requires InterruptSynch in Poly/ML 5.4.0 or earlier);
wenzelm
parents:
41710
diff
changeset
|
47 |
end); |
41710 | 48 |
|
49 |
end; |
|
50 |