Skip to content

Resources, containers and queues

resource

Shared resources with finite capacity (servers, machines, gates, staff ...).

Preempted dataclass

Preempted(resource: str, by: Request, usage_since: float)

Interrupt.cause received by a process whose unit was taken by a higher-priority request.

Request

Request(resource: Resource, sim: Simulation, *, priority: float = 0, entity: Entity | None = None, owner: Process | None = None)

Bases: Waitable

A claim on one unit of a :class:Resource.

Yielding the request waits until it is granted; the yield returns the request itself, so req = yield sim.request(server) works. With a patience the request is withdrawn (reneged) if not granted in time and the yield returns with req.granted == False.

cancel

cancel() -> None

Withdraw a request that has not been granted yet.

Resource

Resource(name: str, capacity: int = 1, *, discipline: Discipline = 'fifo', preemptive: bool = False, sim: Simulation | None = None)

A pool of capacity identical units that entities acquire and release.

Statistics gathered automatically: utilization (time-average busy units / capacity), availability (fraction of capacity not down), queue length (time-weighted), waiting time per granted request, and counts of requests, grants, releases and reneges.

Capacity can change during a run (:meth:set_capacity) and units can be taken down and repaired (:meth:fail / :meth:repair). Units already in use when capacity drops finish normally unless interrupt=True.

With preemptive=True (requires the "priority" discipline) a request that finds no free unit evicts the lowest-priority user if it is strictly more important (lower value). The evicted process receives :class:~simulsi.errors.Interrupt with a :class:Preempted cause; its unit is already released, so it typically re-requests the remaining work.

utilization property

utilization: float

Time-average busy units divided by time-average nominal capacity.

fail

fail(units: int | None = None, *, interrupt: bool = False, cause: Any = None) -> None

Take units (default: all) out of service.

With interrupt=True, the most recently granted users beyond the remaining capacity are interrupted (their processes receive :class:~simulsi.errors.Interrupt with cause).

repair

repair(units: int | None = None) -> None

Return units (default: all) to service.

container

Containers: a level of a bulk or countable quantity (fuel, stock, cash, parts).

Container

Container(name: str = 'container', capacity: float = math.inf, *, init: float = 0.0, sim: Simulation | None = None)

A level between 0 and capacity that processes add to and take from.

yield tank.get(30) waits until 30 units are available and removes them; yield tank.put(50) waits until there is room. Waiting gets (and waiting puts) are served strictly in arrival order, so a large request is not starved by a stream of small ones.

Metrics (container.<name>.): level.mean, level.min, level.max, level_final, put_amount, get_amount, get_wait.mean, put_wait.mean and stockouts (gets that had to wait).

put

put(amount: float) -> ContainerPut

Add amount; the returned waitable triggers once it fits.

get

get(amount: float) -> ContainerGet

Take amount; the returned waitable triggers once enough is available.

cancel

cancel(req: ContainerGet | ContainerPut) -> bool

Withdraw a pending get or put (e.g. after a timeout).

queue

Queues (buffers) that hold items between process steps.

Queue

Queue(name: str = 'queue', *, discipline: Discipline = 'fifo', capacity: float = math.inf, sim: Simulation | None = None)

Bases: Generic[T]

An ordered buffer with optional finite capacity and blocking put/get.

yield queue.put(item) waits while the queue is full; item = yield queue.get() waits while it is empty. Items leave in the order given by discipline ("fifo", "lifo", "priority" or a key function applied to the item).

queue.get(filter=lambda part: part.kind == "A") takes the first item (in discipline order) that matches, waiting until one arrives. A waiting filtered get does not hold up gets for other items.

Accounting invariant (checked in tests): puts == gets + removed + len(queue), so items can never disappear silently.

get

get(filter: Callable[[T], bool] | None = None) -> Get

Take the next item (or the next one matching filter), waiting if there is none.

try_get

try_get(filter: Callable[[T], bool] | None = None) -> T | None

Non-blocking get: the next (matching) item, or None.

remove

remove(item: T) -> bool

Remove a specific item (e.g. a customer abandoning the line).

cancel

cancel(req: Get | Put) -> bool

Withdraw a pending get or put.

discipline

Queue disciplines shared by resources and queues.

OrderedBuffer

OrderedBuffer(discipline: Discipline = 'fifo')

Bases: Generic[T]

Items ordered by a discipline; ties always fall back to arrival order.

  • "fifo" - first in, first out
  • "lifo" - last in, first out
  • "priority" - lowest priority value first, FIFO among equals
  • a callable - key(subject) ascending, FIFO among equals

Removal from the middle (reneging, cancellation) is O(1) via lazy deletion.

first

first(predicate: Callable[[T], bool]) -> T | None

The first item in service order for which predicate is true, or None.