src/Pure/Concurrent/par_exn.ML
author wenzelm
Fri, 06 Dec 2019 16:05:24 +0100
changeset 71250 bd93c71521a0
parent 63806 c54a53ef1873
child 78674 88f47c70187a
permissions -rw-r--r--
tuned signature;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/Concurrent/par_exn.ML
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     3
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     4
Parallel exceptions as flattened results from acyclic graph of
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     5
evaluations.  Interrupt counts as neutral element.
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     6
*)
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     7
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     8
signature PAR_EXN =
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
     9
sig
71250
bd93c71521a0 tuned signature;
wenzelm
parents: 63806
diff changeset
    10
  val identify: Properties.T -> exn -> exn
50911
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    11
  val the_serial: exn -> int
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    12
  val make: exn list -> exn
44271
89f40a5939b2 more precise treatment of exception nesting and serial numbers;
wenzelm
parents: 44270
diff changeset
    13
  val dest: exn -> exn list option
49061
7449b804073b central management of forked goals wrt. transaction id;
wenzelm
parents: 47338
diff changeset
    14
  val is_interrupted: 'a Exn.result list -> bool
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    15
  val release_all: 'a Exn.result list -> 'a list
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    16
  val release_first: 'a Exn.result list -> 'a list
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    17
end;
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    18
47338
e331c6256a41 proper signature constraint;
wenzelm
parents: 44334
diff changeset
    19
structure Par_Exn: PAR_EXN =
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    20
struct
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    21
51428
12e46440e391 more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
wenzelm
parents: 50911
diff changeset
    22
(* identification via serial numbers -- NOT portable! *)
44249
64620f1d6f87 identify parallel exceptions where they emerge first -- to achieve unique results within evaluation graph;
wenzelm
parents: 44248
diff changeset
    23
50911
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    24
fun identify default_props exn =
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    25
  let
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    26
    val props = Exn_Properties.get exn;
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    27
    val update_serial =
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    28
      if Properties.defined props Markup.serialN then []
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    29
      else [(Markup.serialN, serial_string ())];
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    30
    val update_props = filter_out (Properties.defined props o #1) default_props;
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    31
  in Exn_Properties.update (update_serial @ update_props) exn end;
44249
64620f1d6f87 identify parallel exceptions where they emerge first -- to achieve unique results within evaluation graph;
wenzelm
parents: 44248
diff changeset
    32
50911
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    33
fun the_serial exn =
63806
c54a53ef1873 clarified modules;
wenzelm
parents: 62505
diff changeset
    34
  Value.parse_int (the (Properties.get (Exn_Properties.get exn) Markup.serialN));
44270
3eaad39e520c more careful treatment of exception serial numbers, with propagation to message channel;
wenzelm
parents: 44266
diff changeset
    35
59058
a78612c67ec0 renamed "pairself" to "apply2", in accordance to @{apply 2};
wenzelm
parents: 51428
diff changeset
    36
val exn_ord = rev_order o int_ord o apply2 the_serial;
44249
64620f1d6f87 identify parallel exceptions where they emerge first -- to achieve unique results within evaluation graph;
wenzelm
parents: 44248
diff changeset
    37
64620f1d6f87 identify parallel exceptions where they emerge first -- to achieve unique results within evaluation graph;
wenzelm
parents: 44248
diff changeset
    38
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    39
(* parallel exceptions *)
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    40
44264
c21ecbb028b6 tune Par_Exn.make: balance merge;
wenzelm
parents: 44249
diff changeset
    41
exception Par_Exn of exn list;
c21ecbb028b6 tune Par_Exn.make: balance merge;
wenzelm
parents: 44249
diff changeset
    42
  (*non-empty list with unique identified elements sorted by exn_ord;
c21ecbb028b6 tune Par_Exn.make: balance merge;
wenzelm
parents: 44249
diff changeset
    43
    no occurrences of Par_Exn or Exn.Interrupt*)
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    44
44264
c21ecbb028b6 tune Par_Exn.make: balance merge;
wenzelm
parents: 44249
diff changeset
    45
fun par_exns (Par_Exn exns) = exns
50911
ee7fe4230642 more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents: 50909
diff changeset
    46
  | par_exns exn = if Exn.is_interrupt exn then [] else [identify [] exn];
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    47
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    48
fun make exns =
51428
12e46440e391 more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
wenzelm
parents: 50911
diff changeset
    49
  let
12e46440e391 more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
wenzelm
parents: 50911
diff changeset
    50
    val exnss = map par_exns exns;
12e46440e391 more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
wenzelm
parents: 50911
diff changeset
    51
    val exns' = Ord_List.unions exn_ord exnss handle Option.Option => flat exnss;
12e46440e391 more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
wenzelm
parents: 50911
diff changeset
    52
  in if null exns' then Exn.Interrupt else Par_Exn exns' end;
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    53
44271
89f40a5939b2 more precise treatment of exception nesting and serial numbers;
wenzelm
parents: 44270
diff changeset
    54
fun dest (Par_Exn exns) = SOME exns
44270
3eaad39e520c more careful treatment of exception serial numbers, with propagation to message channel;
wenzelm
parents: 44266
diff changeset
    55
  | dest exn = if Exn.is_interrupt exn then SOME [] else NONE;
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    56
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    57
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    58
(* parallel results *)
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    59
49061
7449b804073b central management of forked goals wrt. transaction id;
wenzelm
parents: 47338
diff changeset
    60
fun is_interrupted results =
7449b804073b central management of forked goals wrt. transaction id;
wenzelm
parents: 47338
diff changeset
    61
  exists (fn Exn.Exn _ => true | _ => false) results andalso
7449b804073b central management of forked goals wrt. transaction id;
wenzelm
parents: 47338
diff changeset
    62
    Exn.is_interrupt (make (map_filter Exn.get_exn results));
7449b804073b central management of forked goals wrt. transaction id;
wenzelm
parents: 47338
diff changeset
    63
44266
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    64
fun release_all results =
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    65
  if forall (fn Exn.Res _ => true | _ => false) results
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    66
  then map Exn.release results
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    67
  else raise make (map_filter Exn.get_exn results);
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    68
44266
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    69
fun plain_exn (Exn.Res _) = NONE
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    70
  | plain_exn (Exn.Exn (Par_Exn _)) = NONE
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    71
  | plain_exn (Exn.Exn exn) = if Exn.is_interrupt exn then NONE else SOME exn;
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    72
44248
6a3541412b23 clarified Par_Exn.release_first: traverse topmost list structure only, not arbitrary depths of nested Par_Exn;
wenzelm
parents: 44247
diff changeset
    73
fun release_first results =
44266
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    74
  (case get_first plain_exn results of
d9c7bf932eab clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents: 44264
diff changeset
    75
    NONE => release_all results
62505
9e2a65912111 clarified modules;
wenzelm
parents: 59058
diff changeset
    76
  | SOME exn => Exn.reraise exn);
44247
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    77
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    78
end;
270366301bd7 more systematic handling of parallel exceptions;
wenzelm
parents:
diff changeset
    79