| author | wenzelm | 
| Mon, 13 Apr 2020 17:40:44 +0200 | |
| changeset 71749 | 77232ff6b8f6 | 
| 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: 
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
 | |
| 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: 
64276diff
changeset | 24 | datatype 'a state = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 25 | Immutable of 'a | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 26 |   | Mutable of {lock: Mutex.mutex, cond: ConditionVar.conditionVar, content: 'a};
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 27 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 28 | fun init_state x = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 29 |   Mutable {lock = Mutex.mutex (), cond = ConditionVar.conditionVar (), content = x};
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 30 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
64276diff
changeset | 32 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
33060diff
changeset | 34 | with | 
| 28578 | 35 | |
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 36 | fun var name x = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 37 |   Var {name = name, state = Unsynchronized.ref (init_state x)};
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 38 | |
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 39 | fun value (Var {name, state}) =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 40 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 41 | Immutable x => x | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 42 |   | Mutable {lock, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 43 | Multithreading.synchronized name lock (fn () => | 
| 
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 {content, ...} => content)));
 | 
| 28578 | 47 | |
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 48 | fun assign (Var {name, state}) x =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 49 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 50 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 51 |   | Mutable {lock, cond, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 52 | Multithreading.synchronized name lock (fn () => | 
| 
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 _ => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 56 | Thread_Attributes.uninterruptible (fn _ => fn () => | 
| 68675 
4535a45182d5
updated to polyml-5.7.1-7 (see also afa7c5a239e6);
 wenzelm parents: 
68597diff
changeset | 57 | (state := Immutable x; RunCall.clearMutableBit state; | 
| 68597 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
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: 
64276diff
changeset | 63 | fun timed_access (Var {name, state}) time_limit f =
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 64 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 65 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 66 |   | Mutable {lock, cond, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 67 | Multithreading.synchronized name lock (fn () => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 68 | let | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 69 | fun try_change () = | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 70 | (case ! state of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 71 | Immutable _ => immutable_fail name | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 72 |             | Mutable {content = x, ...} =>
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 73 | (case f x of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 74 | NONE => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 75 | (case Multithreading.sync_wait (time_limit x) cond lock of | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 76 | Exn.Res true => try_change () | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 77 | | Exn.Res false => NONE | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 78 | | Exn.Exn exn => Exn.reraise exn) | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 79 | | SOME (y, x') => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 80 | Thread_Attributes.uninterruptible (fn _ => fn () => | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 81 |                       (state := Mutable {lock = lock, cond = cond, content = x'};
 | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 82 | ConditionVar.broadcast cond; SOME y)) ())); | 
| 
afa7c5a239e6
more frugal assignment of lazy value: fewer mutexes, condvars;
 wenzelm parents: 
64276diff
changeset | 83 | in try_change () end)); | 
| 33060 
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
 wenzelm parents: 
32738diff
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: 
33060diff
changeset | 93 | end; | 
| 33060 
e66b41782cb5
support single-assigment variables -- based on magic RTS operations by David Matthews;
 wenzelm parents: 
32738diff
changeset | 94 | |
| 28578 | 95 | end; |