how can I set priority on simpy process callbacks?

一曲冷凌霜 提交于 2019-12-11 11:48:52

问题


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.

  1. Introduce a small delay. (Scale delay according to priority between processes.)
  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!