From f8ced5cb9b15f5d693e28299c0bee73ba5d70a37 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Wed, 5 May 2010 21:44:35 -0700 Subject: [PATCH] Converted fully over to what the internet assures me is the American spelling of 'canceled' -- this only affects internal variables. Also cleaned up the meticulous timer accounting of the hub tests so they stop failing after other tests are run. Also added new parameter to the abort method because it seemed to be the dominant mode of operation. --- eventlet/greenthread.py | 5 +++-- eventlet/hubs/hub.py | 35 ++++++++++++++++++++--------- eventlet/hubs/timer.py | 3 +-- eventlet/timeout.py | 4 ++-- tests/__init__.py | 16 ++++++++++++- tests/api_test.py | 5 ++--- tests/hub_test.py | 50 +++++++++++++++++++++++------------------ tests/saranwrap_test.py | 3 --- tests/tpool_test.py | 3 --- 9 files changed, 76 insertions(+), 48 deletions(-) diff --git a/eventlet/greenthread.py b/eventlet/greenthread.py index b7e0a81..5fce489 100644 --- a/eventlet/greenthread.py +++ b/eventlet/greenthread.py @@ -23,8 +23,9 @@ def sleep(seconds=0): occasionally; otherwise nothing else will run. """ hub = hubs.get_hub() - assert hub.greenlet is not greenlet.getcurrent(), 'do not call blocking functions from the mainloop' - timer = hub.schedule_call_global(seconds, greenlet.getcurrent().switch) + current = greenlet.getcurrent() + assert hub.greenlet is not current, 'do not call blocking functions from the mainloop' + timer = hub.schedule_call_global(seconds, current.switch) try: hub.switch() finally: diff --git a/eventlet/hubs/hub.py b/eventlet/hubs/hub.py index fe7c18c..2dcc2b1 100644 --- a/eventlet/hubs/hub.py +++ b/eventlet/hubs/hub.py @@ -63,7 +63,7 @@ class BaseHub(object): self.next_timers = [] self.lclass = FdListener self.debug_exceptions = True - self.timers_cancelled = 0 + self.timers_canceled = 0 def add(self, evtype, fileno, cb): """ Signals an intent to or write a particular file descriptor. @@ -183,18 +183,30 @@ class BaseHub(object): else: self.wait(0) else: + self.canceled_timers = 0 del self.timers[:] del self.next_timers[:] finally: self.running = False self.stopping = False - def abort(self): - """Stop the runloop. If run is executing, it will exit after completing - the next runloop iteration. + def abort(self, wait=False): + """Stop the runloop. If run is executing, it will exit after + completing the next runloop iteration. + + Set *wait* to True to cause abort to switch to the hub immediately and + wait until it's finished processing. Waiting for the hub will only + work from the main greenthread; all other greenthreads will become + unreachable. """ if self.running: self.stopping = True + if wait: + # schedule an immediate timer just so the hub doesn't sleep + self.schedule_call_global(0, lambda: None) + # switch to it; when done the hub will switch back to its parent, + # the main greenlet + self.switch() def squelch_generic_exception(self, exc_info): if self.debug_exceptions: @@ -215,10 +227,10 @@ class BaseHub(object): pass def timer_canceled(self, timer): - self.timers_cancelled += 1 + self.timers_canceled += 1 len_timers = len(self.timers) - if len_timers > 1000 and len_timers/2 <= self.timers_cancelled: - self.timers_cancelled = 0 + if len_timers > 1000 and len_timers/2 <= self.timers_canceled: + self.timers_canceled = 0 self.timers = [t for t in self.timers if not t[1].called] heapq.heapify(self.timers) self.timer_finished(timer) @@ -227,7 +239,10 @@ class BaseHub(object): heappush = heapq.heappush t = self.timers for item in self.next_timers: - heappush(t, item) + if item[1].called: + self.timers_canceled -= 1 + else: + heappush(t, item) del self.next_timers[:] def schedule_call_local(self, seconds, cb, *args, **kw): @@ -244,7 +259,7 @@ class BaseHub(object): def schedule_call_global(self, seconds, cb, *args, **kw): """Schedule a callable to be called after 'seconds' seconds have - elapsed. The timer will NOT be cancelled if the current greenlet has + elapsed. The timer will NOT be canceled if the current greenlet has exited before the timer fires. seconds: The number of seconds to wait. cb: The callable to call after the given time. @@ -273,7 +288,7 @@ class BaseHub(object): try: try: if timer.called: - self.timers_cancelled -= 1 + self.timers_canceled -= 1 else: timer() except self.SYSTEM_EXCEPTIONS: diff --git a/eventlet/hubs/timer.py b/eventlet/hubs/timer.py index 519d7c4..827d08e 100644 --- a/eventlet/hubs/timer.py +++ b/eventlet/hubs/timer.py @@ -6,7 +6,6 @@ useful for debugging leaking timers, to find out where the timer was set up. """ _g_debug = False class Timer(object): - #__slots__ = ['seconds', 'tpl', 'called', 'cancelled', 'scheduled_time', 'greenlet', 'traceback', 'impltimer'] def __init__(self, seconds, cb, *args, **kw): """Create a timer. seconds: The minimum number of seconds to wait before calling @@ -64,7 +63,7 @@ class Timer(object): def cancel(self): """Prevent this timer from being called. If the timer has already - been called or cancelled, has no effect. + been called or canceled, has no effect. """ if not self.called: self.called = True diff --git a/eventlet/timeout.py b/eventlet/timeout.py index e50c868..135545b 100644 --- a/eventlet/timeout.py +++ b/eventlet/timeout.py @@ -52,7 +52,7 @@ class Timeout(BaseException): def start(self): """Schedule the timeout. This is called on construction, so it should not be called explicitly, unless the timer has been - cancelled.""" + canceled.""" assert not self.pending, \ '%r is already started; to restart it, cancel it first' % self if self.seconds is None: # "fake" timeout (never expires) @@ -77,7 +77,7 @@ class Timeout(BaseException): """If the timeout is pending, cancel it. If not using Timeouts in ``with`` statements, always call cancel() in a ``finally`` after the block of code that is getting timed out. - If not cancelled, the timeout will be raised later on, in some + If not canceled, the timeout will be raised later on, in some unexpected section of the application.""" if self.timer is not None: self.timer.cancel() diff --git a/tests/__init__.py b/tests/__init__.py index 72cf7e7..6349a96 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -129,6 +129,21 @@ class LimitedTestCase(unittest.TestCase): print debug.format_hub_timers() print debug.format_hub_listeners() + def assert_less_than(self, a,b,msg=None): + if msg: + self.assert_(a