110 filtered_clauses: cnf_thm list} |
117 filtered_clauses: cnf_thm list} |
111 |
118 |
112 type prover = |
119 type prover = |
113 params -> minimize_command -> Time.time -> problem -> prover_result |
120 params -> minimize_command -> Time.time -> problem -> prover_result |
114 |
121 |
115 |
|
116 (** preferences **) |
|
117 |
|
118 val message_store_limit = 20; |
|
119 val message_display_limit = 5; |
|
120 |
|
121 |
|
122 (** thread management **) |
|
123 |
|
124 (* data structures over threads *) |
|
125 |
|
126 structure Thread_Heap = Heap |
|
127 ( |
|
128 type elem = Time.time * Thread.thread; |
|
129 fun ord ((a, _), (b, _)) = Time.compare (a, b); |
|
130 ); |
|
131 |
|
132 fun lookup_thread xs = AList.lookup Thread.equal xs; |
|
133 fun delete_thread xs = AList.delete Thread.equal xs; |
|
134 fun update_thread xs = AList.update Thread.equal xs; |
|
135 |
|
136 |
|
137 (* state of thread manager *) |
|
138 |
|
139 type state = |
|
140 {manager: Thread.thread option, |
|
141 timeout_heap: Thread_Heap.T, |
|
142 active: (Thread.thread * (Time.time * Time.time * string)) list, |
|
143 canceling: (Thread.thread * (Time.time * string)) list, |
|
144 messages: string list, |
|
145 store: string list}; |
|
146 |
|
147 fun make_state manager timeout_heap active canceling messages store : state = |
|
148 {manager = manager, timeout_heap = timeout_heap, active = active, |
|
149 canceling = canceling, messages = messages, store = store} |
|
150 |
|
151 val global_state = Synchronized.var "atp_manager" |
|
152 (make_state NONE Thread_Heap.empty [] [] [] []); |
|
153 |
|
154 |
|
155 (* unregister ATP thread *) |
|
156 |
|
157 fun unregister verbose message thread = |
|
158 Synchronized.change global_state |
|
159 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
|
160 (case lookup_thread active thread of |
|
161 SOME (birth_time, _, desc) => |
|
162 let |
|
163 val active' = delete_thread thread active; |
|
164 val now = Time.now () |
|
165 val canceling' = (thread, (now, desc)) :: canceling |
|
166 val message' = |
|
167 desc ^ "\n" ^ message ^ |
|
168 (if verbose then |
|
169 "Total time: " ^ Int.toString (Time.toMilliseconds |
|
170 (Time.- (now, birth_time))) ^ " ms.\n" |
|
171 else |
|
172 "") |
|
173 val messages' = message' :: messages; |
|
174 val store' = message' :: |
|
175 (if length store <= message_store_limit then store |
|
176 else #1 (chop message_store_limit store)); |
|
177 in make_state manager timeout_heap active' canceling' messages' store' end |
|
178 | NONE => state)); |
|
179 |
|
180 |
|
181 (* main manager thread -- only one may exist *) |
|
182 |
|
183 val min_wait_time = Time.fromMilliseconds 300; |
|
184 val max_wait_time = Time.fromSeconds 10; |
|
185 |
|
186 fun replace_all bef aft = |
|
187 let |
|
188 fun aux seen "" = String.implode (rev seen) |
|
189 | aux seen s = |
|
190 if String.isPrefix bef s then |
|
191 aux seen "" ^ aft ^ aux [] (unprefix bef s) |
|
192 else |
|
193 aux (String.sub (s, 0) :: seen) (String.extract (s, 1, NONE)) |
|
194 in aux [] end |
|
195 |
|
196 (* This is a workaround for Proof General's off-by-a-few sendback display bug, |
|
197 whereby "pr" in "proof" is not highlighted. *) |
|
198 val break_into_chunks = |
|
199 map (replace_all "\n\n" "\000") #> maps (space_explode "\000") |
|
200 |
|
201 fun print_new_messages () = |
|
202 case Synchronized.change_result global_state |
|
203 (fn {manager, timeout_heap, active, canceling, messages, store} => |
|
204 (messages, make_state manager timeout_heap active canceling [] |
|
205 store)) of |
|
206 [] => () |
|
207 | msgs => |
|
208 msgs |> break_into_chunks |
|
209 |> (fn msg :: msgs => "Sledgehammer: " ^ msg :: msgs) |
|
210 |> List.app priority |
|
211 |
|
212 fun check_thread_manager verbose = Synchronized.change global_state |
|
213 (fn state as {manager, timeout_heap, active, canceling, messages, store} => |
|
214 if (case manager of SOME thread => Thread.isActive thread | NONE => false) then state |
|
215 else let val manager = SOME (Toplevel.thread false (fn () => |
|
216 let |
|
217 fun time_limit timeout_heap = |
|
218 (case try Thread_Heap.min timeout_heap of |
|
219 NONE => Time.+ (Time.now (), max_wait_time) |
|
220 | SOME (time, _) => time); |
|
221 |
|
222 (*action: find threads whose timeout is reached, and interrupt canceling threads*) |
|
223 fun action {manager, timeout_heap, active, canceling, messages, store} = |
|
224 let val (timeout_threads, timeout_heap') = |
|
225 Thread_Heap.upto (Time.now (), Thread.self ()) timeout_heap; |
|
226 in |
|
227 if null timeout_threads andalso null canceling |
|
228 then NONE |
|
229 else |
|
230 let |
|
231 val _ = List.app (Simple_Thread.interrupt o #1) canceling |
|
232 val canceling' = filter (Thread.isActive o #1) canceling |
|
233 val state' = make_state manager timeout_heap' active canceling' messages store; |
|
234 in SOME (map #2 timeout_threads, state') end |
|
235 end; |
|
236 in |
|
237 while Synchronized.change_result global_state |
|
238 (fn state as {timeout_heap, active, canceling, messages, store, ...} => |
|
239 if null active andalso null canceling andalso null messages |
|
240 then (false, make_state NONE timeout_heap active canceling messages store) |
|
241 else (true, state)) |
|
242 do |
|
243 (Synchronized.timed_access global_state (SOME o time_limit o #timeout_heap) action |
|
244 |> these |
|
245 |> List.app (unregister verbose "Timed out.\n"); |
|
246 print_new_messages (); |
|
247 (*give threads some time to respond to interrupt*) |
|
248 OS.Process.sleep min_wait_time) |
|
249 end)) |
|
250 in make_state manager timeout_heap active canceling messages store end) |
|
251 |
|
252 |
|
253 (* register ATP thread *) |
|
254 |
|
255 fun register verbose birth_time death_time (thread, desc) = |
|
256 (Synchronized.change global_state |
|
257 (fn {manager, timeout_heap, active, canceling, messages, store} => |
|
258 let |
|
259 val timeout_heap' = Thread_Heap.insert (death_time, thread) timeout_heap; |
|
260 val active' = update_thread (thread, (birth_time, death_time, desc)) active; |
|
261 val state' = make_state manager timeout_heap' active' canceling messages store; |
|
262 in state' end); |
|
263 check_thread_manager verbose); |
|
264 |
|
265 |
|
266 |
|
267 (** user commands **) |
|
268 |
|
269 (* kill ATPs *) |
|
270 |
|
271 fun kill_atps () = Synchronized.change global_state |
|
272 (fn {manager, timeout_heap, active, canceling, messages, store} => |
|
273 let |
|
274 val killing = map (fn (th, (_, _, desc)) => (th, (Time.now (), desc))) active; |
|
275 val state' = make_state manager timeout_heap [] (killing @ canceling) messages store; |
|
276 val _ = if null active then () |
|
277 else priority "Killed active Sledgehammer threads." |
|
278 in state' end); |
|
279 |
|
280 |
|
281 (* running_atps *) |
|
282 |
|
283 fun seconds time = string_of_int (Time.toSeconds time) ^ "s"; |
|
284 |
|
285 fun running_atps () = |
|
286 let |
|
287 val {active, canceling, ...} = Synchronized.value global_state; |
|
288 |
|
289 val now = Time.now (); |
|
290 fun running_info (_, (birth_time, death_time, desc)) = |
|
291 "Running: " ^ seconds (Time.- (now, birth_time)) ^ " -- " ^ |
|
292 seconds (Time.- (death_time, now)) ^ " to live:\n" ^ desc; |
|
293 fun canceling_info (_, (deadth_time, desc)) = |
|
294 "Trying to interrupt thread since " ^ seconds (Time.- (now, deadth_time)) ^ ":\n" ^ desc; |
|
295 |
|
296 val running = |
|
297 if null active then "No ATPs running." |
|
298 else space_implode "\n\n" ("Running ATPs:" :: map running_info active); |
|
299 val interrupting = |
|
300 if null canceling then |
|
301 "" |
|
302 else |
|
303 space_implode "\n\n" ("Trying to interrupt the following ATPs:" :: |
|
304 map canceling_info canceling) |
|
305 in priority (running ^ "\n" ^ interrupting) end; |
|
306 |
|
307 fun messages opt_limit = |
|
308 let |
|
309 val limit = the_default message_display_limit opt_limit; |
|
310 val {store, ...} = Synchronized.value global_state; |
|
311 val header = |
|
312 "Recent ATP messages" ^ |
|
313 (if length store <= limit then ":" else " (" ^ string_of_int limit ^ " displayed):"); |
|
314 in List.app priority (header :: break_into_chunks (#1 (chop limit store))) end |
|
315 |
|
316 |
|
317 (** The Sledgehammer **) |
|
318 |
|
319 (* named provers *) |
122 (* named provers *) |
320 |
123 |
321 structure Data = Theory_Data |
124 structure Data = Theory_Data |
322 ( |
125 ( |
323 type T = (prover * stamp) Symtab.table; |
126 type T = (prover * stamp) Symtab.table; |