mirror of
https://gerrit.ovirt.org/vdsm
synced 2026-02-05 12:46:23 +01:00
concurrent: Add Timer class
This patch adds a Timer class to the concurrent module. The class is based on and behaves pretty much the same as the threading.Timer class, except that the thread which carries out the target function is created with concurrent.thread instead of the regular threading.Thread. This makes the Timer class available for use in vdsm, while still ensuring every thread is created with concurrent.thread. The Timer also doesn't inherit from the threading.Thread class, like the threading.Timer does, but instead keeps the thread object as an attribute. Change-Id: I28f7f0a7f254088129964bc7d30e5fae846eb3fb Signed-off-by: Filip Januska <fjanuska@redhat.com>
This commit is contained in:
committed by
Milan Zamazal
parent
9ce1d39532
commit
5075c8b8c0
@@ -377,3 +377,40 @@ def format_traceback(ident):
|
||||
if line:
|
||||
lines.append(" %s" % (line.strip()))
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
class Timer:
|
||||
"""
|
||||
Timer that creates a thread using concurrent.thread.
|
||||
|
||||
This Timer is similar to threading.Timer, but uses concurrent.thread()
|
||||
instead of threading.Thread.
|
||||
|
||||
Sample usage:
|
||||
t = Timer(30.0, f, args=None, kwargs=None)
|
||||
t.start()
|
||||
t.cancel() # stop the timer's action if it's still waiting
|
||||
"""
|
||||
|
||||
def __init__(self, interval, function, args=(), kwargs=None,
|
||||
name=None, daemon=True, log=None):
|
||||
if kwargs is None:
|
||||
kwargs = {}
|
||||
self._function = function
|
||||
self._args = args
|
||||
self._kwargs = kwargs
|
||||
self._interval = interval
|
||||
self._finished = threading.Event()
|
||||
self._thread = thread(self._run, name=name, daemon=daemon, log=log)
|
||||
|
||||
def cancel(self):
|
||||
"""Stop the timer if it hasn't finished yet."""
|
||||
self._finished.set()
|
||||
|
||||
def _run(self):
|
||||
if not self._finished.wait(self._interval):
|
||||
self._function(*self._args, **self._kwargs)
|
||||
|
||||
def start(self):
|
||||
"""Start the timer."""
|
||||
self._thread.start()
|
||||
|
||||
@@ -524,3 +524,34 @@ class TestValidatingEvent:
|
||||
|
||||
assert all(invalidated)
|
||||
assert not event.valid
|
||||
|
||||
|
||||
class TestTimer:
|
||||
|
||||
def test_run(self):
|
||||
delay = 0.2
|
||||
finished = threading.Event()
|
||||
timer = concurrent.Timer(delay, finished.set)
|
||||
start = time.monotonic()
|
||||
timer.start()
|
||||
assert finished.wait(1)
|
||||
assert time.monotonic() - start >= delay
|
||||
|
||||
def test_cancel(self):
|
||||
delay = 5
|
||||
finished = threading.Event()
|
||||
timer = concurrent.Timer(delay, finished.set)
|
||||
timer.start()
|
||||
timer.cancel()
|
||||
timer._thread.join(1)
|
||||
assert not timer._thread.is_alive()
|
||||
assert not finished.is_set()
|
||||
|
||||
def test_late_cancel(self):
|
||||
delay = 0
|
||||
finished = threading.Event()
|
||||
timer = concurrent.Timer(delay, finished.set)
|
||||
timer.start()
|
||||
finished.wait(1)
|
||||
timer.cancel()
|
||||
assert finished.is_set()
|
||||
|
||||
Reference in New Issue
Block a user