| author | wenzelm | 
| Tue, 31 Oct 2023 16:49:03 +0100 | |
| changeset 78869 | f464f6bc5809 | 
| parent 78720 | 909dc00766a0 | 
| child 80073 | 40f5ddeda2b4 | 
| 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: 
64276diff
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: 
64276diff
changeset | 28 | datatype 'a state = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
78008diff
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: 
64276diff
changeset | 31 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
78008diff
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: 
64276diff
changeset | 34 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
64276diff
changeset | 36 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
33060diff
changeset | 38 | with | 
| 28578 | 39 | |
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 40 | fun var name x = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 41 |   Var {name = name, state = Unsynchronized.ref (init_state x)};
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 42 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 43 | fun value (Var {name, state}) =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 44 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 45 | Immutable x => x | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 46 |   | Mutable {lock, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 47 | Multithreading.synchronized name lock (fn () => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 48 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 49 | Immutable x => x | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 50 |         | Mutable {content, ...} => content)));
 | 
| 28578 | 51 | |
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 52 | fun assign (Var {name, state}) x =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 53 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 54 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 55 |   | Mutable {lock, cond, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 56 | Multithreading.synchronized name lock (fn () => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 57 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 58 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 59 | | Mutable _ => | 
| 78720 | 60 | Thread_Attributes.uninterruptible_body (fn _ => | 
| 68675 
4535a45182d5
updated to polyml-5.7.1-7 (see also afa7c5a239e6);
 wenzelm parents: 
68597diff
changeset | 61 | (state := Immutable x; RunCall.clearMutableBit state; | 
| 78720 | 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: 
64276diff
changeset | 67 | fun timed_access (Var {name, state}) time_limit f =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 68 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 69 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 70 |   | Mutable {lock, cond, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 71 | Multithreading.synchronized name lock (fn () => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 72 | let | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 73 | fun try_change () = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 74 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 75 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 76 |             | Mutable {content = x, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 77 | (case f x of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 78 | NONE => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 79 | (case Multithreading.sync_wait (time_limit x) cond lock of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 80 | Exn.Res true => try_change () | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 81 | | Exn.Res false => NONE | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 82 | | Exn.Exn exn => Exn.reraise exn) | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 83 | | SOME (y, x') => | 
| 78720 | 84 | Thread_Attributes.uninterruptible_body (fn _ => | 
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 85 |                       (state := Mutable {lock = lock, cond = cond, content = x'};
 | 
| 78720 | 86 | Thread.ConditionVar.broadcast cond; SOME y)))); | 
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 87 | in try_change () end)); | 
| 33060 
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
 wenzelm parents: 
32738diff
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: 
33060diff
changeset | 97 | end; | 
| 33060 
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
 wenzelm parents: 
32738diff
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; |