class_docstr: _ParallelEnqueuer defines the semantics for either a threading-based or multiprocessing-based
  enqueuer (threading and multiprocessing are intentionally designed to be API compatible).  The
  implementation-specific details are defined in the child classes.
  
  Generally, the strategy is:
    - in start(): start a bunch of workers with access to a pair of queues.
  
    - in data(): fill the query queue with tuples of (index, order) tuples.  The index comes from
      the _Sampler, and the order just defines in what order we put things into the queue.
  
      Workers will pop (index, order) tuples fram the query queue and put tuples of (data, order)
      in the answers queue.
  
      The main thread will gather the (data, order) tuples, and reorder the data elements to
      match the order they were requested.  Whenever the next-requested data is available, it
      will pass yield that data through the generator.
  
    - in close(): shut down all the workers and clean up resources.
class_docstr_tok: ["_ParallelEnqueuer","defines","the","semantics","for","either","a","threading-based","or","multiprocessing-based","enqueuer","(","threading","and","multiprocessing","are","intentionally","designed","to","be","API","compatible",")",".","The","implementation-specific","details","are","defined","in","the","child","classes",".","Generally",",","the","strategy","is",":","-","in","start","(",")",":","start","a","bunch","of","workers","with","access","to","a","pair","of","queues",".","-","in","data","(",")",":","fill","the","query","queue","with","tuples","of","(","index",",","order",")","tuples",".","The","index","comes","from","the","_Sampler",",","and","the","order","just","defines","in","what","order","we","put","things","into","the","queue",".","Workers","will","pop","(","index",",","order",")","tuples","fram","the","query","queue","and","put","tuples","of","(","data",",","order",")","in","the","answers","queue",".","The","main","thread","will","gather","the","(","data",",","order",")","tuples",",","and","reorder","the","data","elements","to","match","the","order","they","were","requested",".","Whenever","the","next-requested","data","is","available",",","it","will","pass","yield","that","data","through","the","generator",".","-","in","close","(",")",":","shut","down","all","the","workers","and","clean","up","resources","."]
code: def fill_requests(self) -> None:
      if self.index_iter is None:
          # No data left this epoch.
          return
      while len(self.requested) < self.max_queue_size:
          try:
              i = next(self.index_iter)
          except StopIteration:
              self.index_iter = None
              return
          puttable = (i, self.order)
          self.queries.put(puttable)
          self.requested.append(self.order)
          self.order += 1
  
imports: import abc
  import collections
  import multiprocessing
  import multiprocessing.queues
  import queue
  import threading
  from typing import Any, Deque, Dict, Iterator, Optional, Type, Union
  import numpy
  import tensorflow
  from determined.common import check
label_desc: Use image node_id 5 for calling the _ParallelEnqueuer obj's underlying member method code with example usage: obj.fill_requests() without return types