src/HOL/Tools/atp_manager.ML
changeset 29620 dc1257eaa4f2
parent 29598 ba7e19085fc5
child 29784 6fa257b4d10f
equal deleted inserted replaced
29617:b36bcbc1be3a 29620:dc1257eaa4f2
    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 () =
   253   in writeln (running ^ "\n" ^ interrupting) end;
   258   in writeln (running ^ "\n" ^ interrupting) end;
   254 
   259 
   255 fun messages opt_limit =
   260 fun messages opt_limit =
   256   let
   261   let
   257     val limit = the_default message_display_limit opt_limit;
   262     val limit = the_default message_display_limit opt_limit;
   258     val State {messages = msgs, ...} = Synchronized.value state
   263     val State {store = msgs, ...} = Synchronized.value state
   259     val header = "Recent ATP messages" ^
   264     val header = "Recent ATP messages" ^
   260       (if length msgs <= limit then ":" else " (" ^ string_of_int limit ^ " displayed):");
   265       (if length msgs <= limit then ":" else " (" ^ string_of_int limit ^ " displayed):");
   261   in writeln (space_implode "\n\n" (header :: #1 (chop limit msgs))) end;
   266   in writeln (space_implode "\n\n" (header :: #1 (chop limit msgs))) end;
   262 
   267 
   263 
   268 
   305             val result = prover (get_timeout ()) i proof_state
   310             val result = prover (get_timeout ()) i proof_state
   306               handle ResHolClause.TOO_TRIVIAL
   311               handle ResHolClause.TOO_TRIVIAL
   307                 => (true, "Empty clause: Try this command: " ^ Markup.markup Markup.sendback "apply metis")
   312                 => (true, "Empty clause: Try this command: " ^ Markup.markup Markup.sendback "apply metis")
   308               | ERROR msg
   313               | ERROR msg
   309                 => (false, "Error: " ^ msg)
   314                 => (false, "Error: " ^ msg)
   310             val _ = priority (unregister result (Thread.self ()))
   315             val _ = unregister result (Thread.self ())
   311           in () end handle Interrupt => ())
   316           in () end handle Interrupt => ())
   312       in () end);
   317       in () end);
   313 
   318 
   314 
   319 
   315 (* sledghammer for first subgoal *)
   320 (* sledghammer for first subgoal *)