summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZane Bitter <zbitter@redhat.com>2019-01-25 09:25:06 +1300
committerZane Bitter <zbitter@redhat.com>2019-01-25 14:56:57 +1300
commitc5b065c3e4ffe76a3e8eb3b9668a38fd2c16f3a5 (patch)
tree1f939eb040bf781aec90ba2ad3254b6704d80682
parent4eb61941f811a8ab96745a5ea07e6a4a89fe764c (diff)
downloadoslo-utils-c5b065c3e4ffe76a3e8eb3b9668a38fd2c16f3a5.tar.gz
eventletutils: Optimise EventletEvent.clear()
When EventletEvent.clear() is called twice in succession without an intervening set(), there's no need to replace the underlying eventlet.event.Event object, since it has never been sent. Doing so would have woken other greenthreads waiting on the event to no particular end. When clear() is called after the event has been set(), we already did not do anything special with the existing eventlet.event.Event as we cannot call send() on it twice. We simply replace it with a new one; the code in wait() will handle the situation correctly, since it will wake up (due to the initial event having been sent) and begin waiting on the new eventlet.event.Event instead. This is consistent with the observed behaviour of threading.Event. A new unit test verifies this. Change-Id: Ibd5324926431fc760c3dd0be064324e3009cc2c2
-rw-r--r--oslo_utils/eventletutils.py10
-rw-r--r--oslo_utils/tests/test_eventletutils.py24
2 files changed, 27 insertions, 7 deletions
diff --git a/oslo_utils/eventletutils.py b/oslo_utils/eventletutils.py
index 5d3c0a6..2770de1 100644
--- a/oslo_utils/eventletutils.py
+++ b/oslo_utils/eventletutils.py
@@ -150,16 +150,12 @@ class EventletEvent(object):
"""
def __init__(self, *args, **kwargs):
super(EventletEvent, self).__init__()
- self._set = False
self.clear()
def clear(self):
- old_event = getattr(self, "_event", None)
- was_set = self._set
- self._set = False
- self._event = _eventlet.event.Event()
- if old_event is not None and not was_set:
- old_event.send(True)
+ if getattr(self, '_set', True):
+ self._set = False
+ self._event = _eventlet.event.Event()
def is_set(self):
return self._set
diff --git a/oslo_utils/tests/test_eventletutils.py b/oslo_utils/tests/test_eventletutils.py
index b6ce995..d96851c 100644
--- a/oslo_utils/tests/test_eventletutils.py
+++ b/oslo_utils/tests/test_eventletutils.py
@@ -201,6 +201,30 @@ class EventletUtilsTest(test_base.BaseTestCase):
with eventlet.timeout.Timeout(0.7):
b.wait()
+ def test_event_set_clear_timeout(self):
+ event = eventletutils.EventletEvent()
+ wakes = []
+
+ def thread_func():
+ result = event.wait(0.2)
+ wakes.append(result)
+ if len(wakes) == 1:
+ self.assertTrue(result)
+ event.clear()
+ else:
+ self.assertFalse(result)
+
+ a = greenthread.spawn(thread_func)
+ b = greenthread.spawn(thread_func)
+ eventlet.sleep(0) # start threads
+ event.set()
+
+ with eventlet.timeout.Timeout(0.3):
+ a.wait()
+ b.wait()
+ self.assertFalse(event.is_set())
+ self.assertEqual([True, False], wakes)
+
@mock.patch('oslo_utils.eventletutils._eventlet.event.Event')
def test_event_clear_already_sent(self, mock_event):
old_event = mock.Mock()