author | wenzelm |
Wed, 06 Sep 2023 20:51:28 +0200 | |
changeset 78650 | 47d0c333d155 |
parent 78008 | 620d0a5d61a2 |
child 78720 | 909dc00766a0 |
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 |
|
77998 | 17 |
type 'a cache |
18 |
val cache: (unit -> 'a) -> 'a cache |
|
78008 | 19 |
val cache_peek: 'a cache -> 'a option |
77998 | 20 |
val cache_eval: 'a cache -> 'a |
28578 | 21 |
end; |
22 |
||
23 |
structure Synchronized: SYNCHRONIZED = |
|
24 |
struct |
|
25 |
||
56692 | 26 |
(* state variable *) |
28578 | 27 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
28 |
datatype 'a state = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
29 |
Immutable of 'a |
78650
47d0c333d155
clarified signature: retain original Poly/ML names Thread.Thread, Thread.Mutex, Thread.ConditionVar and de-emphasize them for Isabelle/ML;
wenzelm
parents:
78008
diff
changeset
|
30 |
| Mutable of {lock: Thread.Mutex.mutex, cond: Thread.ConditionVar.conditionVar, content: 'a}; |
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
31 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
32 |
fun init_state x = |
78650
47d0c333d155
clarified signature: retain original Poly/ML names Thread.Thread, Thread.Mutex, Thread.ConditionVar and de-emphasize them for Isabelle/ML;
wenzelm
parents:
78008
diff
changeset
|
33 |
Mutable {lock = Thread.Mutex.mutex (), cond = Thread.ConditionVar.conditionVar (), content = x}; |
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
34 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
35 |
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
|
36 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
37 |
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
|
38 |
with |
28578 | 39 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
40 |
fun var name x = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
41 |
Var {name = name, state = Unsynchronized.ref (init_state x)}; |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
42 |
|
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
43 |
fun value (Var {name, state}) = |
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 {lock, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
47 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
48 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
49 |
Immutable x => x |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
50 |
| Mutable {content, ...} => content))); |
28578 | 51 |
|
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
52 |
fun assign (Var {name, state}) x = |
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 {lock, cond, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
56 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
57 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
58 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
59 |
| Mutable _ => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
60 |
Thread_Attributes.uninterruptible (fn _ => fn () => |
68675
4535a45182d5
updated to polyml-5.7.1-7 (see also afa7c5a239e6);
wenzelm
parents:
68597
diff
changeset
|
61 |
(state := Immutable x; RunCall.clearMutableBit state; |
78650
47d0c333d155
clarified signature: retain original Poly/ML names Thread.Thread, Thread.Mutex, Thread.ConditionVar and de-emphasize them for Isabelle/ML;
wenzelm
parents:
78008
diff
changeset
|
62 |
Thread.ConditionVar.broadcast cond)) ()))); |
28580 | 63 |
|
28578 | 64 |
|
65 |
(* synchronized access *) |
|
66 |
||
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
67 |
fun timed_access (Var {name, state}) time_limit f = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
68 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
69 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
70 |
| Mutable {lock, cond, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
71 |
Multithreading.synchronized name lock (fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
72 |
let |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
73 |
fun try_change () = |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
74 |
(case ! state of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
75 |
Immutable _ => immutable_fail name |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
76 |
| Mutable {content = x, ...} => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
77 |
(case f x of |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
78 |
NONE => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
79 |
(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
|
80 |
Exn.Res true => try_change () |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
81 |
| Exn.Res false => NONE |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
82 |
| Exn.Exn exn => Exn.reraise exn) |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
83 |
| SOME (y, x') => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
84 |
Thread_Attributes.uninterruptible (fn _ => fn () => |
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
85 |
(state := Mutable {lock = lock, cond = cond, content = x'}; |
78650
47d0c333d155
clarified signature: retain original Poly/ML names Thread.Thread, Thread.Mutex, Thread.ConditionVar and de-emphasize them for Isabelle/ML;
wenzelm
parents:
78008
diff
changeset
|
86 |
Thread.ConditionVar.broadcast cond; SOME y)) ())); |
68597
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents:
64276
diff
changeset
|
87 |
in try_change () end)); |
33060
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
wenzelm
parents:
32738
diff
changeset
|
88 |
|
62918 | 89 |
fun guarded_access var f = the (timed_access var (fn _ => NONE) f); |
28580 | 90 |
|
91 |
||
92 |
(* unconditional change *) |
|
93 |
||
94 |
fun change_result var f = guarded_access var (SOME o f); |
|
28578 | 95 |
fun change var f = change_result var (fn x => ((), f x)); |
96 |
||
35015
efafb3337ef3
removed slightly adhoc single-assignment feature, cf. structure Single_Assignment;
wenzelm
parents:
33060
diff
changeset
|
97 |
end; |
33060
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
wenzelm
parents:
32738
diff
changeset
|
98 |
|
77998 | 99 |
|
100 |
(* cached evaluation via weak_ref *) |
|
101 |
||
102 |
abstype 'a cache = |
|
103 |
Cache of {expr: unit -> 'a, var: 'a Unsynchronized.weak_ref option var} |
|
104 |
with |
|
105 |
||
106 |
fun cache expr = |
|
107 |
Cache {expr = expr, var = var "Synchronized.cache" NONE}; |
|
108 |
||
78008 | 109 |
fun cache_peek (Cache {var, ...}) = |
110 |
Option.mapPartial Unsynchronized.weak_peek (value var); |
|
111 |
||
77998 | 112 |
fun cache_eval (Cache {expr, var}) = |
113 |
change_result var (fn state => |
|
78001 | 114 |
(case Option.mapPartial Unsynchronized.weak_peek state of |
115 |
SOME result => (result, state) |
|
116 |
| NONE => |
|
117 |
let val result = expr () |
|
118 |
in (result, SOME (Unsynchronized.weak_ref result)) end)); |
|
77998 | 119 |
|
28578 | 120 |
end; |
77998 | 121 |
|
122 |
end; |