class_docstr: A manager for parallel execution of jobs.
  
  A job must be of type :class:`Job` which produces a :class:`Result`
  object upon successful completion. The scheduler maintains a job and
  result queues.
  
  Notes:
      This class should be used as a context manager.
docstr: Run the pool of workers on the dispatched jobs, fetched from the job
  queue and collect the results into the result queue.
  
  Notes:
      The runner will take as long as all jobs from the job queue finish
      before any results are written to the result queue.
docstr_tok: ["Run","the","pool","of","workers","on","the","dispatched","jobs",",","fetched","from","the","job","queue","and","collect","the","results","into","the","result","queue",".","Notes",":","The","runner","will","take","as","long","as","all","jobs","from","the","job","queue","finish","before","any","results","are","written","to","the","result","queue","."]
code: def _run_servant(self):
      """Run the pool of workers on the dispatched jobs, fetched from the job
      queue and collect the results into the result queue.
  
      Notes:
          The runner will take as long as all jobs from the job queue finish
          before any results are written to the result queue.
      """
      # TODO: Switch backend back to default "loky", after the leakage
      #  of semaphores is fixed
      with joblib.Parallel(
          n_jobs=self.n_parallel, backend="multiprocessing"
      ) as parallel:
          while not self._interrupt_event.is_set():
              current_jobs = utils.drain_queue(self._job_queue)
              if not current_jobs:
                  continue
              # the order of the results corresponds to the that of the jobs
              # and the IDs don't need to be shuffled.
              ids = [job.id for job in current_jobs]
              # TODO: in a future version of joblib, this could be a generator
              #  and then the inputs would be stored immediately in the results
              #  queue. Be ready to update whenever this PR gets merged:
              #  https://github.com/joblib/joblib/pull/588
              results = parallel(
                  joblib.delayed(job)() for job in current_jobs
              )
              assert len(ids) == len(results)
              for res in results:
                  self._result_queue.put_nowait(res)
  
file_path: hypertunity/hypertunity/scheduling/scheduler.py
imports: import multiprocessing
  import time
  from typing import List
  import joblib
  from hypertunity import utils
  from .jobs import Job, Result
label_desc: Use image node_id 5 for calling the Scheduler obj's underlying member method code with example usage: obj._run_servant() without return types