1 (* Title: Pure/Concurrent/par_exn.ML
4 Parallel exceptions as flattened results from acyclic graph of
5 evaluations. Interrupt counts as neutral element.
10 val serial: exn -> serial * exn
11 val make: exn list -> exn
12 val dest: exn -> exn list option
13 val release_all: 'a Exn.result list -> 'a list
14 val release_first: 'a Exn.result list -> 'a list
20 (* identification via serial numbers *)
23 (case get_exn_serial exn of
25 | NONE => let val i = Library.serial () in (i, set_exn_serial i exn) end);
27 val exn_ord = rev_order o int_ord o pairself (the o get_exn_serial);
30 (* parallel exceptions *)
32 exception Par_Exn of exn list;
33 (*non-empty list with unique identified elements sorted by exn_ord;
34 no occurrences of Par_Exn or Exn.Interrupt*)
36 fun par_exns (Par_Exn exns) = exns
37 | par_exns exn = if Exn.is_interrupt exn then [] else [#2 (serial exn)];
40 (case Balanced_Tree.make (Ord_List.merge exn_ord) ([] :: map par_exns exns) of
44 fun dest (Par_Exn exns) = SOME exns
48 (* parallel results *)
50 fun all_res results = forall (fn Exn.Res _ => true | _ => false) results;
52 fun release_all results =
53 if all_res results then map Exn.release results
54 else raise make (map_filter Exn.get_exn results);
56 fun release_first results =
57 if all_res results then map Exn.release results
60 (fn res => if Exn.is_interrupt_exn res then NONE else Exn.get_exn res) results of
61 NONE => Exn.interrupt ()
62 | SOME exn => reraise exn);