author | wenzelm |
Thu, 24 Apr 2014 16:52:17 +0200 | |
changeset 56704 | c2f0ddd14747 |
parent 56333 | 38f1422ef473 |
child 59348 | 8a6788917b32 |
permissions | -rw-r--r-- |
52605 | 1 |
(* Title: Pure/PIDE/execution.ML |
52596 | 2 |
Author: Makarius |
3 |
||
52606 | 4 |
Global management of execution. Unique running execution serves as |
53192 | 5 |
barrier for further exploration of forked command execs. |
52596 | 6 |
*) |
7 |
||
52605 | 8 |
signature EXECUTION = |
52596 | 9 |
sig |
52606 | 10 |
val start: unit -> Document_ID.execution |
11 |
val discontinue: unit -> unit |
|
12 |
val is_running: Document_ID.execution -> bool |
|
52784
4ba2e8b9972f
de-assign execs that were not registered as running yet -- observe change of perspective more thoroughly;
wenzelm
parents:
52775
diff
changeset
|
13 |
val is_running_exec: Document_ID.exec -> bool |
53375
78693e46a237
Execution.fork formally requires registered Execution.running;
wenzelm
parents:
53193
diff
changeset
|
14 |
val running: Document_ID.execution -> Document_ID.exec -> Future.group list -> bool |
53192 | 15 |
val peek: Document_ID.exec -> Future.group list |
52655
3b2b1ef13979
more careful termination of removed execs, leaving running execs undisturbed;
wenzelm
parents:
52608
diff
changeset
|
16 |
val cancel: Document_ID.exec -> unit |
3b2b1ef13979
more careful termination of removed execs, leaving running execs undisturbed;
wenzelm
parents:
52608
diff
changeset
|
17 |
val terminate: Document_ID.exec -> unit |
56292 | 18 |
type params = {name: string, pos: Position.T, pri: int} |
19 |
val fork: params -> (unit -> 'a) -> 'a future |
|
56305 | 20 |
val print: params -> (unit -> unit) -> unit |
56292 | 21 |
val fork_prints: Document_ID.exec -> unit |
53192 | 22 |
val purge: Document_ID.exec list -> unit |
23 |
val reset: unit -> Future.group list |
|
24 |
val shutdown: unit -> unit |
|
52596 | 25 |
end; |
26 |
||
52605 | 27 |
structure Execution: EXECUTION = |
52596 | 28 |
struct |
29 |
||
52787
c143ad7811fc
pro-forma Execution.reset, despite lack of final join/commit;
wenzelm
parents:
52784
diff
changeset
|
30 |
(* global state *) |
c143ad7811fc
pro-forma Execution.reset, despite lack of final join/commit;
wenzelm
parents:
52784
diff
changeset
|
31 |
|
56292 | 32 |
type print = {name: string, pri: int, body: unit -> unit}; |
33 |
type exec_state = Future.group list * print list; (*active forks, prints*) |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
34 |
type state = |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
35 |
Document_ID.execution * (*overall document execution*) |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
36 |
exec_state Inttab.table; (*running command execs*) |
52787
c143ad7811fc
pro-forma Execution.reset, despite lack of final join/commit;
wenzelm
parents:
52784
diff
changeset
|
37 |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
38 |
val init_state: state = (Document_ID.none, Inttab.make [(Document_ID.none, ([], []))]); |
52787
c143ad7811fc
pro-forma Execution.reset, despite lack of final join/commit;
wenzelm
parents:
52784
diff
changeset
|
39 |
val state = Synchronized.var "Execution.state" init_state; |
52602
00170ef1dc39
strictly monotonic Document.update: avoid disruptive cancel_execution, merely discontinue_execution and cancel/terminate old execs individually;
wenzelm
parents:
52596
diff
changeset
|
40 |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
41 |
fun get_state () = Synchronized.value state; |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
42 |
fun change_state_result f = Synchronized.change_result state f; |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
43 |
fun change_state f = Synchronized.change state f; |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
44 |
|
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
45 |
fun unregistered exec_id = "Unregistered execution: " ^ Document_ID.print exec_id; |
53192 | 46 |
|
52604 | 47 |
|
52606 | 48 |
(* unique running execution *) |
52604 | 49 |
|
52606 | 50 |
fun start () = |
52602
00170ef1dc39
strictly monotonic Document.update: avoid disruptive cancel_execution, merely discontinue_execution and cancel/terminate old execs individually;
wenzelm
parents:
52596
diff
changeset
|
51 |
let |
52606 | 52 |
val execution_id = Document_ID.make (); |
53192 | 53 |
val _ = change_state (apfst (K execution_id)); |
52606 | 54 |
in execution_id end; |
52604 | 55 |
|
53192 | 56 |
fun discontinue () = change_state (apfst (K Document_ID.none)); |
52606 | 57 |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
58 |
fun is_running execution_id = execution_id = #1 (get_state ()); |
52604 | 59 |
|
60 |
||
53192 | 61 |
(* execs *) |
52604 | 62 |
|
52784
4ba2e8b9972f
de-assign execs that were not registered as running yet -- observe change of perspective more thoroughly;
wenzelm
parents:
52775
diff
changeset
|
63 |
fun is_running_exec exec_id = |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
64 |
Inttab.defined (#2 (get_state ())) exec_id; |
52784
4ba2e8b9972f
de-assign execs that were not registered as running yet -- observe change of perspective more thoroughly;
wenzelm
parents:
52775
diff
changeset
|
65 |
|
53375
78693e46a237
Execution.fork formally requires registered Execution.running;
wenzelm
parents:
53193
diff
changeset
|
66 |
fun running execution_id exec_id groups = |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
67 |
change_state_result (fn (execution_id', execs) => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
68 |
let |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
69 |
val continue = execution_id = execution_id'; |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
70 |
val execs' = |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
71 |
if continue then |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
72 |
Inttab.update_new (exec_id, (groups, [])) execs |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
73 |
handle Inttab.DUP dup => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
74 |
raise Fail ("Execution already registered: " ^ Document_ID.print dup) |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
75 |
else execs; |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
76 |
in (continue, (execution_id', execs')) end); |
53192 | 77 |
|
78 |
fun peek exec_id = |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
79 |
(case Inttab.lookup (#2 (get_state ())) exec_id of |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
80 |
SOME (groups, _) => groups |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
81 |
| NONE => []); |
53192 | 82 |
|
83 |
fun cancel exec_id = List.app Future.cancel_group (peek exec_id); |
|
84 |
fun terminate exec_id = List.app Future.terminate (peek exec_id); |
|
85 |
||
86 |
||
87 |
(* fork *) |
|
88 |
||
89 |
fun status task markups = |
|
56296
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
90 |
let |
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
91 |
val props = |
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
92 |
if ! Multithreading.trace >= 2 |
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
93 |
then [(Markup.taskN, Task_Queue.str_of_task task)] else []; |
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
94 |
in Output.status (implode (map (Markup.markup_only o Markup.properties props) markups)) end; |
53192 | 95 |
|
56292 | 96 |
type params = {name: string, pos: Position.T, pri: int}; |
97 |
||
98 |
fun fork ({name, pos, pri}: params) e = |
|
53192 | 99 |
uninterruptible (fn _ => Position.setmp_thread_data pos (fn () => |
100 |
let |
|
101 |
val exec_id = the_default 0 (Position.parse_id pos); |
|
102 |
val group = Future.worker_subgroup (); |
|
53375
78693e46a237
Execution.fork formally requires registered Execution.running;
wenzelm
parents:
53193
diff
changeset
|
103 |
val _ = change_state (apsnd (fn execs => |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
104 |
(case Inttab.lookup execs exec_id of |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
105 |
SOME (groups, prints) => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
106 |
Inttab.update (exec_id, (group :: groups, prints)) execs |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
107 |
| NONE => raise Fail (unregistered exec_id)))); |
52655
3b2b1ef13979
more careful termination of removed execs, leaving running execs undisturbed;
wenzelm
parents:
52608
diff
changeset
|
108 |
|
53192 | 109 |
val future = |
110 |
(singleton o Future.forks) |
|
111 |
{name = name, group = SOME group, deps = [], pri = pri, interrupts = false} |
|
112 |
(fn () => |
|
113 |
let |
|
114 |
val task = the (Future.worker_task ()); |
|
115 |
val _ = status task [Markup.running]; |
|
116 |
val result = |
|
117 |
Exn.capture (Future.interruptible_task e) () |
|
118 |
|> Future.identify_result pos; |
|
54646
2b38549374ba
more robust status reports: avoid loosing information about physical events (see also 28d207ba9340, 2bc5924b117f, 9edfd36a0355) -- NB: TTY and Proof General ignore Output.status and Output.report;
wenzelm
parents:
53375
diff
changeset
|
119 |
val _ = status task [Markup.joined]; |
53192 | 120 |
val _ = |
121 |
(case result of |
|
54678
87910da843d5
more uniform status -- accommodate spurious Exn.Interrupt from user code, allow ML_Compiler.exn_messages_id to crash;
wenzelm
parents:
54646
diff
changeset
|
122 |
Exn.Exn exn => |
54646
2b38549374ba
more robust status reports: avoid loosing information about physical events (see also 28d207ba9340, 2bc5924b117f, 9edfd36a0355) -- NB: TTY and Proof General ignore Output.status and Output.report;
wenzelm
parents:
53375
diff
changeset
|
123 |
(status task [Markup.failed]; |
54678
87910da843d5
more uniform status -- accommodate spurious Exn.Interrupt from user code, allow ML_Compiler.exn_messages_id to crash;
wenzelm
parents:
54646
diff
changeset
|
124 |
status task [Markup.finished]; |
56333
38f1422ef473
support bulk messages consisting of small string segments, which are more healthy to the Poly/ML RTS and might prevent spurious GC crashes such as MTGCProcessMarkPointers::ScanAddressesInObject;
wenzelm
parents:
56305
diff
changeset
|
125 |
Output.report [Markup.markup_only Markup.bad]; |
54646
2b38549374ba
more robust status reports: avoid loosing information about physical events (see also 28d207ba9340, 2bc5924b117f, 9edfd36a0355) -- NB: TTY and Proof General ignore Output.status and Output.report;
wenzelm
parents:
53375
diff
changeset
|
126 |
if exec_id = 0 then () |
56333
38f1422ef473
support bulk messages consisting of small string segments, which are more healthy to the Poly/ML RTS and might prevent spurious GC crashes such as MTGCProcessMarkPointers::ScanAddressesInObject;
wenzelm
parents:
56305
diff
changeset
|
127 |
else List.app (Future.error_message pos) (Runtime.exn_messages_ids exn)) |
54678
87910da843d5
more uniform status -- accommodate spurious Exn.Interrupt from user code, allow ML_Compiler.exn_messages_id to crash;
wenzelm
parents:
54646
diff
changeset
|
128 |
| Exn.Res _ => |
87910da843d5
more uniform status -- accommodate spurious Exn.Interrupt from user code, allow ML_Compiler.exn_messages_id to crash;
wenzelm
parents:
54646
diff
changeset
|
129 |
status task [Markup.finished]) |
53192 | 130 |
in Exn.release result end); |
54646
2b38549374ba
more robust status reports: avoid loosing information about physical events (see also 28d207ba9340, 2bc5924b117f, 9edfd36a0355) -- NB: TTY and Proof General ignore Output.status and Output.report;
wenzelm
parents:
53375
diff
changeset
|
131 |
|
53192 | 132 |
val _ = status (Future.task_of future) [Markup.forked]; |
133 |
in future end)) (); |
|
52604 | 134 |
|
53192 | 135 |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
136 |
(* print *) |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
137 |
|
56305 | 138 |
fun print ({name, pos, pri}: params) e = |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
139 |
change_state (apsnd (fn execs => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
140 |
let |
56292 | 141 |
val exec_id = the_default 0 (Position.parse_id pos); |
56305 | 142 |
val print = {name = name, pri = pri, body = e}; |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
143 |
in |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
144 |
(case Inttab.lookup execs exec_id of |
56292 | 145 |
SOME (groups, prints) => Inttab.update (exec_id, (groups, print :: prints)) execs |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
146 |
| NONE => raise Fail (unregistered exec_id)) |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
147 |
end)); |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
148 |
|
56292 | 149 |
fun fork_prints exec_id = |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
150 |
(case Inttab.lookup (#2 (get_state ())) exec_id of |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
151 |
SOME (_, prints) => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
152 |
if null prints orelse null (tl prints) orelse not (Multithreading.enabled ()) |
56292 | 153 |
then List.app (fn {body, ...} => body ()) (rev prints) |
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
154 |
else |
56296
5413b6379c0e
less markup by default -- this is stored persistently in Isabelle/Scala;
wenzelm
parents:
56292
diff
changeset
|
155 |
let val pos = Position.thread_data () in |
56292 | 156 |
List.app (fn {name, pri, body} => |
157 |
ignore (fork {name = name, pos = pos, pri = pri} body)) (rev prints) |
|
158 |
end |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
159 |
| NONE => raise Fail (unregistered exec_id)); |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
160 |
|
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
161 |
|
53192 | 162 |
(* cleanup *) |
163 |
||
164 |
fun purge exec_ids = |
|
165 |
(change_state o apsnd) (fn execs => |
|
166 |
let |
|
167 |
val execs' = fold Inttab.delete_safe exec_ids execs; |
|
168 |
val () = |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
169 |
(execs', ()) |-> Inttab.fold (fn (exec_id, (groups, _)) => fn () => |
53192 | 170 |
if Inttab.defined execs' exec_id then () |
171 |
else groups |> List.app (fn group => |
|
172 |
if Task_Queue.is_canceled group then () |
|
53375
78693e46a237
Execution.fork formally requires registered Execution.running;
wenzelm
parents:
53193
diff
changeset
|
173 |
else raise Fail ("Attempt to purge valid execution: " ^ Document_ID.print exec_id))); |
53192 | 174 |
in execs' end); |
175 |
||
176 |
fun reset () = |
|
56291
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
177 |
change_state_result (fn (_, execs) => |
e79f76a48449
added Execution.print: accumulate print operations for some command execution, which are applied later and print time;
wenzelm
parents:
54678
diff
changeset
|
178 |
let val groups = Inttab.fold (append o #1 o #2) execs [] |
53192 | 179 |
in (groups, init_state) end); |
180 |
||
181 |
fun shutdown () = |
|
182 |
(Future.shutdown (); |
|
183 |
(case maps Task_Queue.group_status (reset ()) of |
|
184 |
[] => () |
|
185 |
| exns => raise Par_Exn.make exns)); |
|
186 |
||
187 |
end; |
|
188 |