class_docstr: Wrapper class to add timeout feature to synchronous iterators
  - timeout: timeout for next(). Default=ZERO_TIMEOUT i.e. no timeout or blocking calls to next. Updated using set_timeout() 
  - sentinel: the object returned by iterator when timeout happens
  - reset_on_next: if set to True, timeout is reset to the value of ZERO_TIMEOUT on each iteration
  
  TimeoutIterator uses a thread internally.
  The thread stops once the iterator exhausts or raises an exception during iteration.
  
  Any exceptions raised within the wrapped iterator are propagated as it is.
  Exception is raised when all elements generated by the actual iterator before exception have been consumed
  Timeout can be set dynamically before going for iteration
class_docstr_tok: ["Wrapper","class","to","add","timeout","feature","to","synchronous","iterators","-","timeout",":","timeout","for","next","(",")",".","Default=ZERO_TIMEOUT","i.e",".","no","timeout","or","blocking","calls","to","next",".","Updated","using","set_timeout","(",")","-","sentinel",":","the","object","returned","by","iterator","when","timeout","happens","-","reset_on_next",":","if","set","to","True",",","timeout","is","reset","to","the","value","of","ZERO_TIMEOUT","on","each","iteration","TimeoutIterator","uses","a","thread","internally",".","The","thread","stops","once","the","iterator","exhausts","or","raises","an","exception","during","iteration",".","Any","exceptions","raised","within","the","wrapped","iterator","are","propagated","as","it","is",".","Exception","is","raised","when","all","elements","generated","by","the","actual","iterator","before","exception","have","been","consumed","Timeout","can","be","set","dynamically","before","going","for","iteration"]
docstr: yield the result from iterator
  if timeout > 0:
      yield data if available.
      otherwise yield sentinel
docstr_tok: ["yield","the","result","from","iterator","if","timeout",">","0",":","yield","data","if","available",".","otherwise","yield","sentinel"]
code: def __next__(self):
      """
      yield the result from iterator
      if timeout > 0:
          yield data if available.
          otherwise yield sentinel
      """
      if self._done:
          raise StopIteration
  
      data = self._sentinel
      try:
          if self._timeout > self.ZERO_TIMEOUT:
              data = self._buffer.get(timeout=self._timeout)
          else:
              data = self._buffer.get()
      except queue.Empty:
          pass
      finally:
          # see if timeout needs to be reset
          if self._reset_on_next:
              self._timeout = self.ZERO_TIMEOUT
  
      # propagate any exceptions including StopIteration
      if isinstance(data, BaseException):
          self._done = True
          if isinstance(data, StopIteration):
              raise data
          ex = "".join(traceback.format_tb(data.__traceback__))
          print(
              "Generation Failed: %s %s %s"
              % (str(data), str(ex), self._whichi),
              flush=True,
          )
          if self._raise_on_exception:
              raise data
          else:
              return data
  
      return data
  
file_path: h2ogpt/iterators/timeout_iterator.py
imports: import queue
  import asyncio
  import threading
  import traceback
label_desc: Use image node_id 7 for calling the TimeoutIterator obj's underlying member method code with example usage: obj.__next__() and returns: data, data