Add `Notify` event
Event is a stateful event type. It starts "unfinished" and becomes "done" after Event.set() is called. await Event.wait() blocks until the Event enters the done state; and when in the done state, any further awaits return "immediately". Later the Event can be put back into the unfinished state by calling Event.clear().
This has utility for Events that become done at some point in the future and can't become un-done. It's useful for sequencing primarily.
What is also needed is something like an Event, but not stateful. It does not become done. awaiting this Event-like object blocks until the next call to set(). This is currently accomplished using Event and calling clear() immediately after calling set(), like so:
notifier = Event()
async do_stuff(notifier):
while True:
await notifier.wait()
cocotb.log.info(cocotb.top.thingy.value)
cocotb.start_soon(do_stuff(notifier))
cocotb.start_soon(do_other_stuff(notifier))
# stuff
notifier.set()
notifier.clear()
# stuff
notifier.set()
notifier.clear()
Proposal
It would be nice to support this very common idiom with a custom Trigger or Event-like object. It should be called Notify or Notifier to signal it's intent compared to Event.
class Notifier:
"""Wakes up all waiters when someone calls the `notify` method.
def __init__(self) -> None:
self._event = Event()
def notify(self) -> None:
"""Wake up all waiters."""
self._event.set()
self._event.clear()
def wait(self) -> Trigger:
"""Wait until the next notify."""
return self._event.wait()
This could be implemented using an Event, like above, or have it's own implementation.
While the implementation is trivial, many new users don't understand the nuances of synchronization primitives like Event and how they can be used in multiple ways. I've seen something like Notifier implemented many time, often incorrectly.