43 (* state of thread manager *) |
51 (* state of thread manager *) |
44 |
52 |
45 type state = |
53 type state = |
46 {manager: Thread.thread option, |
54 {manager: Thread.thread option, |
47 timeout_heap: Thread_Heap.T, |
55 timeout_heap: Thread_Heap.T, |
48 active: (Thread.thread * (string * Time.time * Time.time * string)) list, |
56 active: |
49 canceling: (Thread.thread * (string * Time.time * string)) list, |
57 (Thread.thread |
50 messages: (string * string) list, |
58 * (string * Time.time * Time.time * (string * string))) list, |
51 store: (string * string) list} |
59 canceling: (Thread.thread * (string * Time.time * (string * string))) list, |
|
60 messages: (bool * (string * (string * string))) list, |
|
61 store: (string * (string * string)) list} |
52 |
62 |
53 fun make_state manager timeout_heap active canceling messages store : state = |
63 fun make_state manager timeout_heap active canceling messages store : state = |
54 {manager = manager, timeout_heap = timeout_heap, active = active, |
64 {manager = manager, timeout_heap = timeout_heap, active = active, |
55 canceling = canceling, messages = messages, store = store} |
65 canceling = canceling, messages = messages, store = store} |
56 |
66 |
58 (make_state NONE Thread_Heap.empty [] [] [] []); |
68 (make_state NONE Thread_Heap.empty [] [] [] []); |
59 |
69 |
60 |
70 |
61 (* unregister thread *) |
71 (* unregister thread *) |
62 |
72 |
63 fun unregister message thread = |
73 fun unregister (urgent, message) thread = |
64 Synchronized.change global_state |
74 Synchronized.change global_state |
65 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
75 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
66 (case lookup_thread active thread of |
76 (case lookup_thread active thread of |
67 SOME (tool, _, _, desc) => |
77 SOME (tool, _, _, desc as (worker, its_desc)) => |
68 let |
78 let |
69 val active' = delete_thread thread active; |
79 val active' = delete_thread thread active; |
70 val now = Time.now () |
80 val now = Time.now () |
71 val canceling' = (thread, (tool, now, desc)) :: canceling |
81 val canceling' = (thread, (tool, now, desc)) :: canceling |
72 val message' = desc ^ "\n" ^ message |
82 val message' = (worker, its_desc ^ "\n" ^ message) |
73 val messages' = (tool, message') :: messages; |
83 val messages' = (urgent, (tool, message')) :: messages |
74 val store' = (tool, message') :: |
84 val store' = (tool, message') :: |
75 (if length store <= message_store_limit then store |
85 (if length store <= message_store_limit then store |
76 else #1 (chop message_store_limit store)); |
86 else #1 (chop message_store_limit store)); |
77 in make_state manager timeout_heap active' canceling' messages' store' end |
87 in make_state manager timeout_heap active' canceling' messages' store' end |
78 | NONE => state)); |
88 | NONE => state)); |
93 aux (String.sub (s, 0) :: seen) (String.extract (s, 1, NONE)) |
103 aux (String.sub (s, 0) :: seen) (String.extract (s, 1, NONE)) |
94 in aux [] end |
104 in aux [] end |
95 |
105 |
96 (* This is a workaround for Proof General's off-by-a-few sendback display bug, |
106 (* This is a workaround for Proof General's off-by-a-few sendback display bug, |
97 whereby "pr" in "proof" is not highlighted. *) |
107 whereby "pr" in "proof" is not highlighted. *) |
98 val break_into_chunks = maps (space_explode "\000" o replace_all "\n\n" "\000") |
108 val break_into_chunks = space_explode "\000" o replace_all "\n\n" "\000" |
99 |
109 |
100 fun print_new_messages () = |
110 fun print_new_messages () = |
101 case Synchronized.change_result global_state |
111 Synchronized.change_result global_state |
102 (fn {manager, timeout_heap, active, canceling, messages, store} => |
112 (fn {manager, timeout_heap, active, canceling, messages, store} => |
103 (messages, make_state manager timeout_heap active canceling [] |
113 messages |
104 store)) of |
114 |> List.partition (fn (urgent, _) => null active orelse urgent) |
105 [] => () |
115 ||> (fn postponed_messages => |
106 | msgs as (tool, _) :: _ => |
116 make_state manager timeout_heap active canceling |
107 let val ss = break_into_chunks (map snd msgs) in |
117 postponed_messages store)) |
108 List.app Output.urgent_message (tool ^ ": " ^ hd ss :: tl ss) |
118 |> map (fn (_, (tool, (worker, work))) => ((tool, work), worker)) |
109 end |
119 |> AList.group (op =) |
|
120 |> List.app (fn ((tool, work), workers) => |
|
121 tool ^ ": " ^ |
|
122 implode_message (workers |> sort string_ord, work) |
|
123 |> break_into_chunks |
|
124 |> List.app Output.urgent_message) |
110 |
125 |
111 fun check_thread_manager () = Synchronized.change global_state |
126 fun check_thread_manager () = Synchronized.change global_state |
112 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
127 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
113 if (case manager of SOME thread => Thread.isActive thread | NONE => false) then state |
128 if (case manager of SOME thread => Thread.isActive thread | NONE => false) then state |
114 else let val manager = SOME (Toplevel.thread false (fn () => |
129 else let val manager = SOME (Toplevel.thread false (fn () => |
166 (Toplevel.thread true |
181 (Toplevel.thread true |
167 (fn () => |
182 (fn () => |
168 let |
183 let |
169 val self = Thread.self () |
184 val self = Thread.self () |
170 val _ = register tool birth_time death_time desc self |
185 val _ = register tool birth_time death_time desc self |
171 val message = f () |
186 in unregister (f ()) self end); |
172 in unregister message self end); |
|
173 ()) |
187 ()) |
174 |
188 |
175 |
189 |
176 (** user commands **) |
190 (** user commands **) |
177 |
191 |
178 (* kill threads *) |
192 (* kill threads *) |
179 |
193 |
180 fun kill_threads tool workers = Synchronized.change global_state |
194 fun kill_threads tool das_wort_worker = Synchronized.change global_state |
181 (fn {manager, timeout_heap, active, canceling, messages, store} => |
195 (fn {manager, timeout_heap, active, canceling, messages, store} => |
182 let |
196 let |
183 val killing = |
197 val killing = |
184 map_filter (fn (th, (tool', _, _, desc)) => |
198 map_filter (fn (th, (tool', _, _, desc)) => |
185 if tool' = tool then SOME (th, (tool', Time.now (), desc)) |
199 if tool' = tool then SOME (th, (tool', Time.now (), desc)) |
186 else NONE) active |
200 else NONE) active |
187 val state' = make_state manager timeout_heap [] (killing @ canceling) messages store; |
201 val state' = make_state manager timeout_heap [] (killing @ canceling) messages store; |
188 val _ = if null killing then () else Output.urgent_message ("Killed active " ^ workers ^ ".") |
202 val _ = |
|
203 if null killing then () |
|
204 else Output.urgent_message ("Killed active " ^ das_wort_worker ^ "s.") |
189 in state' end); |
205 in state' end); |
190 |
206 |
191 |
207 |
192 (* running threads *) |
208 (* running threads *) |
193 |
209 |
194 fun seconds time = string_of_int (Time.toSeconds time) ^ " s" |
210 fun seconds time = string_of_int (Time.toSeconds time) ^ " s" |
195 |
211 |
196 fun running_threads tool workers = |
212 fun running_threads tool das_wort_worker = |
197 let |
213 let |
198 val {active, canceling, ...} = Synchronized.value global_state; |
214 val {active, canceling, ...} = Synchronized.value global_state; |
199 |
215 |
200 val now = Time.now (); |
216 val now = Time.now (); |
201 fun running_info (_, (tool', birth_time, death_time, desc)) = |
217 fun running_info (_, (tool', birth_time, death_time, desc)) = |
202 if tool' = tool then |
218 if tool' = tool then |
203 SOME ("Running: " ^ seconds (Time.- (now, birth_time)) ^ " -- " ^ |
219 SOME ("Running: " ^ seconds (Time.- (now, birth_time)) ^ " -- " ^ |
204 seconds (Time.- (death_time, now)) ^ " to live:\n" ^ desc) |
220 seconds (Time.- (death_time, now)) ^ " to live:\n" ^ |
|
221 implode_desc desc) |
205 else |
222 else |
206 NONE |
223 NONE |
207 fun canceling_info (_, (tool', death_time, desc)) = |
224 fun canceling_info (_, (tool', death_time, desc)) = |
208 if tool' = tool then |
225 if tool' = tool then |
209 SOME ("Trying to interrupt thread since " ^ |
226 SOME ("Trying to interrupt " ^ das_wort_worker ^ " since " ^ |
210 seconds (Time.- (now, death_time)) ^ ":\n" ^ desc) |
227 seconds (Time.- (now, death_time)) ^ ":\n" ^ implode_desc desc) |
211 else |
228 else |
212 NONE |
229 NONE |
213 val running = |
230 val running = |
214 case map_filter running_info active of |
231 case map_filter running_info active of |
215 [] => ["No " ^ workers ^ " running."] |
232 [] => ["No " ^ das_wort_worker ^ "s running."] |
216 | ss => "Running " ^ workers ^ ":" :: ss |
233 | ss => "Running " ^ das_wort_worker ^ "s " :: ss |
217 val interrupting = |
234 val interrupting = |
218 case map_filter canceling_info canceling of |
235 case map_filter canceling_info canceling of |
219 [] => [] |
236 [] => [] |
220 | ss => "Trying to interrupt the following " ^ workers ^ ":" :: ss |
237 | ss => "Interrupting " ^ das_wort_worker ^ "s " :: ss |
221 in Output.urgent_message (space_implode "\n\n" (running @ interrupting)) end |
238 in Output.urgent_message (space_implode "\n\n" (running @ interrupting)) end |
222 |
239 |
223 fun thread_messages tool worker opt_limit = |
240 fun thread_messages tool das_wort_worker opt_limit = |
224 let |
241 let |
225 val limit = the_default message_display_limit opt_limit; |
242 val limit = the_default message_display_limit opt_limit; |
226 val tool_store = Synchronized.value global_state |
243 val tool_store = Synchronized.value global_state |
227 |> #store |> filter (curry (op =) tool o fst) |
244 |> #store |> filter (curry (op =) tool o fst) |
228 val header = |
245 val header = |
229 "Recent " ^ worker ^ " messages" ^ |
246 "Recent " ^ das_wort_worker ^ " messages" ^ |
230 (if length tool_store <= limit then ":" |
247 (if length tool_store <= limit then ":" |
231 else " (" ^ string_of_int limit ^ " displayed):"); |
248 else " (" ^ string_of_int limit ^ " displayed):"); |
232 in |
249 val ss = tool_store |> chop limit |> #1 |> map (implode_desc o snd) |
233 List.app Output.urgent_message (header :: break_into_chunks |
250 in List.app Output.urgent_message (header :: maps break_into_chunks ss) end |
234 (map snd (#1 (chop limit tool_store)))) |
|
235 end |
|
236 |
251 |
237 end; |
252 end; |