src/Pure/Concurrent/synchronized.ML
changeset 28578 c7f2a0899679
child 28580 3f37ae257506
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/Pure/Concurrent/synchronized.ML	Mon Oct 13 15:48:40 2008 +0200
     1.3 @@ -0,0 +1,53 @@
     1.4 +(*  Title:      Pure/Concurrent/synchronized.ML
     1.5 +    ID:         $Id$
     1.6 +    Author:     Fabian Immler and Makarius
     1.7 +
     1.8 +State variables with synchronized access.
     1.9 +*)
    1.10 +
    1.11 +signature SYNCHRONIZED =
    1.12 +sig
    1.13 +  type 'a var
    1.14 +  val var: string -> 'a -> 'a var
    1.15 +  val guarded_change: ('a -> bool) -> ('a -> Time.time option) ->
    1.16 +    'a var -> (bool -> 'a -> 'b * 'a) -> 'b
    1.17 +  val change_result: 'a var -> ('a -> 'b * 'a) -> 'b
    1.18 +  val change: 'a var -> ('a -> 'a) -> unit
    1.19 +end;
    1.20 +
    1.21 +structure Synchronized: SYNCHRONIZED =
    1.22 +struct
    1.23 +
    1.24 +(* state variables *)
    1.25 +
    1.26 +datatype 'a var = Var of
    1.27 + {name: string,
    1.28 +  lock: Mutex.mutex,
    1.29 +  cond: ConditionVar.conditionVar,
    1.30 +  var: 'a ref};
    1.31 +
    1.32 +fun var name x = Var
    1.33 + {name = name,
    1.34 +  lock = Mutex.mutex (),
    1.35 +  cond = ConditionVar.conditionVar (),
    1.36 +  var = ref x};
    1.37 +
    1.38 +
    1.39 +(* synchronized access *)
    1.40 +
    1.41 +fun guarded_change guard time_limit (Var {name, lock, cond, var}) f =
    1.42 +  SimpleThread.synchronized name lock (fn () =>
    1.43 +    let
    1.44 +      fun check () = guard (! var) orelse
    1.45 +        (case time_limit (! var) of
    1.46 +          NONE => (ConditionVar.wait (cond, lock); check ())
    1.47 +        | SOME t => ConditionVar.waitUntil (cond, lock, t) andalso check ());
    1.48 +      val ok = check ();
    1.49 +      val res = change_result var (f ok);
    1.50 +      val _ = ConditionVar.broadcast cond;
    1.51 +    in res end);
    1.52 +
    1.53 +fun change_result var f = guarded_change (K true) (K NONE) var (K f);
    1.54 +fun change var f = change_result var (fn x => ((), f x));
    1.55 +
    1.56 +end;