Use eventlet Event for loopingcall events

This fixes broken logic for finding out how to use green threads. Using
threading.Event with eventlet creates useless load related to timers.

Change-Id: I62e9f1a7cde8846be368fbec58b8e0825ce02079
Closes-Bug: #1798774
This commit is contained in:
Thomas Herve 2018-10-19 10:45:48 +02:00
parent 2705800cd3
commit c2463470f5
2 changed files with 24 additions and 50 deletions

View File

@ -17,13 +17,12 @@
import random import random
import sys import sys
import threading
import time import time
from eventlet import event from eventlet import event
from eventlet import greenthread from eventlet import greenthread
from eventlet import timeout as eventlettimeout
from oslo_log import log as logging from oslo_log import log as logging
from oslo_utils import eventletutils
from oslo_utils import excutils from oslo_utils import excutils
from oslo_utils import reflection from oslo_utils import reflection
from oslo_utils import timeutils from oslo_utils import timeutils
@ -77,51 +76,30 @@ def _safe_wrapper(f, kind, func_name):
return func return func
def _Event(): class _Event(object):
if eventletutils.is_monkey_patched('thread'): """A class that provides consistent eventlet/threading Event API.
return _ThreadingEvent()
else:
return _GreenEvent()
It's a copy from the oslo_utils repository, as we need the private version
class _ThreadingEvent(object): because we don't want to use the threading.Event version.
def __init__(self): """
self._abort = threading.Event() def __init__(self, *args, **kwargs):
self.clear()
def is_running(self):
return not self._abort.is_set()
def clear(self): def clear(self):
self._abort.clear() self._set = False
self._event = event.Event()
def wait(self, timeout): def is_set(self):
self._abort.wait(timeout) return self._set
def stop(self): def set(self):
self._abort.set() self._set = True
self._event.send(True)
def done(self): def wait(self, timeout=None):
pass with eventlettimeout.Timeout(timeout, False):
self._event.wait()
return self.is_set()
class _GreenEvent(object):
def __init__(self):
self._running = False
def is_running(self):
return self._running
def clear(self):
self._running = True
def wait(self, timeout):
greenthread.sleep(timeout)
def stop(self):
self._running = False
def done(self):
self._running = False
class LoopingCallBase(object): class LoopingCallBase(object):
@ -136,24 +114,23 @@ class LoopingCallBase(object):
self.f = f self.f = f
self._thread = None self._thread = None
self.done = None self.done = None
self._event = _Event() self._abort = _Event()
@property @property
def _running(self): def _running(self):
return self._event.is_running() return not self._abort.is_set()
def stop(self): def stop(self):
self._event.stop() self._abort.set()
def wait(self): def wait(self):
return self.done.wait() return self.done.wait()
def _on_done(self, gt, *args, **kwargs): def _on_done(self, gt, *args, **kwargs):
self._thread = None self._thread = None
self._event.done()
def _sleep(self, timeout): def _sleep(self, timeout):
self._event.wait(timeout) self._abort.wait(timeout)
def _start(self, idle_for, initial_delay=None, stop_on_exception=True): def _start(self, idle_for, initial_delay=None, stop_on_exception=True):
"""Start the looping """Start the looping
@ -171,7 +148,7 @@ class LoopingCallBase(object):
if self._thread is not None: if self._thread is not None:
raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE) raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)
self.done = event.Event() self.done = event.Event()
self._event.clear() self._abort.clear()
self._thread = greenthread.spawn( self._thread = greenthread.spawn(
self._run_loop, idle_for, self._run_loop, idle_for,
initial_delay=initial_delay, stop_on_exception=stop_on_exception) initial_delay=initial_delay, stop_on_exception=stop_on_exception)

View File

@ -20,9 +20,6 @@ from oslotest import base as test_base
import oslo_service import oslo_service
from oslo_service import loopingcall from oslo_service import loopingcall
threading = eventlet.patcher.original('threading')
time = eventlet.patcher.original('time')
class LoopingCallTestCase(test_base.BaseTestCase): class LoopingCallTestCase(test_base.BaseTestCase):