src/HOL/Tools/Sledgehammer/async_manager.ML
changeset 43846 c96f06bffd90
parent 41290 8275f52ac991
child 43870 3e060b1c844b
equal deleted inserted replaced
43845:20e9caff1f86 43846:c96f06bffd90
     6 Central manager for asynchronous diagnosis tool threads.
     6 Central manager for asynchronous diagnosis tool threads.
     7 *)
     7 *)
     8 
     8 
     9 signature ASYNC_MANAGER =
     9 signature ASYNC_MANAGER =
    10 sig
    10 sig
    11   val break_into_chunks : string list -> string list
    11   val implode_desc : string * string -> string
       
    12   val break_into_chunks : string -> string list
    12   val launch :
    13   val launch :
    13     string -> Time.time -> Time.time -> string -> (unit -> string) -> unit
    14     string -> Time.time -> Time.time -> string * string
       
    15     -> (unit -> bool * string) -> unit
    14   val kill_threads : string -> string -> unit
    16   val kill_threads : string -> string -> unit
    15   val running_threads : string -> string -> unit
    17   val running_threads : string -> string -> unit
    16   val thread_messages : string -> string -> int option -> unit
    18   val thread_messages : string -> string -> int option -> unit
    17 end;
    19 end;
    18 
    20 
    24 val message_store_limit = 20;
    26 val message_store_limit = 20;
    25 val message_display_limit = 5;
    27 val message_display_limit = 5;
    26 
    28 
    27 
    29 
    28 (** thread management **)
    30 (** thread management **)
       
    31 
       
    32 val implode_desc = op ^ o apfst quote
       
    33 
       
    34 fun implode_message (workers, work) =
       
    35   space_implode " " (ATP_Proof.serial_commas "and" (map quote workers)) ^ work
       
    36 
    29 
    37 
    30 (* data structures over threads *)
    38 (* data structures over threads *)
    31 
    39 
    32 structure Thread_Heap = Heap
    40 structure Thread_Heap = Heap
    33 (
    41 (
    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 () =>
   139             then (false, make_state NONE timeout_heap active canceling messages store)
   154             then (false, make_state NONE timeout_heap active canceling messages store)
   140             else (true, state))
   155             else (true, state))
   141         do
   156         do
   142           (Synchronized.timed_access global_state (SOME o time_limit o #timeout_heap) action
   157           (Synchronized.timed_access global_state (SOME o time_limit o #timeout_heap) action
   143             |> these
   158             |> these
   144             |> List.app (unregister "Timed out.\n");
   159             |> List.app (unregister (false, "Timed out.\n"));
   145             print_new_messages ();
   160             print_new_messages ();
   146             (*give threads some time to respond to interrupt*)
   161             (*give threads some time to respond to interrupt*)
   147             OS.Process.sleep min_wait_time)
   162             OS.Process.sleep min_wait_time)
   148       end))
   163       end))
   149     in make_state manager timeout_heap active canceling messages store end)
   164     in make_state manager timeout_heap active canceling messages store end)
   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;