SimPy Resource vs PriorityResource vs PreemptiveResource: Complete Guide to Resource Scheduling
SimPy provides three resource classes—Resource, PriorityResource, and PreemptiveResource—that differ in queue ordering and preemption capabilities, ranging from simple FIFO allocation to priority-based interruption of running processes.
The K-Dense-AI/scientific-agent-skills repository contains detailed reference implementations showing how each class manages process contention in discrete-event simulations. Understanding these differences is critical for accurately modeling real-world systems like CPU schedulers, emergency rooms, or manufacturing lines where task priority and preemption matter.
Core Differences Between SimPy Resource Types
SimPy's resource hierarchy adds progressive layers of scheduling control. Each class builds upon the previous one, starting from basic capacity limits to full preemption capabilities.
Resource: FIFO Semantics
The simpy.Resource class implements a simple semaphore-style resource where processes wait in a FIFO (first-come-first-served) queue. When a slot frees, the first waiting request in resource.queue is granted access. Once a process acquires the resource, it runs to completion or until voluntary release—there is no mechanism to interrupt an active holder.
Typical use: Modeling simple capacity constraints like gas pumps, database connection pools, or limited server instances where arrival order determines service sequence.
PriorityResource: Ordered Waiting Queue
simpy.PriorityResource extends Resource by replacing the FIFO queue with a priority heap (min-heap) ordered by a numeric priority argument. Lower values indicate higher priority. When a slot becomes available, the waiting request with the smallest priority value is served next.
Important limitation: This priority ordering only affects the waiting queue. A process currently holding the resource cannot be displaced; it runs uninterrupted until completion.
Typical use: VIP service lanes, emergency dispatch systems, or any scenario where waiting jobs have different importance levels but running jobs must complete.
PreemptiveResource: Interruptible Execution
simpy.PreemptiveResource extends PriorityResource with full preemption capabilities. When a higher-priority request arrives while a lower-priority process holds the resource, SimPy raises a simpy.Interrupt exception inside the active process's context. The preempted process exits its with block prematurely and can catch the exception to perform cleanup or resume later.
Implementation detail: According to the source in scientific-skills/simpy/references/process-interaction.md, the resource tracks currently holding processes and compares incoming request priorities against active holders to trigger interruptions.
Typical use: Real-time operating systems, CPU scheduling algorithms, or emergency room triage where critical tasks must immediately displace less urgent ones.
Implementation Details from Source Code
The scientific-skills/simpy/SKILL.md file summarizes these resource types in a comparative table format, while scientific-skills/simpy/references/resources.md contains the concrete implementation patterns.
Key architectural implementations:
Resource: Maintainsresource.queueas a standard list processed in FIFO orderPriorityResource: Stores requests as tuples(priority, ...)in a heap structure, ensuringheapqalways pops the lowest priority value firstPreemptiveResource: Checks incoming request priorities against active holders; ifnew_priority < active_priority, triggerssimpy.Interruptin the active process
Code Examples
Basic FIFO Resource
import simpy
env = simpy.Environment()
fifo_res = simpy.Resource(env, capacity=2)
def fifo_user(env, name):
with fifo_res.request() as req:
yield req
print(f'{name} got the resource at {env.now}')
yield env.timeout(5)
print(f'{name} released the resource at {env.now}')
for i in range(3):
env.process(fifo_user(env, f'FIFO-{i+1}'))
env.run()
Priority-Based Queue
import simpy
env = simpy.Environment()
prio_res = simpy.PriorityResource(env, capacity=1)
def prio_user(env, name, prio):
with prio_res.request(priority=prio) as req:
yield req
print(f'{name} (prio={prio}) got the resource at {env.now}')
yield env.timeout(5)
env.process(prio_user(env, 'Low‑prio', priority=10))
env.process(prio_user(env, 'High‑prio', priority=1))
env.run()
Preemptive Resource with Interrupt Handling
import simpy
env = simpy.Environment()
pre_res = simpy.PreemptiveResource(env, capacity=1)
def preemptive_user(env, name, prio):
with pre_res.request(priority=prio) as req:
try:
yield req
print(f'{name} (prio={prio}) acquired at {env.now}')
yield env.timeout(10) # Long job
print(f'{name} finished at {env.now}')
except simpy.Interrupt:
print(f'{name} was pre‑empted at {env.now}')
env.process(preemptive_user(env, 'Low‑prio', priority=10))
env.process(preemptive_user(env, 'High‑prio', priority=1))
env.run()
When to Use Each Resource Type
Choose your resource class based on scheduling requirements:
-
Use
Resourcewhen you need simple capacity limiting without priority distinctions, such as modeling parking spaces or network bandwidth where first-come-first-served is realistic. -
Use
PriorityResourcewhen tasks have different importance levels but should not be interrupted once started, such as hospital appointment scheduling or customer service tiers. -
Use
PreemptiveResourcewhen critical tasks must immediately seize control from less urgent ones, such as real-time system interrupts or emergency medical triage where a critical patient displaces a stable one.
Summary
simpy.Resourceprovides FIFO access with no preemption; processes wait in arrival order and run to completion.simpy.PriorityResourceadds numeric priority to the waiting queue (lower value = higher priority) but does not interrupt active processes.simpy.PreemptiveResourceallows high-priority processes to interrupt low-priority holders viasimpy.Interruptexceptions.- All three classes share the same
request()API, butPriorityResourceandPreemptiveResourcerequire thepriorityparameter. - Preempted processes must implement
try/except simpy.Interruptblocks to handle forced release gracefully.
Frequently Asked Questions
Can I change the priority of a waiting request after it has been submitted?
No, once a request is submitted to PriorityResource or PreemptiveResource, its priority is fixed in the heap. To change priority, you must cancel the existing request and submit a new one with the updated priority value.
What happens to a preempted process after it catches the Interrupt exception?
The preempted process exits the with resource.request() context, releasing the resource immediately. You can choose to retry the request later, terminate the process, or move it to another queue. The simulation continues based on your exception handling logic.
Does lower priority number mean higher or lower importance in SimPy?
Lower numeric values indicate higher priority. When using priority=1 versus priority=10, the request with priority 1 is considered more urgent and will be served first (or preempt the holder in PreemptiveResource).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →