Fix #13449: add 'blocking' parameter to sched.scheduler.run() so that the scheduler can be used in non-blocking applications

This commit is contained in:
Giampaolo Rodola' 2011-12-14 14:38:45 +01:00
parent 73520d57eb
commit 556ba04a8d
5 changed files with 34 additions and 4 deletions

View File

@ -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

View File

@ -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`)

View File

@ -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)

View File

@ -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)

View File

@ -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.