I am new to SimPy and need help to figure out how to do this:
There are multiple foo
processes running and a monitor
process. At every time step, is there a way to ensure that the monitor
process runs only after the other foo
processes have finished running for that time step?
I attempt to do this in my example below by listening for changes to any process's is_alive
property, then run the actual monitor
logic after no more changes are detected.
However, from the output shown here, you can see that the string
1 : Doing something after all other processes....
appeared before
1 : a has finished after 1 steps
so monitor
process did not manage to run its logic after all the other processes at environment step #1
Output
0 : Unfinished processes= [<Process(foo) object at 0x7f820b3df7f0>, <Process(foo) object at 0x7f820aae4790>, <Process(foo) object at 0x7f820aad2490>]
0 : Doing something after all other processes....
1 : Unfinished processes= [<Process(foo) object at 0x7f820b3df7f0>, <Process(foo) object at 0x7f820aae4790>, <Process(foo) object at 0x7f820aad2490>]
1 : Doing something after all other processes....
1 : a has finished after 1 steps
2 : Unfinished processes= [<Process(foo) object at 0x7f820aae4790>, <Process(foo) object at 0x7f820aad2490>]
2 : Doing something after all other processes....
3 : Unfinished processes= [<Process(foo) object at 0x7f820aae4790>, <Process(foo) object at 0x7f820aad2490>]
3 : Doing something after all other processes....
4 : Unfinished processes= [<Process(foo) object at 0x7f820aae4790>, <Process(foo) object at 0x7f820aad2490>]
4 : Doing something after all other processes....
5 : b has finished after 5 steps
5 : c has finished after 5 steps
5 : Doing something after all other processes....
My Simpy code
import simpy
def foo(env, id, delay):
yield env.timeout(delay)
print(f"{env.now} : {id} has finished after {delay} steps")
def monitor(env):
while True:
prev_unfinished_processes = []
while True:
unfinished_processes = [p for p in processes if p.is_alive]
if set(unfinished_processes) != set(prev_unfinished_processes):
print(env.now, ": Unfinished processes=", unfinished_processes)
else:
print(env.now, ": Doing something after all other processes....")
break
prev_unfinished_processes = unfinished_processes
yield env.timeout(1)
env = simpy.Environment()
env.process(monitor(env))
processes = [
env.process(foo(env, "a", 1)),
env.process(foo(env, "b", 5)),
env.process(foo(env, "c", 5)),
]
env.run(until=6)
Is there a better way to achieve this? Thanks