src/Pure/Concurrent/time_limit.ML
author wenzelm
Wed, 10 Aug 2011 15:17:24 +0200
changeset 44112 ef876972fdc1
parent 41714 3bafa8ba51db
child 52051 9362fcd0318c
permissions -rw-r--r--
more explicit Simple_Thread.interrupt_unsynchronized, to emphasize its meaning;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
41710
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/Concurrent/time_limit.ML
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
     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
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    12
*)
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    13
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    14
signature TIME_LIMIT =
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    15
sig
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    16
  exception TimeOut
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    17
  val timeLimit : Time.time -> ('a -> 'b) -> 'a -> 'b
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    18
end;
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    19
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    20
structure TimeLimit: TIME_LIMIT =
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    21
struct
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    22
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    23
exception TimeOut;
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    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
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    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
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    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
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    48
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    49
end;
11ae688e4e30 clarified bootstrapping of structure TimeLimit;
wenzelm
parents:
diff changeset
    50