Set execution order of simultaneous events

396 views
Skip to first unread message

empw...@googlemail.com

unread,
Apr 20, 2017, 3:00:28 AM4/20/17
to python-simpy
Hi,

I'm using SimPy for a bigger project and I've run into some trouble concerning simultaneous events (eg. events occuring at the same instant of simulation time).

To be precise, I have 3 processes A, B and C. B waits for A to finish, to finish itself, C interrupts B if it finds it unfinished. For clarification see the following minimal working example:

import simpy

def A(env):
    print(env.now, 'Foo, waiting for 5 time steps.')
    yield simpy.Timeout(env, 5)
    print(env.now, 'Foo, waited for 5 time steps, terminating.')

def B(env, wait_for):
    print(env.now, 'Bar, waiting for processes.')
    try:
        yield simpy.AllOf(env, wait_for)
        print(env.now, 'Bar, successfully waited for processes.')
    except simpy.Interrupt:
        print(env.now, 'Bar, interrupted, interrupting processes.')
        for process in wait_for:
            process.interrupt()
        print(env.now, 'Bar, interrupted, successfully interrupted processes.')

def C(env, process):
    print(env.now, 'Interrupt_If, waiting for 5 time steps')
    yield simpy.Timeout(env, 5)
    if not process.triggered:
        print(env.now, 'Interrupt_If, process not finished, interrupting')
        process.interrupt()
        print(env.now, 'Interrupt_If, process not finished, successfully interrupted process')

env = simpy.Environment()

process_a = env.process(A(env))
process_b = env.process(B(env, [process_a]))
process_c = env.process(C(env, process_b))

env.run(until=20)

The problem happens, when the processes are executed in the order A -> C -> B, since now B tries to interrupt A, which is already terminted.

As far as I see, there are some possible solutions, however (please keep in mind, that the code above is a minimal working example and does not reflect the architecture of my project), I don't find them satisfactory.

a) Only interrupt A in B, if A is still running: This is the workaround I currently have implemented, however, this has some short comings since I want to do some pre and post interrupt processing in B. This I can only do, if I'm certain that this interrupt is "legitimate".
b) Don't model B as an process: This really breaks with my design :/

So much for the problem, now for my questions:

Is there in SimPy the possibility to specify a certain order in which events have to be processed? In this case I would like to have all "termination" events to be processed before the interrupt event.
If there is no such way, do you have any experience and thus suggestions in handling this type of problems?

James Arruda

unread,
Apr 20, 2017, 3:28:37 PM4/20/17
to python-simpy
With interrupts you have to do the work of making sure your processes are in an interruptible state.

I don't know how to solve the problem with interrupts besides doing all the checking (or creating flags that say `can_be_interrupted` and the like). If you get out of your process as soon as it's past the interruptible parts, that makes the `triggered` check reliable. Just have your last line in that process spin up a new process, such as one that does your post-processing.

To avoid the interrupt problem you can create an event that A yields on along with its timeout. B gets to tell that event to succeed, and C will be able to do the same for B. The nice part is, once your timeout (or whatever) is done, anyone setting that event won't actually interrupt the other process if that process is no longer listening in on that event. Switching to classes where the processes are a method will make this easier. If you do that, you can compare the current time to the timeout finishing time and decide if you're actually interrupted or if you should have completed. 


Reply all
Reply to author
Forward
0 new messages