clarified execution: maintain running execs only, check "stable" separately via memo (again);
tuned signatures;
1.1 --- a/src/Pure/PIDE/command.ML Fri Jul 12 11:28:03 2013 +0200
1.2 +++ b/src/Pure/PIDE/command.ML Fri Jul 12 12:04:16 2013 +0200
1.3 @@ -8,8 +8,9 @@
1.4 sig
1.5 val read: (unit -> theory) -> Token.T list -> Toplevel.transition
1.6 type eval
1.7 + val eval_eq: eval * eval -> bool
1.8 val eval_result_state: eval -> Toplevel.state
1.9 - val eval_same: eval * eval -> bool
1.10 + val eval_stable: eval -> bool
1.11 val eval: (unit -> theory) -> Token.T list -> eval -> eval
1.12 type print
1.13 val print: bool -> string -> eval -> print list -> print list option
1.14 @@ -40,10 +41,15 @@
1.15
1.16 fun memo_result (Memo v) =
1.17 (case Synchronized.value v of
1.18 - Result res => Exn.release res
1.19 - | Expr (exec_id, _) => error ("Unfinished execution result: " ^ Document_ID.print exec_id));
1.20 + Expr (exec_id, _) => error ("Unfinished execution result: " ^ Document_ID.print exec_id)
1.21 + | Result res => Exn.release res);
1.22
1.23 -fun memo_exec context (Memo v) =
1.24 +fun memo_stable (Memo v) =
1.25 + (case Synchronized.value v of
1.26 + Expr _ => true
1.27 + | Result res => not (Exn.is_interrupt_exn res));
1.28 +
1.29 +fun memo_exec execution_id (Memo v) =
1.30 (case Synchronized.value v of
1.31 Result res => res
1.32 | Expr _ =>
1.33 @@ -51,23 +57,24 @@
1.34 (fn Result res => SOME (res, Result res)
1.35 | expr as Expr (exec_id, e) =>
1.36 uninterruptible (fn restore_attributes => fn () =>
1.37 - if Execution.running context exec_id then
1.38 + if Execution.running execution_id exec_id then
1.39 let
1.40 val res = Exn.capture (restore_attributes e) ();
1.41 - val _ = Execution.finished exec_id (not (Exn.is_interrupt_exn res));
1.42 + val _ = Execution.finished exec_id;
1.43 in SOME (res, Result res) end
1.44 else SOME (Exn.interrupt_exn, expr)) ())
1.45 |> (fn NONE => error "Concurrent execution attempt" | SOME res => res))
1.46 |> Exn.release |> ignore;
1.47
1.48 -fun memo_fork params context (Memo v) =
1.49 +fun memo_fork params execution_id (Memo v) =
1.50 (case Synchronized.value v of
1.51 Result _ => ()
1.52 - | _ => ignore ((singleton o Future.forks) params (fn () => memo_exec context (Memo v))));
1.53 + | _ => ignore ((singleton o Future.forks) params (fn () => memo_exec execution_id (Memo v))));
1.54
1.55 end;
1.56
1.57
1.58 +
1.59 (** main phases of execution **)
1.60
1.61 (* read *)
1.62 @@ -109,11 +116,13 @@
1.63
1.64 datatype eval = Eval of {exec_id: Document_ID.exec, eval_process: eval_state memo};
1.65
1.66 +fun eval_eq (Eval {exec_id, ...}, Eval {exec_id = exec_id', ...}) = exec_id = exec_id';
1.67 +
1.68 fun eval_result (Eval {eval_process, ...}) = memo_result eval_process;
1.69 val eval_result_state = #state o eval_result;
1.70
1.71 -fun eval_same (Eval {exec_id, ...}, Eval {exec_id = exec_id', ...}) =
1.72 - exec_id = exec_id' andalso Execution.is_stable exec_id;
1.73 +fun eval_stable (Eval {exec_id, eval_process}) =
1.74 + Goal.stable_futures exec_id andalso memo_stable eval_process;
1.75
1.76 local
1.77
1.78 @@ -197,9 +206,12 @@
1.79 (Toplevel.setmp_thread_position tr o Runtime.controlled_execution) e () handle exn =>
1.80 List.app (Future.error_msg (Toplevel.pos_of tr)) (ML_Compiler.exn_messages_ids exn);
1.81
1.82 +fun print_eq (Print {exec_id, ...}, Print {exec_id = exec_id', ...}) = exec_id = exec_id';
1.83 +
1.84 +fun print_stable (Print {exec_id, print_process, ...}) =
1.85 + Goal.stable_futures exec_id andalso memo_stable print_process;
1.86 +
1.87 fun print_persistent (Print {persistent, ...}) = persistent;
1.88 -fun print_stable (Print {exec_id, ...}) = Execution.is_stable exec_id;
1.89 -fun print_eq (Print {exec_id, ...}, Print {exec_id = exec_id', ...}) = exec_id = exec_id';
1.90
1.91 in
1.92
1.93 @@ -276,15 +288,15 @@
1.94
1.95 local
1.96
1.97 -fun run_print context (Print {name, pri, print_process, ...}) =
1.98 +fun run_print execution_id (Print {name, pri, print_process, ...}) =
1.99 (if Multithreading.enabled () then
1.100 memo_fork {name = name, group = NONE, deps = [], pri = pri, interrupts = true}
1.101 - else memo_exec) context print_process;
1.102 + else memo_exec) execution_id print_process;
1.103
1.104 in
1.105
1.106 -fun exec context (Eval {eval_process, ...}, prints) =
1.107 - (memo_exec context eval_process; List.app (run_print context) prints);
1.108 +fun exec execution_id (Eval {eval_process, ...}, prints) =
1.109 + (memo_exec execution_id eval_process; List.app (run_print execution_id) prints);
1.110
1.111 end;
1.112
2.1 --- a/src/Pure/PIDE/document.ML Fri Jul 12 11:28:03 2013 +0200
2.2 +++ b/src/Pure/PIDE/document.ML Fri Jul 12 12:04:16 2013 +0200
2.3 @@ -108,7 +108,7 @@
2.4
2.5 fun changed_result node node' =
2.6 (case (get_result node, get_result node') of
2.7 - (SOME eval, SOME eval') => not (Command.eval_same (eval, eval'))
2.8 + (SOME eval, SOME eval') => not (Command.eval_eq (eval, eval'))
2.9 | (NONE, NONE) => false
2.10 | _ => true);
2.11
2.12 @@ -401,7 +401,8 @@
2.13 val flags' = update_flags prev flags;
2.14 val same' =
2.15 (case (lookup_entry node0 command_id, opt_exec) of
2.16 - (SOME (eval0, _), SOME (eval, _)) => Command.eval_same (eval0, eval)
2.17 + (SOME (eval0, _), SOME (eval, _)) =>
2.18 + Command.eval_eq (eval0, eval) andalso Command.eval_stable eval
2.19 | _ => false);
2.20 val assign_update' = assign_update |> same' ?
2.21 (case opt_exec of
2.22 @@ -445,7 +446,7 @@
2.23
2.24 fun cancel_old_execs node0 (command_id, exec_ids) =
2.25 subtract (op =) exec_ids (Command.exec_ids (lookup_entry node0 command_id))
2.26 - |> map_filter (Execution.peek_running #> Option.map (tap Future.cancel_group));
2.27 + |> map_filter (Execution.peek #> Option.map (tap Future.cancel_group));
2.28
2.29 in
2.30
3.1 --- a/src/Pure/PIDE/execution.ML Fri Jul 12 11:28:03 2013 +0200
3.2 +++ b/src/Pure/PIDE/execution.ML Fri Jul 12 12:04:16 2013 +0200
3.3 @@ -11,18 +11,17 @@
3.4 val discontinue: unit -> unit
3.5 val is_running: Document_ID.execution -> bool
3.6 val running: Document_ID.execution -> Document_ID.exec -> bool
3.7 - val finished: Document_ID.exec -> bool -> unit
3.8 - val is_stable: Document_ID.exec -> bool
3.9 - val peek_running: Document_ID.exec -> Future.group option
3.10 - val purge_canceled: unit -> unit
3.11 - val terminate_all: unit -> unit
3.12 + val finished: Document_ID.exec -> unit
3.13 + val peek: Document_ID.exec -> Future.group option
3.14 + val snapshot: unit -> Future.group list
3.15 end;
3.16
3.17 structure Execution: EXECUTION =
3.18 struct
3.19
3.20 -type status = Future.group option; (*SOME group: running, NONE: canceled*)
3.21 -val state = Synchronized.var "Execution.state" (Document_ID.none, Inttab.empty: status Inttab.table);
3.22 +val state =
3.23 + Synchronized.var "Execution.state"
3.24 + (Document_ID.none, Inttab.empty: Future.group Inttab.table);
3.25
3.26
3.27 (* unique running execution *)
3.28 @@ -48,46 +47,23 @@
3.29 val continue = execution_id = execution_id';
3.30 val execs' =
3.31 if continue then
3.32 - Inttab.update_new (exec_id, SOME (Future.the_worker_group ())) execs
3.33 + Inttab.update_new (exec_id, Future.the_worker_group ()) execs
3.34 handle Inttab.DUP dup => error ("Duplicate execution " ^ Document_ID.print dup)
3.35 else execs;
3.36 in SOME (continue, (execution_id', execs')) end);
3.37
3.38 -fun finished exec_id stable =
3.39 +fun finished exec_id =
3.40 Synchronized.change state
3.41 (apsnd (fn execs =>
3.42 - if not (Inttab.defined execs exec_id) then
3.43 - error ("Attempt to finish unknown execution: " ^ Document_ID.print exec_id)
3.44 - else if stable then Inttab.delete exec_id execs
3.45 - else Inttab.update (exec_id, NONE) execs));
3.46 + Inttab.delete exec_id execs
3.47 + handle Inttab.UNDEF bad =>
3.48 + error ("Attempt to finish unknown execution: " ^ Document_ID.print bad)));
3.49
3.50 -fun is_stable exec_id =
3.51 - not (Par_Exn.is_interrupted (Future.join_results (Goal.peek_futures exec_id))) andalso
3.52 - (case Inttab.lookup (snd (Synchronized.value state)) exec_id of
3.53 - NONE => true
3.54 - | SOME status => is_some status);
3.55 +fun peek exec_id =
3.56 + Inttab.lookup (snd (Synchronized.value state)) exec_id;
3.57
3.58 -fun peek_running exec_id =
3.59 - (case Inttab.lookup (snd (Synchronized.value state)) exec_id of
3.60 - SOME (SOME group) => SOME group
3.61 - | _ => NONE);
3.62 -
3.63 -fun purge_canceled () =
3.64 - Synchronized.guarded_access state
3.65 - (fn (execution_id, execs) =>
3.66 - let
3.67 - val canceled = Inttab.fold (fn (exec_id, NONE) => cons exec_id | _ => I) execs [];
3.68 - val execs' = fold Inttab.delete canceled execs;
3.69 - in SOME ((), (execution_id, execs')) end);
3.70 -
3.71 -fun terminate_all () =
3.72 - let
3.73 - val groups =
3.74 - Inttab.fold (fn (_, SOME group) => cons group | _ => I)
3.75 - (snd (Synchronized.value state)) [];
3.76 - val _ = List.app Future.cancel_group groups;
3.77 - val _ = List.app Future.terminate groups;
3.78 - in () end;
3.79 +fun snapshot () =
3.80 + Inttab.fold (cons o #2) (snd (Synchronized.value state)) [];
3.81
3.82 end;
3.83
4.1 --- a/src/Pure/PIDE/protocol.ML Fri Jul 12 11:28:03 2013 +0200
4.2 +++ b/src/Pure/PIDE/protocol.ML Fri Jul 12 12:04:16 2013 +0200
4.3 @@ -21,7 +21,13 @@
4.4
4.5 val _ =
4.6 Isabelle_Process.protocol_command "Document.cancel_execution"
4.7 - (fn [] => (Execution.discontinue (); Execution.terminate_all ()));
4.8 + (fn [] =>
4.9 + let
4.10 + val _ = Execution.discontinue ();
4.11 + val groups = Execution.snapshot ();
4.12 + val _ = List.app Future.cancel_group groups;
4.13 + val _ = List.app Future.terminate groups;
4.14 + in () end);
4.15
4.16 val _ =
4.17 Isabelle_Process.protocol_command "Document.update"
4.18 @@ -54,7 +60,6 @@
4.19 val (assign_update, state') = Document.update old_id new_id edits state;
4.20
4.21 val _ = List.app Future.cancel_group (Goal.reset_futures ());
4.22 - val _ = Execution.purge_canceled ();
4.23 val _ = Isabelle_Process.reset_tracing ();
4.24
4.25 val _ =
5.1 --- a/src/Pure/goal.ML Fri Jul 12 11:28:03 2013 +0200
5.2 +++ b/src/Pure/goal.ML Fri Jul 12 12:04:16 2013 +0200
5.3 @@ -27,7 +27,8 @@
5.4 val norm_result: thm -> thm
5.5 val fork_params: {name: string, pos: Position.T, pri: int} -> (unit -> 'a) -> 'a future
5.6 val fork: int -> (unit -> 'a) -> 'a future
5.7 - val peek_futures: serial -> unit future list
5.8 + val peek_futures: int -> unit future list
5.9 + val stable_futures: int-> bool
5.10 val reset_futures: unit -> Future.group list
5.11 val shutdown_futures: unit -> unit
5.12 val skip_proofs_enabled: unit -> bool
5.13 @@ -181,6 +182,9 @@
5.14 fun peek_futures id =
5.15 Inttab.lookup_list (#3 (Synchronized.value forked_proofs)) id;
5.16
5.17 +fun stable_futures id =
5.18 + not (Par_Exn.is_interrupted (Future.join_results (peek_futures id)));
5.19 +
5.20 fun reset_futures () =
5.21 Synchronized.change_result forked_proofs (fn (_, groups, _) =>
5.22 (Future.forked_proofs := 0; (groups, (0, [], Inttab.empty))));