src/Pure/Concurrent/synchronized.ML
changeset 28578 c7f2a0899679
child 28580 3f37ae257506
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Pure/Concurrent/synchronized.ML	Mon Oct 13 15:48:40 2008 +0200
@@ -0,0 +1,53 @@
+(*  Title:      Pure/Concurrent/synchronized.ML
+    ID:         $Id$
+    Author:     Fabian Immler and Makarius
+
+State variables with synchronized access.
+*)
+
+signature SYNCHRONIZED =
+sig
+  type 'a var
+  val var: string -> 'a -> 'a var
+  val guarded_change: ('a -> bool) -> ('a -> Time.time option) ->
+    'a var -> (bool -> 'a -> 'b * 'a) -> 'b
+  val change_result: 'a var -> ('a -> 'b * 'a) -> 'b
+  val change: 'a var -> ('a -> 'a) -> unit
+end;
+
+structure Synchronized: SYNCHRONIZED =
+struct
+
+(* state variables *)
+
+datatype 'a var = Var of
+ {name: string,
+  lock: Mutex.mutex,
+  cond: ConditionVar.conditionVar,
+  var: 'a ref};
+
+fun var name x = Var
+ {name = name,
+  lock = Mutex.mutex (),
+  cond = ConditionVar.conditionVar (),
+  var = ref x};
+
+
+(* synchronized access *)
+
+fun guarded_change guard time_limit (Var {name, lock, cond, var}) f =
+  SimpleThread.synchronized name lock (fn () =>
+    let
+      fun check () = guard (! var) orelse
+        (case time_limit (! var) of
+          NONE => (ConditionVar.wait (cond, lock); check ())
+        | SOME t => ConditionVar.waitUntil (cond, lock, t) andalso check ());
+      val ok = check ();
+      val res = change_result var (f ok);
+      val _ = ConditionVar.broadcast cond;
+    in res end);
+
+fun change_result var f = guarded_change (K true) (K NONE) var (K f);
+fun change var f = change_result var (fn x => ((), f x));
+
+end;