Interrupt Problems

55 views
Skip to first unread message

ccf...@gmail.com

unread,
Sep 12, 2020, 12:17:23 PM9/12/20
to python-simpy
A worker must perform two different tasks in sequence. Work breaks can happen, which I think of as an interrupt. If a break happens, the specific task she is working on should be stopped, the time spent on the task pre-break should be captured, then the specific task resumes using the remaining task duration.

I implemented the following toy example (borrowing heavily from the Machine Shop example in the docs) but unsure how to propagate the break interrupt to the specific task. You'll see that I have commented out code related to the interrupt and provide, hopefully helpful additional comments. Thanks in advance for any help!

Chris

import simpy

class Worker:
  def __init__(self, env):
    self.env = env
    self.work_proc = env.process(self.work())
#   self.break_proc = env.process(self.break_time())

  def work(self):
    while True:
      # two different tasks, w/ different durations
      # 'Task 20' finishes before 'Task 40' starts
      # if you put try/except here, 'Task 20' will
      # resume after interrupt, even though may be
      # on 'Task 40'
      yield self.env.process(self.task(20))
      yield self.env.process(self.task(40))

  def task(self, duration):
    while duration:
      # I put try/except at 'task level'
      # following Machine Shop example
      try:
        start = self.env.now
        yield self.env.timeout(duration)
        print(f'Task {duration} finished at {env.now}')
        duration = 0 # Exits while loop
      except simpy.Interrupt:
        duration -= self.env.now - start

# def break_time(self):
#   yield self.env.timeout(10) # just picked 10, can be anything
    # I would like to interrupt the work process
    # and somehow this gets propagated to the 'in progress' task
#   self.work_proc.interrupt()

env = simpy.Environment()
w = Worker(env)
env.run(until=100)

Task 20 finished at 20
Task 40 finished at 60
Task 20 finished at 80


Michael Gibbs

unread,
Sep 16, 2020, 5:46:29 PM9/16/20
to python-simpy
Try this

When a task starts, I save a reference to the process.  This will be the "in process" task.
When my break_time process timeout expires, I simply interrupt the last saved task
A more robust version would check that the task being interrupted is active.

import simpy

class Worker:
  def __init__(self, env):
    self.env = env
    env.process(self.work())
    self.runningTask = None # the in process task
    env.process(self.break_time())


  def work(self):
    while True:
      # two different tasks, w/ different durations
      # 'Task 20' finishes before 'Task 40' starts
      # if you put try/except here, 'Task 20' will
      # resume after interrupt, even though may be
      # on 'Task 40'

      # remember what task in in process
      self.runningTask = self.env.process(self.task(20))
      yield self.runningTask

      self.runningTask = self.env.process(self.task(40))
      yield self.runningTask

  def task(self, duration):
    while duration:
      # I put try/except at 'task level'
      # following Machine Shop example
      try:
        start = self.env.now
        yield self.env.timeout(duration)
        print(f'Task {duration} finished at {env.now}')
        duration = 0 # Exits while loop
      except simpy.Interrupt:
        duration -= self.env.now - start
        print(f'break at {env.now}, has remaining duration of {duration}')

  def break_time(self):
    yield self.env.timeout(30) # just picked 30, can be anything
    #I would like to interrupt the work process
    #and somehow this gets propagated to the 'in progress' task

    # saved the inprocess task, may want to test if process is still live
    self.runningTask.interrupt()

env = simpy.Environment()
w = Worker(env)
env.run(until=100)

ccf...@gmail.com

unread,
Sep 19, 2020, 8:11:05 AM9/19/20
to python-simpy
Hi Michael,

Thanks for working through the example in your post. Much appreciated.

Chris

Reply all
Reply to author
Forward
0 new messages