87 datatype T = State of |
87 datatype T = State of |
88 {timeout_heap: ThreadHeap.T, |
88 {timeout_heap: ThreadHeap.T, |
89 oldest_heap: ThreadHeap.T, |
89 oldest_heap: ThreadHeap.T, |
90 active: (Thread.thread * (Time.time * Time.time * string)) list, |
90 active: (Thread.thread * (Time.time * Time.time * string)) list, |
91 cancelling: (Thread.thread * (Time.time * Time.time * string)) list, |
91 cancelling: (Thread.thread * (Time.time * Time.time * string)) list, |
92 messages: string list}; |
92 messages: string list, |
93 |
93 store: string list}; |
94 fun make_state timeout_heap oldest_heap active cancelling messages = |
94 |
|
95 fun make_state timeout_heap oldest_heap active cancelling messages store = |
95 State {timeout_heap = timeout_heap, oldest_heap = oldest_heap, |
96 State {timeout_heap = timeout_heap, oldest_heap = oldest_heap, |
96 active = active, cancelling = cancelling, messages = messages}; |
97 active = active, cancelling = cancelling, messages = messages, store = store}; |
97 |
98 |
98 val state = Synchronized.var "atp_manager" (make_state ThreadHeap.empty ThreadHeap.empty [] [] []); |
99 val state = Synchronized.var "atp_manager" (make_state ThreadHeap.empty ThreadHeap.empty [] [] [] []); |
99 |
100 |
100 |
101 |
101 (* the managing thread *) |
102 (* the managing thread *) |
102 |
103 |
103 (*watches over running threads and interrupts them if required*) |
104 (*watches over running threads and interrupts them if required*) |
104 val managing_thread = ref (NONE: Thread.thread option); |
105 val managing_thread = ref (NONE: Thread.thread option); |
105 |
106 |
106 |
107 |
107 (* unregister thread *) |
108 (* unregister thread *) |
108 |
109 |
109 fun unregister (success, message) thread = Synchronized.change_result state |
110 fun unregister (success, message) thread = Synchronized.change state |
110 (fn state as State {timeout_heap, oldest_heap, active, cancelling, messages} => |
111 (fn state as State {timeout_heap, oldest_heap, active, cancelling, messages, store} => |
111 (case lookup_thread active thread of |
112 (case lookup_thread active thread of |
112 SOME (birthtime, _, description) => |
113 SOME (birthtime, _, description) => |
113 let |
114 let |
114 val (group, active') = |
115 val (group, active') = |
115 if success then List.partition (fn (_, (tb, _, _)) => tb = birthtime) active |
116 if success then List.partition (fn (_, (tb, _, _)) => tb = birthtime) active |
116 else List.partition (fn (th, _) => Thread.equal (th, thread)) active |
117 else List.partition (fn (th, _) => Thread.equal (th, thread)) active |
117 (* do not interrupt successful thread, as it needs to print out its message |
|
118 (and terminates afterwards - see start_prover )*) |
|
119 val group' = if success then delete_thread thread group else group |
|
120 |
118 |
121 val now = Time.now () |
119 val now = Time.now () |
122 val cancelling' = |
120 val cancelling' = |
123 fold (fn (th, (tb, _, desc)) => update_thread (th, (tb, now, desc))) group' cancelling |
121 fold (fn (th, (tb, _, desc)) => update_thread (th, (tb, now, desc))) group cancelling |
124 |
122 |
125 val msg = description ^ "\n" ^ message |
123 val message' = description ^ "\n" ^ message ^ |
126 val message' = "Sledgehammer: " ^ msg ^ |
|
127 (if length group <= 1 then "" |
124 (if length group <= 1 then "" |
128 else "\nInterrupted " ^ string_of_int (length group - 1) ^ " other group members") |
125 else "\nInterrupted " ^ string_of_int (length group - 1) ^ " other group members") |
129 val messages' = msg :: |
126 val store' = message' :: |
130 (if length messages <= message_store_limit then messages |
127 (if length store <= message_store_limit then store |
131 else #1 (chop message_store_limit messages)) |
128 else #1 (chop message_store_limit store)) |
132 in (message', make_state timeout_heap oldest_heap active' cancelling' messages') end |
129 in make_state timeout_heap oldest_heap active' cancelling' (message' :: messages) store' end |
133 | NONE => ("", state))); |
130 | NONE =>state)); |
134 |
131 |
135 |
132 |
136 (* kill excessive atp threads *) |
133 (* kill excessive atp threads *) |
137 |
134 |
138 fun excessive_atps active = |
135 fun excessive_atps active = |
142 local |
139 local |
143 |
140 |
144 fun kill_oldest () = |
141 fun kill_oldest () = |
145 let exception Unchanged in |
142 let exception Unchanged in |
146 Synchronized.change_result state |
143 Synchronized.change_result state |
147 (fn State {timeout_heap, oldest_heap, active, cancelling, messages} => |
144 (fn State {timeout_heap, oldest_heap, active, cancelling, messages, store} => |
148 if ThreadHeap.is_empty oldest_heap orelse not (excessive_atps active) |
145 if ThreadHeap.is_empty oldest_heap orelse not (excessive_atps active) |
149 then raise Unchanged |
146 then raise Unchanged |
150 else |
147 else |
151 let val ((_, oldest_thread), oldest_heap') = ThreadHeap.min_elem oldest_heap |
148 let val ((_, oldest_thread), oldest_heap') = ThreadHeap.min_elem oldest_heap |
152 in (oldest_thread, make_state timeout_heap oldest_heap' active cancelling messages) end) |
149 in (oldest_thread, make_state timeout_heap oldest_heap' active cancelling messages store) end) |
153 |> (priority o unregister (false, "Interrupted (maximum number of ATPs exceeded)")) |
150 |> unregister (false, "Interrupted (maximum number of ATPs exceeded)") |
154 handle Unchanged => () |
151 handle Unchanged => () |
155 end; |
152 end; |
156 |
153 |
157 in |
154 in |
158 |
155 |
159 fun kill_excessive () = |
156 fun kill_excessive () = |
160 let val State {active, ...} = Synchronized.value state |
157 let val State {active, ...} = Synchronized.value state |
161 in if excessive_atps active then (kill_oldest (); kill_excessive ()) else () end; |
158 in if excessive_atps active then (kill_oldest (); kill_excessive ()) else () end; |
162 |
159 |
163 end; |
160 end; |
|
161 |
|
162 fun print_new_messages () = |
|
163 let val to_print = Synchronized.change_result state |
|
164 (fn State {timeout_heap, oldest_heap, active, cancelling, messages, store} => |
|
165 (messages, make_state timeout_heap oldest_heap active cancelling [] store)) |
|
166 in if null to_print then () |
|
167 else priority ("Sledgehammer: " ^ (space_implode "\n\n" to_print)) end; |
164 |
168 |
165 |
169 |
166 (* start a watching thread which runs forever -- only one may exist *) |
170 (* start a watching thread which runs forever -- only one may exist *) |
167 |
171 |
168 fun check_thread_manager () = CRITICAL (fn () => |
172 fun check_thread_manager () = CRITICAL (fn () => |
176 fun time_limit (State {timeout_heap, ...}) = |
180 fun time_limit (State {timeout_heap, ...}) = |
177 (case try ThreadHeap.min timeout_heap of |
181 (case try ThreadHeap.min timeout_heap of |
178 NONE => SOME (Time.+ (Time.now (), max_wait_time)) |
182 NONE => SOME (Time.+ (Time.now (), max_wait_time)) |
179 | SOME (time, _) => SOME time) |
183 | SOME (time, _) => SOME time) |
180 |
184 |
181 (* action: cancel find threads whose timeout is reached, and interrupt cancelling threads *) |
185 (* action: find threads whose timeout is reached, and interrupt cancelling threads *) |
182 fun action (State {timeout_heap, oldest_heap, active, cancelling, messages}) = |
186 fun action (State {timeout_heap, oldest_heap, active, cancelling, messages, store}) = |
183 let val (timeout_threads, timeout_heap') = |
187 let val (timeout_threads, timeout_heap') = |
184 ThreadHeap.upto (Time.now (), Thread.self ()) timeout_heap |
188 ThreadHeap.upto (Time.now (), Thread.self ()) timeout_heap |
185 in |
189 in |
186 if null timeout_threads andalso null cancelling andalso not (excessive_atps active) |
190 if null timeout_threads andalso null cancelling andalso not (excessive_atps active) |
187 then NONE |
191 then NONE |
188 else |
192 else |
189 let |
193 let |
190 val _ = List.app (SimpleThread.interrupt o #1) cancelling |
194 val _ = List.app (SimpleThread.interrupt o #1) cancelling |
191 val cancelling' = filter (Thread.isActive o #1) cancelling |
195 val cancelling' = filter (Thread.isActive o #1) cancelling |
192 val state' = make_state timeout_heap' oldest_heap active cancelling' messages |
196 val state' = make_state timeout_heap' oldest_heap active cancelling' messages store |
193 in SOME (map #2 timeout_threads, state') end |
197 in SOME (map #2 timeout_threads, state') end |
194 end |
198 end |
195 in |
199 in |
196 while true do |
200 while true do |
197 (Synchronized.timed_access state time_limit action |
201 (Synchronized.timed_access state time_limit action |
198 |> these |
202 |> these |
199 |> List.app (priority o unregister (false, "Interrupted (reached timeout)")); |
203 |> List.app (unregister (false, "Interrupted (reached timeout)")); |
200 kill_excessive (); |
204 kill_excessive (); |
|
205 print_new_messages (); |
201 (*give threads time to respond to interrupt*) |
206 (*give threads time to respond to interrupt*) |
202 OS.Process.sleep min_wait_time) |
207 OS.Process.sleep min_wait_time) |
203 end))); |
208 end))); |
204 |
209 |
205 |
210 |
206 (* thread is registered here by sledgehammer *) |
211 (* thread is registered here by sledgehammer *) |
207 |
212 |
208 fun register birthtime deadtime (thread, desc) = |
213 fun register birthtime deadtime (thread, desc) = |
209 (check_thread_manager (); |
214 (check_thread_manager (); |
210 Synchronized.change state |
215 Synchronized.change state |
211 (fn State {timeout_heap, oldest_heap, active, cancelling, messages} => |
216 (fn State {timeout_heap, oldest_heap, active, cancelling, messages, store} => |
212 let |
217 let |
213 val timeout_heap' = ThreadHeap.insert (deadtime, thread) timeout_heap |
218 val timeout_heap' = ThreadHeap.insert (deadtime, thread) timeout_heap |
214 val oldest_heap' = ThreadHeap.insert (birthtime, thread) oldest_heap |
219 val oldest_heap' = ThreadHeap.insert (birthtime, thread) oldest_heap |
215 val active' = update_thread (thread, (birthtime, deadtime, desc)) active |
220 val active' = update_thread (thread, (birthtime, deadtime, desc)) active |
216 in make_state timeout_heap' oldest_heap' active' cancelling messages end)); |
221 in make_state timeout_heap' oldest_heap' active' cancelling messages store end)); |
217 |
222 |
218 |
223 |
219 |
224 |
220 (** user commands **) |
225 (** user commands **) |
221 |
226 |
222 (* kill: move all threads to cancelling *) |
227 (* kill: move all threads to cancelling *) |
223 |
228 |
224 fun kill () = Synchronized.change state |
229 fun kill () = Synchronized.change state |
225 (fn State {timeout_heap, oldest_heap, active, cancelling, messages} => |
230 (fn State {timeout_heap, oldest_heap, active, cancelling, messages, store} => |
226 let val formerly_active = map (fn (th, (tb, _, desc)) => (th, (tb, Time.now (), desc))) active |
231 let val formerly_active = map (fn (th, (tb, _, desc)) => (th, (tb, Time.now (), desc))) active |
227 in make_state timeout_heap oldest_heap [] (formerly_active @ cancelling) messages end); |
232 in make_state timeout_heap oldest_heap [] (formerly_active @ cancelling) messages store end); |
228 |
233 |
229 |
234 |
230 (* ATP info *) |
235 (* ATP info *) |
231 |
236 |
232 fun info () = |
237 fun info () = |