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
-
Container(env, capacity=N, init=K)creates a tank that starts at levelKand holds at mostNunits. Both integers and floats are accepted for capacity. -
put(amount)blocks if addingamountwould exceed capacity.get(amount)blocks if the tank holds less thanamount. -
A successful
get()immediately wakes any pending putter, and a successfulput()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. -
Unlike
Queue, aContainerhas 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?