1

在 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)
4

1 回答 1

0

我为此找到了两种解决方案。

  1. 引入一个小的延迟。(根据进程之间的优先级缩放延迟。)
  2. 检查队列中的特定条件并使其首先得到处理。

解决方案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)
于 2015-10-22T10:18:19.470 回答