如何中断或取消SimPy超时事件?

时间:2016-02-04 13:58:32

标签: python simulation simpy

我想创建一个带有回调的计时器,可以使用SimPy中断或重置。如果中断,我不希望执行回调,如果重置,我希望定时器从env.now以相同的延迟重新启动。通过简单地使用env.timeout,这似乎是一件容易的事情。但是,文档说明:

  

要实际让时间在模拟中传递,会有超时事件。超时有两个参数:延迟和可选值:超时(延迟,值=无)。它在创建过程中触发自身,并在现在+延迟时间表自行调度。因此,不能再次调用succeed()和fail()方法,并且在创建超时时必须将事件值传递给它。

由于模拟启动已触发,我无法添加回调,因为您无法调用fail,我无法中断超时。< / p>

我考虑过只执行一个等待一个时间步的进程并检查一个标志是否被中断或到达它正在等待的env.now,但这似乎非常低效,如果我有很多计时器(我会),我担心发电机的数量会压倒模拟。 (超时功能似乎可以通过在模拟的未来安排自己来工作,这就是为什么你可以运行大量的那些)。

因此规范是 - 创建一个在指定时间后触发回调的事件,但可以在该时间发生之前重置或中断。有什么想法吗?

1 个答案:

答案 0 :(得分: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()