src/Pure/Concurrent/par_exn.ML
author wenzelm
Thu, 18 Aug 2011 15:39:00 +0200
changeset 45149 d9c7bf932eab
parent 45147 c21ecbb028b6
child 45153 3eaad39e520c
permissions -rw-r--r--
clarified Par_Exn.release_first: prefer plain exn, before falling back on full pack of parallel exceptions;
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@45127
    10
  val serial: exn -> serial * exn
wenzelm@45125
    11
  val make: exn list -> exn
wenzelm@45127
    12
  val dest: exn -> exn list option
wenzelm@45125
    13
  val release_all: 'a Exn.result list -> 'a list
wenzelm@45125
    14
  val release_first: 'a Exn.result list -> 'a list
wenzelm@45125
    15
end;
wenzelm@45125
    16
wenzelm@45125
    17
structure Par_Exn =
wenzelm@45125
    18
struct
wenzelm@45125
    19
wenzelm@45127
    20
(* identification via serial numbers *)
wenzelm@45127
    21
wenzelm@45127
    22
fun serial exn =
wenzelm@45127
    23
  (case get_exn_serial exn of
wenzelm@45127
    24
    SOME i => (i, exn)
wenzelm@45127
    25
  | NONE => let val i = Library.serial () in (i, set_exn_serial i exn) end);
wenzelm@45127
    26
wenzelm@45127
    27
val exn_ord = rev_order o int_ord o pairself (the o get_exn_serial);
wenzelm@45127
    28
wenzelm@45127
    29
wenzelm@45125
    30
(* parallel exceptions *)
wenzelm@45125
    31
wenzelm@45147
    32
exception Par_Exn of exn list;
wenzelm@45147
    33
  (*non-empty list with unique identified elements sorted by exn_ord;
wenzelm@45147
    34
    no occurrences of Par_Exn or Exn.Interrupt*)
wenzelm@45125
    35
wenzelm@45147
    36
fun par_exns (Par_Exn exns) = exns
wenzelm@45147
    37
  | par_exns exn = if Exn.is_interrupt exn then [] else [#2 (serial exn)];
wenzelm@45125
    38
wenzelm@45125
    39
fun make exns =
wenzelm@45147
    40
  (case Balanced_Tree.make (Ord_List.merge exn_ord) ([] :: map par_exns exns) of
wenzelm@45125
    41
    [] => Exn.Interrupt
wenzelm@45147
    42
  | es => Par_Exn es);
wenzelm@45125
    43
wenzelm@45147
    44
fun dest (Par_Exn exns) = SOME exns
wenzelm@45125
    45
  | dest _ = NONE;
wenzelm@45125
    46
wenzelm@45125
    47
wenzelm@45125
    48
(* parallel results *)
wenzelm@45125
    49
wenzelm@45125
    50
fun release_all results =
wenzelm@45149
    51
  if forall (fn Exn.Res _ => true | _ => false) results
wenzelm@45149
    52
  then map Exn.release results
wenzelm@45125
    53
  else raise make (map_filter Exn.get_exn results);
wenzelm@45125
    54
wenzelm@45149
    55
fun plain_exn (Exn.Res _) = NONE
wenzelm@45149
    56
  | plain_exn (Exn.Exn (Par_Exn _)) = NONE
wenzelm@45149
    57
  | plain_exn (Exn.Exn exn) = if Exn.is_interrupt exn then NONE else SOME exn;
wenzelm@45149
    58
wenzelm@45126
    59
fun release_first results =
wenzelm@45149
    60
  (case get_first plain_exn results of
wenzelm@45149
    61
    NONE => release_all results
wenzelm@45149
    62
  | SOME exn => reraise exn);
wenzelm@45125
    63
wenzelm@45125
    64
end;
wenzelm@45125
    65