author | wenzelm |
Mon, 29 Jul 2019 18:16:51 +0200 | |
changeset 70440 | 03cfef16ddb4 |
parent 68675 | 4535a45182d5 |
child 77998 | cad50a7c8091 |
permissions | -rw-r--r-- |
28578 | 1 |
(* Title: Pure/Concurrent/synchronized.ML |
2 |
Author: Fabian Immler and Makarius |
|
3 |
||
56685 | 4 |
Synchronized variables. |
28578 | 5 |
*) |
6 |
||
7 |
signature SYNCHRONIZED = |
|
8 |
sig |
|
9 |
type 'a var |
|
10 |
val var: string -> 'a -> 'a var |
|
28580 | 11 |
val value: 'a var -> 'a |
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
12 |
val assign: 'a var -> 'a -> unit |
28580 | 13 |
val timed_access: 'a var -> ('a -> Time.time option) -> ('a -> ('b * 'a) option) -> 'b option |
14 |
val guarded_access: 'a var -> ('a -> ('b * 'a) option) -> 'b |
|
28578 | 15 |
val change_result: 'a var -> ('a -> 'b * 'a) -> 'b |
16 |
val change: 'a var -> ('a -> 'a) -> unit |
|
17 |
end; |
|
18 |
||
19 |
structure Synchronized: SYNCHRONIZED = |
|
20 |
struct |
|
21 |
||
56692 | 22 |
(* state variable *) |
28578 | 23 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
24 |
datatype 'a state = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
25 |
Immutable of 'a |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
26 |
| Mutable of {lock: Mutex.mutex, cond: ConditionVar.conditionVar, content: 'a}; |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
27 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
28 |
fun init_state x = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
29 |
Mutable {lock = Mutex.mutex (), cond = ConditionVar.conditionVar (), content = x}; |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
30 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
31 |
fun immutable_fail name = raise Fail ("Illegal access to immutable value " ^ name); |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
32 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
33 |
abstype 'a var = Var of {name: string, state: 'a state Unsynchronized.ref} |
35015
efafb3337ef3
removed slightly adhoc single-assignment feature, cf. structure Single_Assignment;
wenzelm
parents:
33060
diff
changeset
|
34 |
with |
28578 | 35 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
36 |
fun var name x = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
37 |
Var {name = name, state = Unsynchronized.ref (init_state x)}; |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
38 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
39 |
fun value (Var {name, state}) = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
40 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
41 |
Immutable x => x |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
42 |
| Mutable {lock, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
43 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
44 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
45 |
Immutable x => x |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
46 |
| Mutable {content, ...} => content))); |
28578 | 47 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
48 |
fun assign (Var {name, state}) x = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
49 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
50 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
51 |
| Mutable {lock, cond, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
52 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
53 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
54 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
55 |
| Mutable _ => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
56 |
Thread_Attributes.uninterruptible (fn _ => fn () => |
68675
4535a45182d5
updated to polyml-5.7.1-7 (see also afa7c5a239e6);
wenzelm
parents:
68597
diff
changeset
|
57 |
(state := Immutable x; RunCall.clearMutableBit state; |
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
58 |
ConditionVar.broadcast cond)) ()))); |
28580 | 59 |
|
28578 | 60 |
|
61 |
(* synchronized access *) |
|
62 |
||
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
63 |
fun timed_access (Var {name, state}) time_limit f = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
64 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
65 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
66 |
| Mutable {lock, cond, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
67 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
68 |
let |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
69 |
fun try_change () = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
70 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
71 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
72 |
| Mutable {content = x, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
73 |
(case f x of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
74 |
NONE => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
75 |
(case Multithreading.sync_wait (time_limit x) cond lock of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
76 |
Exn.Res true => try_change () |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
77 |
| Exn.Res false => NONE |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
78 |
| Exn.Exn exn => Exn.reraise exn) |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
79 |
| SOME (y, x') => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
80 |
Thread_Attributes.uninterruptible (fn _ => fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
81 |
(state := Mutable {lock = lock, cond = cond, content = x'}; |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
82 |
ConditionVar.broadcast cond; SOME y)) ())); |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
83 |
in try_change () end)); |
33060
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
wenzelm
parents:
32738
diff
changeset
|
84 |
|
62918 | 85 |
fun guarded_access var f = the (timed_access var (fn _ => NONE) f); |
28580 | 86 |
|
87 |
||
88 |
(* unconditional change *) |
|
89 |
||
90 |
fun change_result var f = guarded_access var (SOME o f); |
|
28578 | 91 |
fun change var f = change_result var (fn x => ((), f x)); |
92 |
||
35015
efafb3337ef3
removed slightly adhoc single-assignment feature, cf. structure Single_Assignment;
wenzelm
parents:
33060
diff
changeset
|
93 |
end; |
33060
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
wenzelm
parents:
32738
diff
changeset
|
94 |
|
28578 | 95 |
end; |