src/Pure/Concurrent/par_exn.ML
author wenzelm
Wed, 17 Aug 2011 22:25:00 +0200
changeset 45126 6a3541412b23
parent 45125 270366301bd7
child 45127 64620f1d6f87
permissions -rw-r--r--
clarified Par_Exn.release_first: traverse topmost list structure only, not arbitrary depths of nested Par_Exn;
wenzelm@45125
     1
(*  Title:      Pure/Concurrent/par_exn.ML
wenzelm@45125
     2
    Author:     Makarius
wenzelm@45125
     3
wenzelm@45125
     4
Parallel exceptions as flattened results from acyclic graph of
wenzelm@45125
     5
evaluations.  Interrupt counts as neutral element.
wenzelm@45125
     6
*)
wenzelm@45125
     7
wenzelm@45125
     8
signature PAR_EXN =
wenzelm@45125
     9
sig
wenzelm@45125
    10
  val make: exn list -> exn
wenzelm@45125
    11
  val dest: exn -> (serial * exn) list option
wenzelm@45125
    12
  val release_all: 'a Exn.result list -> 'a list
wenzelm@45125
    13
  val release_first: 'a Exn.result list -> 'a list
wenzelm@45125
    14
end;
wenzelm@45125
    15
wenzelm@45125
    16
structure Par_Exn =
wenzelm@45125
    17
struct
wenzelm@45125
    18
wenzelm@45125
    19
(* parallel exceptions *)
wenzelm@45125
    20
wenzelm@45125
    21
exception Par_Exn of (serial * exn) Ord_List.T;
wenzelm@45125
    22
wenzelm@45125
    23
fun exn_ord ((i, _), (j, _)) = int_ord (j, i);
wenzelm@45125
    24
wenzelm@45125
    25
fun par_exns (Par_Exn exns) = SOME exns
wenzelm@45125
    26
  | par_exns exn = if Exn.is_interrupt exn then NONE else SOME [(serial (), exn)];
wenzelm@45125
    27
wenzelm@45125
    28
fun make exns =
wenzelm@45125
    29
  (case map_filter par_exns exns of
wenzelm@45125
    30
    [] => Exn.Interrupt
wenzelm@45125
    31
  | e :: es => Par_Exn (Library.foldl (Ord_List.merge exn_ord) (e, es)));
wenzelm@45125
    32
wenzelm@45125
    33
fun dest (Par_Exn exns) = SOME (rev exns)
wenzelm@45125
    34
  | dest _ = NONE;
wenzelm@45125
    35
wenzelm@45125
    36
wenzelm@45125
    37
(* parallel results *)
wenzelm@45125
    38
wenzelm@45125
    39
fun all_res results = forall (fn Exn.Res _ => true | _ => false) results;
wenzelm@45125
    40
wenzelm@45125
    41
fun release_all results =
wenzelm@45125
    42
  if all_res results then map Exn.release results
wenzelm@45125
    43
  else raise make (map_filter Exn.get_exn results);
wenzelm@45125
    44
wenzelm@45126
    45
fun release_first results =
wenzelm@45126
    46
  if all_res results then map Exn.release results
wenzelm@45126
    47
  else
wenzelm@45126
    48
    (case get_first
wenzelm@45126
    49
        (fn res => if Exn.is_interrupt_exn res then NONE else Exn.get_exn res) results of
wenzelm@45126
    50
      NONE => Exn.interrupt ()
wenzelm@45126
    51
    | SOME exn => reraise exn);
wenzelm@45125
    52
wenzelm@45125
    53
end;
wenzelm@45125
    54