src/Pure/Concurrent/single_assignment.ML
author wenzelm
Mon, 15 Nov 2010 17:14:43 +0100
changeset 40545 956c2cc7fced
parent 37906 4195727a1f6c
child 43761 e72ba84ae58f
permissions -rw-r--r--
more robust treatment of spaces in file names;

(*  Title:      Pure/Concurrent/single_assignment.ML
    Author:     Makarius

Single-assignment variables with locking/signalling.
*)

signature SINGLE_ASSIGNMENT =
sig
  type 'a var
  val var: string -> 'a var
  val peek: 'a var -> 'a option
  val await: 'a var -> 'a
  val assign: 'a var -> 'a -> unit
end;

structure Single_Assignment: SINGLE_ASSIGNMENT =
struct

abstype 'a var = Var of
 {name: string,
  lock: Mutex.mutex,
  cond: ConditionVar.conditionVar,
  var: 'a SingleAssignment.saref}
with

fun var name = Var
 {name = name,
  lock = Mutex.mutex (),
  cond = ConditionVar.conditionVar (),
  var = SingleAssignment.saref ()};

fun peek (Var {var, ...}) = SingleAssignment.savalue var;

fun await (v as Var {name, lock, cond, ...}) =
  Simple_Thread.synchronized name lock (fn () =>
    let
      fun wait () =
        (case peek v of
          NONE =>
            (case Multithreading.sync_wait NONE NONE cond lock of
              Exn.Result _ => wait ()
            | Exn.Exn exn => reraise exn)
        | SOME x => x);
    in wait () end);

fun assign (v as Var {name, lock, cond, var}) x =
  Simple_Thread.synchronized name lock (fn () =>
    (case peek v of
      SOME _ => raise Fail ("Duplicate assignment to variable " ^ quote name)
    | NONE =>
        uninterruptible (fn _ => fn () =>
         (SingleAssignment.saset (var, x); ConditionVar.broadcast cond)) ()));

end;

end;