Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bpo-29569: threading.Timer class: Continue periodical execution till action return True #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions Doc/library/threading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -831,29 +831,39 @@ method. The :meth:`~Event.wait` method blocks until the flag is true.
Timer Objects
-------------

This class represents an action that should be run only after a certain amount
of time has passed --- a timer. :class:`Timer` is a subclass of :class:`Thread`
This class represents an action that should be run after a certain amount
of time has passed --- a timer. It also can run periodically. Each run takes
place after a specified time after the previous run. This continues until
the action returns TRUE. :class:`Timer` is a subclass of :class:`Thread`
and as such also functions as an example of creating custom threads.

Timers are started, as with threads, by calling their :meth:`~Timer.start`
method. The timer can be stopped (before its action has begun) by calling the
:meth:`~Timer.cancel` method. The interval the timer will wait before
executing its action may not be exactly the same as the interval specified by
the user.
:meth:`~Timer.cancel` method. If action has returned True then next run is
scheduled after the timer interval. The interval the timer will wait before
executing its action may not be exactly the same as the interval specified
by the user.


For example::

def hello():
print("hello, world")
def star():
global cnt
print("*")
cnt -= 1
if cnt > 0:
return True

t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed
cnt = 5
t = Timer(1.0, star)
t.start() # it prints five "*" with 1 sec waiting between prints


.. class:: Timer(interval, function, args=None, kwargs=None)

Create a timer that will run *function* with arguments *args* and keyword
arguments *kwargs*, after *interval* seconds have passed.
arguments *kwargs*, after *interval* seconds have passed and continues
periodically run *function* till *function* returns True.
If *args* is ``None`` (the default) then an empty list will be used.
If *kwargs* is ``None`` (the default) then an empty dict will be used.

Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,7 @@ class TimerTests(BaseTestCase):
def setUp(self):
BaseTestCase.setUp(self)
self.callback_args = []
self.callback_cnt = 3
self.callback_event = threading.Event()

def test_init_immutable_default_args(self):
Expand All @@ -1087,6 +1088,29 @@ def test_init_immutable_default_args(self):
def _callback_spy(self, *args, **kwargs):
self.callback_args.append((args[:], kwargs.copy()))
self.callback_event.set()
self.assertEqual(self.callback_event.is_set(), True)

def test_continuous_execution(self):
timer1 = threading.Timer(0.01, self._callback_cont)
self.callback_event.clear()
timer1.start()
for i in range(3):
self.callback_event.wait(1.0)
self.callback_event.clear()
self.assertEqual(self.callback_cnt, 0)
self.callback_cnt = 3
timer2 = threading.Timer(0.5, self._callback_cont)
self.callback_event.clear()
timer2.start()
timer2.cancel()
timer2.join(2.0)
self.assertEqual(self.callback_cnt, 3)

def _callback_cont(self):
self.callback_cnt -= 1
self.callback_event.set()
self.assertEqual(self.callback_event.is_set(), True)
return self.callback_cnt > 0

class LockTests(lock_tests.LockTests):
locktype = staticmethod(threading.Lock)
Expand Down
7 changes: 4 additions & 3 deletions Lib/threading.py
Original file line number Diff line number Diff line change
Expand Up @@ -1177,9 +1177,10 @@ def cancel(self):
self.finished.set()

def run(self):
self.finished.wait(self.interval)
if not self.finished.is_set():
self.function(*self.args, **self.kwargs)
"""Continue execution after wait till function returns True"""
while(not self.finished.wait(self.interval)):
if not self.function(*self.args, **self.kwargs):
break
self.finished.set()

# Special thread class to represent the main thread
Expand Down