Source code for traits.util.async_trait_wait
# (C) Copyright 2005-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!
import threading
[docs]def wait_for_condition(condition, obj, trait, timeout=None):
"""
Wait until the given condition is true, re-evaluating on trait change.
This is intended for use in multithreading situations where traits can be
modified from a different thread than the calling thread.
Wait until `condition` is satisfied. Raise a RuntimeError if
`condition` is not satisfied within the given timeout.
`condition` is a callback function that will be called with `obj`
as its single argument. It should return a boolean indicating
whether the condition is satisfied or not.
`timeout` gives the maximum time in seconds to wait for the
condition to become true. The default value of `None` indicates
no timeout.
(obj, trait) give an object and trait to listen to for indication
of a possible change: whenever the trait changes, the condition is
re-evaluated. The condition will also be evaluated on entering
this function.
Note that in cases of unusual timing it's possible for the condition to be
evaluated one more time *after* the ``wait_for_condition`` call has
returned.
"""
condition_satisfied = threading.Event()
def handler():
if condition(obj):
condition_satisfied.set()
obj.on_trait_change(handler, trait)
try:
if condition(obj):
# Catch case where the condition was satisfied before
# the on_trait_change handler was active.
pass
elif timeout is None:
# Allow a Ctrl-C to interrupt. The 0.05 value matches
# what's used by the standard library's Condition.wait.
while not condition_satisfied.is_set():
condition_satisfied.wait(timeout=0.05)
else:
condition_satisfied.wait(timeout=timeout)
if not condition_satisfied.is_set():
raise RuntimeError("Timed out waiting for condition.")
finally:
obj.on_trait_change(handler, trait, remove=True)