code: def run(self, duration: float = inf) -> None:
          
          if _logger is not None:
              self._log(INFO, "run", __now=self.now(), duration=duration)
          counter_stop_event = None
          if duration != inf:
              counter_stop_event = self._counter
              self._schedule(duration, self.stop)
  
          self._is_running = True
          while self.is_running and len(self._events) > 0:
              event = heappop(self._events)
              self._ts_now = event.timestamp or self._ts_now
              event.execute(self)
  
          if len(self._events) == 0:
              if _logger is not None:
                  self._log(DEBUG, "out-of-events", __now=self.now())
          self.stop()
  
          if counter_stop_event is not None:
              # Change the planned stop to a no-op. We would rather eliminate it, but this would force a re-sort of the
              # event queue.
              for (i, event) in enumerate(self._events):
                  if event.identifier == counter_stop_event:
                      if _logger is not None:
                          self._log(DEBUG, "cancel-stop", counter=counter_stop_event)
                      event.cancel()
                      break
docs: Runs the simulation until a stopping condition is met (no more events, or an event invokes method stop()), or
          until the simulated clock hits the given duration.