问题
The default order in which processes are triggered in simpy seems to rely on the order they were created? I want to expressly rank processes so they are triggered in a precise order, regardless of when they were created. If you need an example, here's a simulation with 3 processes: eat food, refill plate, remove plate. the eat()
process triggers the plateEmpty
event, expecting it to be refilled. But if the removePlate()
process happens before refillPlate()
, then refill can't happen. I want refill to always happen first. And the only way I can enforce that is ordering lines 44 and 45. Is there another way?
[PS: I know about priority resources, but that's not what I want.]
import simpy
env = simpy.Environment()
plateEmpty = env.event()
plateGone = env.event()
scoop = 5
def eat(env):
global plateEmpty
global food
while True:
e = yield env.timeout(5) | plateGone
if plateGone in e:
print "Ack! my plate is gone." #bad
break
if food > 0:
food -= 1 # one bite
print env.now,"took a bite"
if food == 0:
plateEmpty.succeed("I want more food")
def refillPlate(env):
global food
global plateEmpty
while True:
e = yield plateEmpty | plateGone
if plateGone in e:
print env.now, "cannot refill."
break
food += scoop
print env.now,"refilled plate"
plateEmpty = env.event() # reset trigger
def removePlate(env):
while True:
e = yield plateEmpty | plateGone
if plateEmpty not in e: continue # trigger was reset
print env.now,"removed plate"
plateGone.succeed()
break
food = scoop
env.process(eat(env))
env.process(removePlate(env)) # line 44: want this triggered last
env.process(refillPlate(env)) # line 45: want this triggered first
env.run(until=100)
回答1:
I find two solutions for this.
- Introduce a small delay. (Scale delay according to priority between processes.)
- Check the queue for a specific condition and let it be processed first.
Solution 1:
def removePlate(env):
while True:
e = yield plateEmpty | plateGone
yield env.timeout(0.00001)
if plateEmpty not in e: continue # trigger was reset
print(env.now,"removed plate")
plateGone.succeed()
break
Solution 2:
import simpy
env = simpy.Environment()
plateEmpty = env.event()
plateGone = env.event()
scoop = 5
condition = None
def eat(env):
global plateEmpty
global food
while True:
e = yield env.timeout(5) | plateGone
if plateGone in e:
print("Ack! my plate is gone.") #bad
break
if food > 0:
food -= 1 # one bite
print(env.now,"took a bite")
if food == 0:
plateEmpty.succeed("I want more food")
def refillPlate(env):
global food
global plateEmpty
global condition
while True:
condition = plateEmpty | plateGone
e = yield condition
if plateGone in e:
print(env.now, "cannot refill.")
break
food += scoop
print(env.now,"refilled plate")
plateEmpty = env.event() # reset trigger
def removePlate(env):
global spec_proc
while True:
e = yield plateEmpty | plateGone
# Check if the other process is scheduled to run at the same time
if (env.now, condition) in [(time, condition) for time, _, _, condition in env._queue]:
yield env.timeout(0.00001)
if plateEmpty not in e: continue # trigger was reset
print(env.now,"removed plate")
plateGone.succeed()
break
food = scoop
env.process(eat(env))
spec_proc = env.process(removePlate(env)) # line 44: want this triggered last
env.process(refillPlate(env)) # line 45: want this triggered first
env.run(until=100)
来源:https://stackoverflow.com/questions/33085532/how-can-i-set-priority-on-simpy-process-callbacks