with Maze;
with Traversal;
with Pool_Manager;
with Search_Leads;
with Global_Options;

pragma Elaborate_All (Pool_Manager);

package Search_Team is

   procedure Launch_Searcher
     (Starting_Point : in     Maze.Position;
      Track          : in     Traversal.Trail;
      Launched       :    out Boolean);
   --  Attempts to start a new searcher thread at the specified location and
   --  with the given trail. Launched will be True on return if a searcher was
   --  successfully launched, otherwise it will be False.

private

   type Searcher;

   type Volunteer is access Searcher;

   task type Searcher is
      entry Start
        (My_ID : in Volunteer;
         --  a pointer to this task, so it can put itself back into
         --  the pool
         Start : in Maze.Position;
         --  the position to start from when searching within the maze
         Track : in Traversal.Trail);
      --  the current, partial solution
   end Searcher;
   --  The task type representing the actual searcher threads. The searcher
   --  tasks wait for their next assignment (when taken from the pool), search
   --  as long as possible, and then put themselves back into the pool. While
   --  waiting to be taken from the pool they are also able to terminate.

   package Pool is new Pool_Manager
     (Pool_Size => Global_Options.Max_Searchers,
      Element   => Searcher,
      Reference => Volunteer);
   --  Searchers are maintained within a pool for the sake of avoiding the
   --  expense of repeatedly creating new threads. The number of threads in the
   --  pool is set by the global options, which come from the command line
   --  switches (with a default if not explicitly set). This number of threads
   --  is important, in that we should not have too few relative to the number
   --  of processors available. Although the unused tasks will be idle in the
   --  pool, there can be a not-insignificant overhead from having too many
   --  tasks when the number is quite large. Having the number set by parameter
   --  facilitates experimentation without requiring a rebuild of the
   --  application. The pool is loaded during package (body) elaboration.

   procedure Delegate
      (Next    : in     Maze.Positions;
       History : in     Traversal.Trail;
       Store   : in out Search_Leads.Repository);
   --  Next is an array of candidate positions that can be searched, relative to
   --  the current position, thus representing a fork in the path. For each
   --  value in Next except the last, a separate searcher is given that position
   --  and trail so that it is searched in parallel. The last candidate is taken
   --  by the original thread calling Delegate. If no searcher was available
   --  from the pool, the position and trail are saved in the thread-local
   --  repository Store so that the calling searcher thread can go back and
   --  pursue them later.

end Search_Team;

