Skip to content

Container

Source and Output

"""Example: container as a shared tank."""

from asimpy import Container, Environment, Process
from _util import example

TANK_CAPACITY = 10  # maximum units the tank can hold
FILL_AMOUNT = 4  # units added by each pump cycle
FILL_INTERVAL = 2  # ticks between pump cycles
DRAIN_AMOUNT = 3  # units consumed by each motor cycle
DRAIN_INTERVAL = 3  # ticks between motor cycles
NUM_CYCLES = 4  # number of drain cycles before the motor stops


class Pump(Process):
    def init(self, tank):
        self._tank = tank

    async def run(self):
        while True:
            await self.timeout(FILL_INTERVAL)
            await self._tank.put(FILL_AMOUNT)
            self._env.log("pump", f"added {FILL_AMOUNT}, level={self._tank.level}")


class Motor(Process):
    def init(self, tank):
        self._tank = tank

    async def run(self):
        for _ in range(NUM_CYCLES):
            await self.timeout(DRAIN_INTERVAL)
            self._env.log("motor", f"request {DRAIN_AMOUNT}, level={self._tank.level}")
            await self._tank.get(DRAIN_AMOUNT)
            self._env.log("motor", f"consumed {DRAIN_AMOUNT}, level={self._tank.level}")


def main():
    env = Environment()
    tank = Container(env, capacity=TANK_CAPACITY, init=5)
    Pump(env, tank)
    Motor(env, tank)
    env.run()
    return env


if __name__ == "__main__":
    example(main)

time name event
2 pump added 4, level=9
3 motor request 3, level=9
3 motor consumed 3, level=6
4 pump added 4, level=10
6 motor request 3, level=10
6 motor consumed 3, level=7
9 motor request 3, level=7
9 motor consumed 3, level=8
9 pump added 4, level=8
12 motor request 3, level=8
12 motor consumed 3, level=9
12 pump added 4, level=9

Key Points

  1. Container(env, capacity=N, init=K) creates a tank that starts at level K and holds at most N units. Both integers and floats are accepted for capacity.

  2. put(amount) blocks if adding amount would exceed capacity. get(amount) blocks if the tank holds less than amount.

  3. A successful get() immediately wakes any pending putter, and a successful put() immediately wakes any pending getter. At t=9 the motor's drain triggers the pump's blocked add in the same tick, so the log shows the pump's entry at t=9 even though no extra time passes.

  4. Unlike Queue, a Container has no concept of individual items: it tracks a single numeric level.

Check for Understanding

If init were 0 instead of 5, the motor would block on its first get(3) at t=3 because the tank would be empty. At what time would the motor finally receive those 3 units, and why?