author | wenzelm |
Wed, 17 Aug 2011 22:25:00 +0200 | |
changeset 45126 | 6a3541412b23 |
parent 45125 | 270366301bd7 |
child 45127 | 64620f1d6f87 |
permissions | -rw-r--r-- |
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 |