# SimPy Resource vs PriorityResource vs PreemptiveResource: Complete Guide to Resource Scheduling

> Understand SimPy Resource, PriorityResource, and PreemptiveResource differences. Learn how to manage queues and preemption for efficient scheduling in your simulations.

- Repository: [K-Dense/scientific-agent-skills](https://github.com/K-Dense-AI/scientific-agent-skills)
- Tags: deep-dive
- Published: 2026-05-14

---

**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`](https://github.com/K-Dense-AI/scientific-agent-skills/blob/main/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`](https://github.com/K-Dense-AI/scientific-agent-skills/blob/main/scientific-skills/simpy/SKILL.md) file summarizes these resource types in a comparative table format, while [`scientific-skills/simpy/references/resources.md`](https://github.com/K-Dense-AI/scientific-agent-skills/blob/main/scientific-skills/simpy/references/resources.md) contains the concrete implementation patterns.

Key architectural implementations:
- **`Resource`**: Maintains `resource.queue` as a standard list processed in FIFO order
- **`PriorityResource`**: Stores requests as tuples `(priority, ...)` in a heap structure, ensuring `heapq` always pops the lowest priority value first
- **`PreemptiveResource`**: Checks incoming request priorities against active holders; if `new_priority < active_priority`, triggers `simpy.Interrupt` in the active process

## Code Examples

### Basic FIFO Resource

```python
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

```python
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

```python
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 `Resource`** when you need simple capacity limiting without priority distinctions, such as modeling parking spaces or network bandwidth where first-come-first-served is realistic.

- **Use `PriorityResource`** when tasks have different importance levels but should not be interrupted once started, such as hospital appointment scheduling or customer service tiers.

- **Use `PreemptiveResource`** when 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.Resource`** provides FIFO access with no preemption; processes wait in arrival order and run to completion.
- **`simpy.PriorityResource`** adds numeric priority to the waiting queue (lower value = higher priority) but does not interrupt active processes.
- **`simpy.PreemptiveResource`** allows high-priority processes to interrupt low-priority holders via `simpy.Interrupt` exceptions.
- All three classes share the same `request()` API, but `PriorityResource` and `PreemptiveResource` require the `priority` parameter.
- Preempted processes must implement `try/except simpy.Interrupt` blocks 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`).