2016-02-04 7 views
3

Я хочу создать таймер с обратным вызовом, который можно прервать или сбросить с помощью SimPy. Если прервано, я не хочу, чтобы обратный вызов выполнялся, и если он сбрасывается, я хочу, чтобы таймер перезапускался с той же задержкой от env.now. Сначала это казалось простой задачей, просто используя env.timeout. Тем не менее, примечания к документации:Как прервать или отменить событие тайм-аута SimPy?

Чтобы на самом деле позволить времени проходить в симуляции, есть событие таймаута. Тайм-аут имеет два параметра: задержка и необязательное значение: Timeout (delay, value = None). Он запускает себя во время его создания и расписал себя в настоящее время + задержка. Таким образом, методы success() и fail() не могут быть вызваны снова, и вам нужно передать значение события, когда вы создаете таймаут.

Поскольку моделирование начинается срабатывает, я не могу добавить обратные вызовы и потому, что вы не можете назвать fail, я не могу прервать тайм-аут.

Я рассмотрел только процесс, который ждет один тайм-код и проверяет флаг, если он был прерван или достиг env.now, которого он ожидал, но это кажется ужасно неэффективным, и если у меня много таймеров (что я будет), я беспокоюсь, что количество генераторов будет подавлять симуляцию. (Функция тайм-аута, похоже, работает, планируя себя в будущем симуляции, поэтому у вас может быть тонна тех, кто работает).

Таким образом, спецификация - создание события, которое вызывает обратный вызов через определенное время, но может быть сброшено или прервано до этого времени. Есть предположения?

ответ

1

Ну, если я правильно понял ваш вопрос, вы можете создать класс Timer с методом ожидания, который проверяет наличие simpy.Interrupt. Вы можете получить stop(), так что, когда он вызывается, вы также вызываете interrupt(). Таким образом, обратный вызов не будет выполнен, если ранее был вызван interrupt(). Метод сброса просто вызовет stop() (прерывание) и start(), снова установив действие обратно на running() и снова вызовет wait(), что позволит снова выполнить обратный вызов после каждого таймаута, пока не будет вызвано прерывание.

Вот пример реализации такого Timer класса:

import simpy 

class Timer(object): 

    def __init__(self, env, delay, callback): 
     self.env  = env 
     self.delay = delay 
     self.action = None 
     self.callback = callback 
     self.running = False 
     self.canceled = False 

    def wait(self): 
     """ 
     Calls a callback after time has elapsed. 
     """ 
     try: 
      yield self.env.timeout(self.delay) 
      self.callback() 
      self.running = False 
     except simpy.Interrupt as i: 
      print "Interrupted!" 
      self.canceled = True 
      self.running = False 

    def start(self): 
     """ 
     Starts the timer 
     """ 
     if not self.running: 
      self.running = True 
      self.action = self.env.process(self.wait()) 

    def stop(self): 
     """ 
     Stops the timer 
     """ 
     if self.running: 
      self.action.interrupt() 
      self.action = None 

    def reset(self): 
     """ 
     Interrupts the current timer and restarts. 
     """ 
     self.stop() 
     self.start() 
+0

Великий ответ! Я протестировал и «начал»/'stop', пока вы« уступаете »' timer.action'. Однако это не похоже на то, что работает 'reset' - среда почему-то не получает сообщение. – bbengfort