yusri
yusri

Reputation: 21

Interrupt conditional event in simpy

simpy newbie here. I just started to make Speaker-Moderator simulation with simpy. Here is my code

import simpy

def speaker(env):
    try:
        print("Speaker start to talk at: {}".format(env.now))
        speak_time = 40
        print ("Speaker want to speak for {}".format(speak_time))
        yield env.timeout(speak_time)
        print ("Speaker finish the talk at: {}".format(env.now))
   except simpy.Interrupt as interrupt:
        print (interrupt.cause)

def moderator(env):
    for i in range(3):
        print("Moderator let the speaker number {} to begin the speak".format(i))
        speaker_proc = env.process(speaker(env))

        print("Time now: {}".format(env.now))
        time_limit = env.timeout(30)
        results = yield speaker_proc | time_limit
        print("Moderator check whether speaker passed the time limit or no")
        print("Time limit passed: {}".format (speaker_proc not in results))


        if speaker_proc not in results:
            print("Time now: {}".format(env.now))
            speaker_proc.interrupt()
            print ("Moderator stop the talk at: {}".format(env.now))
        print()
        print()

env = simpy.Environment()
env.process(moderator(env))
env.run()    

When I run it with speak_time > 30 or speak_time < 30, It has no problem but if I change speak_time in function speaker become 30 it will get error like this:

RuntimeError: <Process(speaker) object at 0x9e17930> has terminated and cannot be interrupted.

What happened?

Upvotes: 2

Views: 1553

Answers (1)

Stefan Scherfke
Stefan Scherfke

Reputation: 3232

You hit a strange corner case here. While the behavior you observed is totally intended, it is not very easy to understand for SimBy newbies.

I added two print() to your moderator() process to show what’s going on:

import simpy


def speaker(env):
    try:
        print("Speaker start to talk at: {}".format(env.now))
        speak_time = 30
        print("Speaker want to speak for {}".format(speak_time))
        yield env.timeout(speak_time)
        print("Speaker finish the talk at: {}".format(env.now))
    except simpy.Interrupt as interrupt:
        print(interrupt.cause)


def moderator(env):
    for i in range(3):
        print("Moderator let the speaker number {} to begin the speak".format(i))
        speaker_proc = env.process(speaker(env))

        print("Time now: {}".format(env.now))
        time_limit = env.timeout(30)
        print('Timeout created')
        results = yield speaker_proc | time_limit
        print("Moderator check whether speaker passed the time limit or no")
        print("Time limit passed: {}".format(speaker_proc not in results))

        if speaker_proc not in results:
            print("Time now: {}".format(env.now))
            print(speaker_proc.is_alive)
            speaker_proc.interrupt()
            print("Moderator stop the talk at: {}".format(env.now))
        print()
        print()

env = simpy.Environment()
env.process(moderator(env))
env.run()

The output:

Moderator let the speaker number 0 to begin the speak
Time now: 0
Timeout created
Speaker start to talk at: 0
Speaker want to speak for 30
Speaker finish the talk at: 30
Moderator check whether speaker passed the time limit or no
Time limit passed: True
Time now: 30
False
Traceback (most recent call last):

So what happend?

  1. The moderator is active until its first yield. During that time, it creates the speaker process and the timeout.

  2. The timeout is immediately triggered and added to the event queue.

  3. The moderator yields the conditon event.

  4. The speaker runs and creates its timeout. It is also immediately triggered and scheduled (at the same time as the moderator's timeout, but it is inserted after it in the event queue).

  5. The Condition event is triggered when the moderator's timeout is processed.

  6. When the moderator is resumed, the condition event only holds the result of moderator's timeout, but the speaker processes terminated, too. You can check this via the speaker_proc.is_alive property.

This guide contains some more in-depth information about this topic.

Upvotes: 1

Related Questions