class BaseDispatcher:

  "Base Abstract Class for Dispatchers"


  def __init__(self,):
    """
      Initializes Dispatchers and starts tasks queues
    """
    pass
  
  def shutdown(self,):
    """
      shutdowns subprocesses and releases memory being used by dispatcher.
    """
    raise NotImplementedError

  def run(self, func, *args, **kwargs):
    """
      Places a task into the servers queued tasks for client completion.

      # Returns 
      The associated task id to recover the results.
    """
    raise NotImplementedError
  
  def join(self,):
    """
      Gets results from all queued tasks and subsequently shuts down
      the dispatcher.
    """
    results = self.get_results(task_ids=None, values_only=True)
    self.shutdown()
    return results
  
  def get_results(self, task_ids=None, values_only=True):
    """
      Gets the results to tasks associated with the passed in task_ids. 
      Hangs current thread until all the tasks are complete.

      task_ids: task_ids as generated by self.run(). These are used by the 
        server to identify which task to return the results for.
      values_only: if False returns dictionary that includes the task ids with its 
        results. Otherwise, returns the values computed in order of the 
        requested task ids.
    """
    raise NotImplementedError
