Generateurv2/backend/env/lib/python3.10/site-packages/simpy/util.py
2022-06-24 17:14:37 +02:00

71 lines
2.0 KiB
Python

"""
A collection of utility functions:
.. autosummary::
start_delayed
"""
from typing import Generator
from simpy.core import Environment, SimTime
from simpy.events import Event, Process, ProcessGenerator
def start_delayed(
env: Environment, generator: ProcessGenerator, delay: SimTime
) -> Process:
"""Return a helper process that starts another process for *generator*
after a certain *delay*.
:meth:`~simpy.core.Environment.process()` starts a process at the current
simulation time. This helper allows you to start a process after a delay of
*delay* simulation time units::
>>> from simpy import Environment
>>> from simpy.util import start_delayed
>>> def my_process(env, x):
... print(f'{env.now}, {x}')
... yield env.timeout(1)
...
>>> env = Environment()
>>> proc = start_delayed(env, my_process(env, 3), 5)
>>> env.run()
5, 3
Raise a :exc:`ValueError` if ``delay <= 0``.
"""
if delay <= 0:
raise ValueError(f'delay(={delay}) must be > 0.')
def starter() -> Generator[Event, None, Process]:
yield env.timeout(delay)
proc = env.process(generator)
return proc
return env.process(starter())
def subscribe_at(event: Event) -> None:
"""Register at the *event* to receive an interrupt when it occurs.
The most common use case for this is to pass
a :class:`~simpy.events.Process` to get notified when it terminates.
Raise a :exc:`RuntimeError` if ``event`` has already occurred.
"""
env = event.env
assert env.active_process is not None
subscriber = env.active_process
def signaller(signaller: Event, receiver: Process) -> ProcessGenerator:
result = yield signaller
if receiver.is_alive:
receiver.interrupt((signaller, result))
if event.callbacks is not None:
env.process(signaller(event, subscriber))
else:
raise RuntimeError(f'{event} has already terminated.')