Commit 556ba04a authored by Giampaolo Rodola's avatar Giampaolo Rodola

Fix #13449: add 'blocking' parameter to sched.scheduler.run() so that the...

Fix #13449: add 'blocking' parameter to sched.scheduler.run() so that the scheduler can be used in non-blocking applications
parent 73520d57
......@@ -102,12 +102,15 @@ Scheduler Objects
Return true if the event queue is empty.
.. method:: scheduler.run()
.. method:: scheduler.run(blocking=True)
Run all scheduled events. This function will wait (using the :func:`delayfunc`
Run all scheduled events. This method will wait (using the :func:`delayfunc`
function passed to the constructor) for the next event, then execute it and so
on until there are no more scheduled events.
If *blocking* is False executes the scheduled events due to expire soonest
(if any) and then return.
Either *action* or *delayfunc* can raise an exception. In either case, the
scheduler will maintain a consistent state and propagate the exception. If an
exception is raised by *action*, the event will not be attempted in future calls
......@@ -118,6 +121,9 @@ Scheduler Objects
the calling code is responsible for canceling events which are no longer
pertinent.
.. versionadded:: 3.3
*blocking* parameter was added.
.. attribute:: scheduler.queue
Read-only attribute returning a list of upcoming events in the order they
......
......@@ -662,6 +662,12 @@ should be used. For example, this will send a ``'HEAD'`` request::
sched
-----
* :meth:`~sched.scheduler.run` now accepts a *blocking* parameter which when
set to False makes the method execute the scheduled events due to expire
soonest (if any) and then return immediately.
This is useful in case you want to use the :class:`~sched.scheduler` in
non-blocking applications. (Contributed by Giampaolo Rodolà in :issue:`13449`)
* :class:`~sched.scheduler` class can now be safely used in multi-threaded
environments. (Contributed by Josiah Carlson and Giampaolo Rodolà in
:issue:`8684`)
......
......@@ -91,8 +91,10 @@ class scheduler:
with self._lock:
return not self._queue
def run(self):
def run(self, blocking=True):
"""Execute events until the queue is empty.
If blocking is False executes the scheduled events due to
expire soonest (if any) and then return.
When there is a positive delay until the first event, the
delay function is called and the event is left in the queue;
......@@ -123,6 +125,8 @@ class scheduler:
time, priority, action, argument, kwargs = checked_event = q[0]
now = timefunc()
if now < time:
if not blocking:
return
delayfunc(time - now)
else:
event = pop(q)
......
......@@ -86,6 +86,16 @@ class TestCase(unittest.TestCase):
scheduler.run()
self.assertEqual(flag, [None])
def test_run_non_blocking(self):
l = []
fun = lambda x: l.append(x)
scheduler = sched.scheduler(time.time, time.sleep)
for x in [10, 9, 8, 7, 6]:
scheduler.enter(x, 1, fun, (x,))
scheduler.run(blocking=False)
self.assertEqual(l, [])
def test_main():
support.run_unittest(TestCase)
......
......@@ -409,8 +409,12 @@ Core and Builtins
Library
-------
- Issue #13449 sched.scheduler.run() method has a new "blocking" parameter which
when set to False makes run() execute the scheduled events due to expire
soonest (if any) and then return. Patch by Giampaolo Rodolà.
- Issue #8684 sched.scheduler class can be safely used in multi-threaded
environments.
environments. Patch by Josiah Carlson and Giampaolo Rodolà.
- Alias resource.error to OSError ala PEP 3151.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment