src/Pure/Concurrent/synchronized.ML
author wenzelm
Fri, 06 Jul 2018 15:35:48 +0200
changeset 68597 afa7c5a239e6
parent 64276 622f4e4ac388
child 68675 4535a45182d5
permissions -rw-r--r--
more frugal assignment of lazy value: fewer mutexes, condvars; cannot use RunCall.clearMutableBit due to spurious crashes;
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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    17
end;
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    18
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    19
structure Synchronized: SYNCHRONIZED =
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    20
struct
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    21
56692
8219a65b24e3 synchronized access, similar to ML version;
wenzelm
parents: 56685
diff changeset
    22
(* state variable *)
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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 () =>
afa7c5a239e6 more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents: 64276
diff changeset
    57
             (state := Immutable x; (* FIXME RunCall.clearMutableBit state; *)
afa7c5a239e6 more frugal assignment of lazy value: fewer mutexes, condvars;
wenzelm
parents: 64276
diff changeset
    58
               ConditionVar.broadcast cond)) ())));
28580
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    59
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    60
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    61
(* synchronized access *)
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
2fcbd4abc021 clarified modules;
wenzelm
parents: 62891
diff changeset
    85
fun guarded_access var f = the (timed_access var (fn _ => NONE) f);
28580
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    86
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    87
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    88
(* unconditional change *)
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    89
3f37ae257506 added value;
wenzelm
parents: 28578
diff changeset
    90
fun change_result var f = guarded_access var (SOME o f);
28578
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    91
fun change var f = change_result var (fn x => ((), f x));
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    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
c7f2a0899679 State variables with synchronized access.
wenzelm
parents:
diff changeset
    95
end;