|
1 | 1 | # License: MIT |
2 | 2 | # Copyright © 2023 Frequenz Energy-as-a-Service GmbH |
3 | 3 |
|
4 | | -"""A receiver that can be made ready through an event.""" |
| 4 | +"""A receiver that can be made ready directly. |
5 | 5 |
|
| 6 | +!!! Tip inline end |
| 7 | +
|
| 8 | + Read the [`Event`][frequenz.channels.event.Event] documentation for more |
| 9 | + information. |
| 10 | +
|
| 11 | +This module contains the following: |
| 12 | +
|
| 13 | +* [`Event`][frequenz.channels.event.Event]: |
| 14 | + {{docstring_summary("frequenz.channels.event.Event")}} |
| 15 | +""" |
6 | 16 |
|
7 | 17 | import asyncio as _asyncio |
8 | 18 |
|
9 | 19 | from frequenz.channels import _receiver |
10 | 20 |
|
11 | 21 |
|
12 | 22 | class Event(_receiver.Receiver[None]): |
13 | | - """A receiver that can be made ready through an event. |
| 23 | + """A receiver that can be made ready directly. |
| 24 | +
|
| 25 | + # Usage |
14 | 26 |
|
15 | | - The receiver (the [`ready()`][frequenz.channels.event.Event.ready] method) will wait |
16 | | - until [`set()`][frequenz.channels.event.Event.set] is called. At that point the |
17 | | - receiver will wait again after the event is |
18 | | - [`consume()`][frequenz.channels.Receiver.consume]d. |
| 27 | + There are cases where it is useful to be able to send a signal to |
| 28 | + a [`select()`][frequenz.channels.select] loop, for example, to stop a loop from |
| 29 | + outside the loop itself. |
19 | 30 |
|
20 | | - The receiver can be completely stopped by calling |
| 31 | + To do that, you can use an [`Event`][frequenz.channels.event.Event] receiver and |
| 32 | + call [`set()`][frequenz.channels.event.Event.set] on it when you want to make it |
| 33 | + ready. |
| 34 | +
|
| 35 | + # Stopping |
| 36 | +
|
| 37 | + The receiver will be re-activated (will keep blocking) after the current set |
| 38 | + event is received. To stop the receiver completely, you can call |
21 | 39 | [`stop()`][frequenz.channels.event.Event.stop]. |
22 | 40 |
|
23 | | - Example: |
| 41 | + # Example |
| 42 | +
|
| 43 | + Example: Exit after printing the first 5 numbers |
24 | 44 | ```python |
25 | 45 | import asyncio |
26 | | - from frequenz.channels import Receiver, select, selected_from |
| 46 | +
|
| 47 | + from frequenz.channels import Anycast, select, selected_from |
27 | 48 | from frequenz.channels.event import Event |
28 | 49 |
|
29 | | - other_receiver: Receiver[int] = ... |
30 | | - exit_event = Event() |
| 50 | + channel: Anycast[int] = Anycast(name="channel") |
| 51 | + receiver = channel.new_receiver() |
| 52 | + sender = channel.new_sender() |
| 53 | + stop_event = Event(name="stop") |
| 54 | +
|
| 55 | +
|
| 56 | + async def do_work() -> None: |
| 57 | + async for selected in select(receiver, stop_event): |
| 58 | + if selected_from(selected, receiver): |
| 59 | + print(selected.value) |
| 60 | + elif selected_from(selected, stop_event): |
| 61 | + print("Stop event triggered") |
| 62 | + stop_event.stop() |
| 63 | + break |
| 64 | +
|
| 65 | +
|
| 66 | + async def send_stuff() -> None: |
| 67 | + for i in range(10): |
| 68 | + if stop_event.is_stopped: |
| 69 | + break |
| 70 | + await asyncio.sleep(1) |
| 71 | + await sender.send(i) |
| 72 | +
|
31 | 73 |
|
32 | | - async def exit_after_10_seconds() -> None: |
33 | | - asyncio.sleep(10) |
34 | | - exit_event.set() |
| 74 | + async def main() -> None: |
| 75 | + async with asyncio.TaskGroup() as task_group: |
| 76 | + task_group.create_task(do_work(), name="do_work") |
| 77 | + task_group.create_task(send_stuff(), name="send_stuff") |
| 78 | + await asyncio.sleep(5.5) |
| 79 | + stop_event.set() |
35 | 80 |
|
36 | | - asyncio.ensure_future(exit_after_10_seconds()) |
37 | 81 |
|
38 | | - async for selected in select(exit_event, other_receiver): |
39 | | - if selected_from(selected, exit_event): |
40 | | - break |
41 | | - if selected_from(selected, other_receiver): |
42 | | - print(selected.value) |
43 | | - else: |
44 | | - assert False, "Unknown receiver selected" |
| 82 | + asyncio.run(main()) |
45 | 83 | ``` |
46 | 84 | """ |
47 | 85 |
|
|
0 commit comments