src/Pure/Concurrent/synchronized.ML
author wenzelm
Wed, 06 Sep 2023 20:51:28 +0200
changeset 78650 47d0c333d155
parent 78008 620d0a5d61a2
child 78720 909dc00766a0
permissions -rw-r--r--
clarified signature: retain original Poly/ML names Thread.Thread, Thread.Mutex, Thread.ConditionVar and de-emphasize them for Isabelle/ML;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/Concurrent/synchronized.ML
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     2
    Author:     Fabian Immler and Makarius
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     3
56685
535d59d4ed12 more uniform synchronized variables;
wenzelm
parents: 52537
diff changeset
     4
Synchronized variables.
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     5
*)
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     6
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     7
signature SYNCHRONIZED =
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     8
sig
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
     9
  type 'a var
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    10
  val var: string -> 'a -> 'a var
28580
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    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
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    13
  val timed_access: 'a var -> ('a -> Time.time option) -> ('a -> ('b * 'a) option) -> 'b option
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    14
  val guarded_access: 'a var -> ('a -> ('b * 'a) option) -> 'b
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    15
  val change_result: 'a var -> ('a -> 'b * 'a) -> 'b
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    16
  val change: 'a var -> ('a -> 'a) -> unit
77998
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
    17
  type 'a cache
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
    18
  val cache: (unit -> 'a) -> 'a cache
78008
620d0a5d61a2 more operations;
wenzelm
parents: 78001
diff changeset
    19
  val cache_peek: 'a cache -> 'a option
77998
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
    20
  val cache_eval: 'a cache -> 'a
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    21
end;
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    22
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    23
structure Synchronized: SYNCHRONIZED =
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    24
struct
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    25
56692
8219a65b24e3 synchronized access, similar to ML version;
wenzelm
parents: 56685
diff changeset
    26
(* state variable *)
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    63
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    64
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    65
(* synchronized access *)
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
2fcbd4abc021 clarified modules;
wenzelm
parents: 62891
diff changeset
    89
fun guarded_access var f = the (timed_access var (fn _ => NONE) f);
28580
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    90
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    91
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    92
(* unconditional change *)
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    93
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    94
fun change_result var f = guarded_access var (SOME o f);
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    95
fun change var f = change_result var (fn x => ((), f x));
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
    99
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   100
(* cached evaluation via weak_ref *)
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   101
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   102
abstype 'a cache =
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   103
  Cache of {expr: unit -> 'a, var: 'a Unsynchronized.weak_ref option var}
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   104
with
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   105
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   106
fun cache expr =
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   107
  Cache {expr = expr, var = var "Synchronized.cache" NONE};
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   108
78008
620d0a5d61a2 more operations;
wenzelm
parents: 78001
diff changeset
   109
fun cache_peek (Cache {var, ...}) =
620d0a5d61a2 more operations;
wenzelm
parents: 78001
diff changeset
   110
  Option.mapPartial Unsynchronized.weak_peek (value var);
620d0a5d61a2 more operations;
wenzelm
parents: 78001
diff changeset
   111
77998
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   112
fun cache_eval (Cache {expr, var}) =
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   113
  change_result var (fn state =>
78001
e5c146904c90 clarified signature;
wenzelm
parents: 77998
diff changeset
   114
    (case Option.mapPartial Unsynchronized.weak_peek state of
e5c146904c90 clarified signature;
wenzelm
parents: 77998
diff changeset
   115
      SOME result => (result, state)
e5c146904c90 clarified signature;
wenzelm
parents: 77998
diff changeset
   116
    | NONE =>
e5c146904c90 clarified signature;
wenzelm
parents: 77998
diff changeset
   117
        let val result = expr ()
e5c146904c90 clarified signature;
wenzelm
parents: 77998
diff changeset
   118
        in (result, SOME (Unsynchronized.weak_ref result)) end));
77998
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   119
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
   120
end;
77998
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   121
cad50a7c8091 support for cached evaluation via weak_ref;
wenzelm
parents: 68675
diff changeset
   122
end;