src/Pure/ML-Systems/multithreading_polyml.ML
author wenzelm
Wed, 25 Jul 2007 22:20:53 +0200
changeset 23991 d4417ba26706
parent 23981 03b71bf91318
child 24060 b643ee118928
permissions -rw-r--r--
renamed CRITICAL' to NAMED_CRITICAL; tuned messages;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/ML-Systems/multithreading_polyml.ML
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     2
    ID:         $Id$
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     3
    Author:     Makarius
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     4
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     5
Multithreading in Poly/ML (version 5.1).
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     6
*)
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     7
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     8
open Thread;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
     9
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    10
structure Multithreading: MULTITHREADING =
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    11
struct
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    12
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    13
val trace = ref false;
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    14
fun tracing msg =
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    15
  if ! trace
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    16
  then (TextIO.output (TextIO.stdErr, (">>> " ^ msg () ^ "\n")); TextIO.flushOut TextIO.stdErr)
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    17
  else ();
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    18
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    19
val available = true;
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    20
val max_threads = ref 1;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    21
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    22
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    23
(* critical section -- may be nested within the same thread *)
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    24
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    25
local
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    26
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    27
val critical_lock = Mutex.mutex ();
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    28
val critical_thread = ref (NONE: Thread.thread option);
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    29
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    30
in
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    31
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    32
fun self_critical () =
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    33
  (case ! critical_thread of
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    34
    NONE => false
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    35
  | SOME id => Thread.equal (id, Thread.self ()));
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    36
23991
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    37
fun NAMED_CRITICAL name e =
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    38
  if self_critical () then e ()
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    39
  else
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    40
    let
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    41
      val _ =
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    42
        if Mutex.trylock critical_lock then ()
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    43
        else
23991
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    44
         (tracing (fn () =>
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    45
            "CRITICAL" ^ (if name = "" then "" else " " ^ name) ^ ": waiting for lock");
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    46
          Mutex.lock critical_lock;
23991
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    47
          tracing (fn () =>
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    48
            "CRITICAL" ^ (if name = "" then "" else " " ^ name) ^ ": obtained lock"));
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    49
      val _ = critical_thread := SOME (Thread.self ());
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    50
      val result = Exn.capture e ();
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    51
      val _ = critical_thread := NONE;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    52
      val _ = Mutex.unlock critical_lock;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    53
    in Exn.release result end;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    54
23991
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
    55
fun CRITICAL e = NAMED_CRITICAL "" e;
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    56
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    57
end;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
    58
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    59
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    60
(* scheduling -- non-interruptible threads working on a queue of tasks *)
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    61
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    62
fun schedule n next_task tasks =
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    63
  let
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    64
    (*protected execution*)
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    65
    val lock = Mutex.mutex ();
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    66
    fun PROTECTED k e =
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    67
      let
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    68
        val _ =
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    69
          if Mutex.trylock lock then ()
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    70
          else
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    71
           (tracing (fn () => "PROTECTED " ^ Int.toString k ^ ": waiting for lock");
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    72
            Mutex.lock lock;
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    73
            tracing (fn () => "PROTECTED " ^ Int.toString k ^ ": obtained lock"));
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    74
        val res = Exn.capture e ();
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    75
        val _ = Mutex.unlock lock;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    76
      in Exn.release res end;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    77
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    78
    (*the queue of tasks*)
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    79
    val queue = ref tasks;
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    80
    fun dequeue k = PROTECTED k (fn () =>
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    81
      let
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    82
        val (next, tasks') = next_task (! queue);
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    83
        val _ = queue := tasks';
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    84
      in next end);
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    85
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    86
    (*worker threads*)
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    87
    val running = ref 0;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    88
    val status = ref ([]: exn list);
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
    89
    val finished = ConditionVar.conditionVar ();
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    90
    fun wait () = ConditionVar.waitUntil (finished, lock, Time.fromMilliseconds 500);
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    91
    fun continue cont k =
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    92
      (PROTECTED k (fn () => queue := cont (! queue)); ConditionVar.signal finished; work k ())
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    93
    and work k () =
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    94
      (case dequeue k of
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    95
        (Task.Task f, cont) =>
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    96
          (tracing (fn () => "TASK " ^ Int.toString k);
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    97
           case Exn.capture f () of
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    98
            Exn.Result () => continue cont k
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
    99
          | Exn.Exn exn =>
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   100
              (PROTECTED k (fn () => status := exn :: ! status); continue cont k))
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   101
      | (Task.Running, _) =>
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   102
          (tracing (fn () => "WAITING " ^ Int.toString k);
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   103
           PROTECTED k wait; work k ())
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   104
      | (Task.Finished, _) =>
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   105
         (tracing (fn () => "TERMINATING " ^ Int.toString k);
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   106
          PROTECTED k (fn () => running := ! running - 1);
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   107
          ConditionVar.signal finished));
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   108
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   109
    (*main control: fork and wait*)
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   110
    fun fork 0 = ()
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   111
      | fork k =
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   112
         (running := ! running + 1;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   113
          Thread.fork (work k, [Thread.InterruptState Thread.InterruptDefer]);
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   114
          fork (k - 1));
23981
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   115
    val _ = PROTECTED 0 (fn () =>
03b71bf91318 added trace flag, official tracing operation;
wenzelm
parents: 23973
diff changeset
   116
     (fork (Int.max (n, 1)); while ! running <> 0 do (tracing (fn () => "MAIN WAIT"); wait ())));
23973
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   117
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   118
  in ! status end;
b6ce6de5b700 renamed number_of_threads to max_threads;
wenzelm
parents: 23961
diff changeset
   119
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
   120
end;
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
   121
23991
d4417ba26706 renamed CRITICAL' to NAMED_CRITICAL;
wenzelm
parents: 23981
diff changeset
   122
val NAMED_CRITICAL = Multithreading.NAMED_CRITICAL;
23961
9e7e1e309ebd Multithreading in Poly/ML (version 5.1).
wenzelm
parents:
diff changeset
   123
val CRITICAL = Multithreading.CRITICAL;