author | wenzelm |
Sat, 28 Mar 2015 17:26:42 +0100 | |
changeset 59828 | 0e9baaf0e0bb |
parent 59058 | a78612c67ec0 |
child 62505 | 9e2a65912111 |
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 |
|
50911
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents:
50909
diff
changeset
|
10 |
val identify: Properties.entry list -> exn -> exn |
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 | 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 | 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:
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 = |
ee7fe4230642
more explicit treatment of (optional) exception properties, notably for "serial" -- avoid conflict with startPosition = offset;
wenzelm
parents:
50909
diff
changeset
|
34 |
Markup.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 | 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:
50909
diff
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:
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 | 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 | 56 |
|
57 |
||
58 |
(* parallel results *) |
|
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 | 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 | 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 |
d9c7bf932eab
clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
wenzelm
parents:
44264
diff
changeset
|
76 |
| SOME exn => reraise exn); |
44247 | 77 |
|
78 |
end; |
|
79 |