| author | wenzelm | 
| Sun, 26 Feb 2023 21:17:10 +0100 | |
| changeset 77386 | cae3d891adff | 
| parent 71250 | bd93c71521a0 | 
| child 78674 | 88f47c70187a | 
| permissions | -rw-r--r-- | 
| 44247 | 1 | (* Title: Pure/Concurrent/par_exn.ML | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Parallel exceptions as flattened results from acyclic graph of | |
| 5 | evaluations. Interrupt counts as neutral element. | |
| 6 | *) | |
| 7 | ||
| 8 | signature PAR_EXN = | |
| 9 | sig | |
| 71250 | 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: 
50909diff
changeset | 11 | val the_serial: exn -> int | 
| 44247 | 12 | val make: exn list -> exn | 
| 44271 
89f40a5939b2
more precise treatment of exception nesting and serial numbers;
 wenzelm parents: 
44270diff
changeset | 13 | val dest: exn -> exn list option | 
| 49061 
7449b804073b
central management of forked goals wrt. transaction id;
 wenzelm parents: 
47338diff
changeset | 14 | val is_interrupted: 'a Exn.result list -> bool | 
| 44247 | 15 | val release_all: 'a Exn.result list -> 'a list | 
| 16 | val release_first: 'a Exn.result list -> 'a list | |
| 17 | end; | |
| 18 | ||
| 47338 | 19 | structure Par_Exn: PAR_EXN = | 
| 44247 | 20 | struct | 
| 21 | ||
| 51428 
12e46440e391
more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
 wenzelm parents: 
50911diff
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: 
44248diff
changeset | 23 | |
| 50911 
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
 wenzelm parents: 
50909diff
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: 
50909diff
changeset | 25 | let | 
| 
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
 wenzelm parents: 
50909diff
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: 
50909diff
changeset | 27 | val update_serial = | 
| 
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
 wenzelm parents: 
50909diff
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: 
50909diff
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: 
50909diff
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: 
50909diff
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: 
44248diff
changeset | 32 | |
| 50911 
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
 wenzelm parents: 
50909diff
changeset | 33 | fun the_serial exn = | 
| 63806 | 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: 
44266diff
changeset | 35 | |
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
51428diff
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: 
44248diff
changeset | 37 | |
| 
64620f1d6f87
identify parallel exceptions where they emerge first -- to achieve unique results within evaluation graph;
 wenzelm parents: 
44248diff
changeset | 38 | |
| 44247 | 39 | (* parallel exceptions *) | 
| 40 | ||
| 44264 | 41 | exception Par_Exn of exn list; | 
| 42 | (*non-empty list with unique identified elements sorted by exn_ord; | |
| 43 | no occurrences of Par_Exn or Exn.Interrupt*) | |
| 44247 | 44 | |
| 44264 | 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: 
50909diff
changeset | 46 | | par_exns exn = if Exn.is_interrupt exn then [] else [identify [] exn]; | 
| 44247 | 47 | |
| 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: 
50911diff
changeset | 49 | let | 
| 
12e46440e391
more robust Par_Exn.make, especially relevant for SML/NJ trying to use Par_Exn.release_all;
 wenzelm parents: 
50911diff
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: 
50911diff
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: 
50911diff
changeset | 52 | in if null exns' then Exn.Interrupt else Par_Exn exns' end; | 
| 44247 | 53 | |
| 44271 
89f40a5939b2
more precise treatment of exception nesting and serial numbers;
 wenzelm parents: 
44270diff
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: 
44266diff
changeset | 55 | | dest exn = if Exn.is_interrupt exn then SOME [] else NONE; | 
| 44247 | 56 | |
| 57 | ||
| 58 | (* parallel results *) | |
| 59 | ||
| 49061 
7449b804073b
central management of forked goals wrt. transaction id;
 wenzelm parents: 
47338diff
changeset | 60 | fun is_interrupted results = | 
| 
7449b804073b
central management of forked goals wrt. transaction id;
 wenzelm parents: 
47338diff
changeset | 61 | exists (fn Exn.Exn _ => true | _ => false) results andalso | 
| 
7449b804073b
central management of forked goals wrt. transaction id;
 wenzelm parents: 
47338diff
changeset | 62 | Exn.is_interrupt (make (map_filter Exn.get_exn results)); | 
| 
7449b804073b
central management of forked goals wrt. transaction id;
 wenzelm parents: 
47338diff
changeset | 63 | |
| 44266 
d9c7bf932eab
clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
 wenzelm parents: 
44264diff
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: 
44264diff
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: 
44264diff
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: 
44264diff
changeset | 67 | else raise make (map_filter Exn.get_exn results); | 
| 44247 | 68 | |
| 44266 
d9c7bf932eab
clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
 wenzelm parents: 
44264diff
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: 
44264diff
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: 
44264diff
changeset | 71 | | plain_exn (Exn.Exn exn) = if Exn.is_interrupt exn then NONE else SOME exn; | 
| 44247 | 72 | |
| 44248 
6a3541412b23
clarified Par_Exn.release_first: traverse topmost list structure only, not arbitrary depths of nested Par_Exn;
 wenzelm parents: 
44247diff
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: 
44264diff
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: 
44264diff
changeset | 75 | NONE => release_all results | 
| 62505 | 76 | | SOME exn => Exn.reraise exn); | 
| 44247 | 77 | |
| 78 | end; | |
| 79 |