如何设置简单的进程回调优先级?

时间:2015-10-12 16:05:31

标签: python simpy

在simpy中触发进程的默认顺序似乎依赖于它们的创建顺序?我想明确地对流程进行排名,以便按照精确的顺序触发,无论它们何时被创建。如果你需要一个例子,这里有3个过程的模拟:吃食物,补充板,移除板。 eat()进程会触发plateEmpty事件,期望重新填充该事件。但是如果removePlate()进程发生在refillPlate()之前,那么重新填充就不会发生。我想要先重新装满。我可以执行的唯一方法是订购44和45号线。还有另外一种方法吗?

[PS:我知道优先资源,但这不是我想要的。]

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 个答案:

答案 0 :(得分:0)

我找到了两个解决方案。

  1. 引入一个小延迟。 (根据进程之间的优先级缩放延迟。)
  2. 检查队列中是否有特定条件,并先让它处理。
  3. 解决方案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
    

    解决方案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)