wenzelm@28578
|
1 |
(* Title: Pure/Concurrent/synchronized.ML
|
wenzelm@28578
|
2 |
ID: $Id$
|
wenzelm@28578
|
3 |
Author: Fabian Immler and Makarius
|
wenzelm@28578
|
4 |
|
wenzelm@28578
|
5 |
State variables with synchronized access.
|
wenzelm@28578
|
6 |
*)
|
wenzelm@28578
|
7 |
|
wenzelm@28578
|
8 |
signature SYNCHRONIZED =
|
wenzelm@28578
|
9 |
sig
|
wenzelm@28578
|
10 |
type 'a var
|
wenzelm@28578
|
11 |
val var: string -> 'a -> 'a var
|
wenzelm@28578
|
12 |
val guarded_change: ('a -> bool) -> ('a -> Time.time option) ->
|
wenzelm@28578
|
13 |
'a var -> (bool -> 'a -> 'b * 'a) -> 'b
|
wenzelm@28578
|
14 |
val change_result: 'a var -> ('a -> 'b * 'a) -> 'b
|
wenzelm@28578
|
15 |
val change: 'a var -> ('a -> 'a) -> unit
|
wenzelm@28578
|
16 |
end;
|
wenzelm@28578
|
17 |
|
wenzelm@28578
|
18 |
structure Synchronized: SYNCHRONIZED =
|
wenzelm@28578
|
19 |
struct
|
wenzelm@28578
|
20 |
|
wenzelm@28578
|
21 |
(* state variables *)
|
wenzelm@28578
|
22 |
|
wenzelm@28578
|
23 |
datatype 'a var = Var of
|
wenzelm@28578
|
24 |
{name: string,
|
wenzelm@28578
|
25 |
lock: Mutex.mutex,
|
wenzelm@28578
|
26 |
cond: ConditionVar.conditionVar,
|
wenzelm@28578
|
27 |
var: 'a ref};
|
wenzelm@28578
|
28 |
|
wenzelm@28578
|
29 |
fun var name x = Var
|
wenzelm@28578
|
30 |
{name = name,
|
wenzelm@28578
|
31 |
lock = Mutex.mutex (),
|
wenzelm@28578
|
32 |
cond = ConditionVar.conditionVar (),
|
wenzelm@28578
|
33 |
var = ref x};
|
wenzelm@28578
|
34 |
|
wenzelm@28578
|
35 |
|
wenzelm@28578
|
36 |
(* synchronized access *)
|
wenzelm@28578
|
37 |
|
wenzelm@28578
|
38 |
fun guarded_change guard time_limit (Var {name, lock, cond, var}) f =
|
wenzelm@28578
|
39 |
SimpleThread.synchronized name lock (fn () =>
|
wenzelm@28578
|
40 |
let
|
wenzelm@28578
|
41 |
fun check () = guard (! var) orelse
|
wenzelm@28578
|
42 |
(case time_limit (! var) of
|
wenzelm@28578
|
43 |
NONE => (ConditionVar.wait (cond, lock); check ())
|
wenzelm@28578
|
44 |
| SOME t => ConditionVar.waitUntil (cond, lock, t) andalso check ());
|
wenzelm@28578
|
45 |
val ok = check ();
|
wenzelm@28578
|
46 |
val res = change_result var (f ok);
|
wenzelm@28578
|
47 |
val _ = ConditionVar.broadcast cond;
|
wenzelm@28578
|
48 |
in res end);
|
wenzelm@28578
|
49 |
|
wenzelm@28578
|
50 |
fun change_result var f = guarded_change (K true) (K NONE) var (K f);
|
wenzelm@28578
|
51 |
fun change var f = change_result var (fn x => ((), f x));
|
wenzelm@28578
|
52 |
|
wenzelm@28578
|
53 |
end;
|