diff options
author | Zane Bitter <zbitter@redhat.com> | 2019-01-25 09:25:06 +1300 |
---|---|---|
committer | Zane Bitter <zbitter@redhat.com> | 2019-01-25 14:56:57 +1300 |
commit | c5b065c3e4ffe76a3e8eb3b9668a38fd2c16f3a5 (patch) | |
tree | 1f939eb040bf781aec90ba2ad3254b6704d80682 | |
parent | 4eb61941f811a8ab96745a5ea07e6a4a89fe764c (diff) | |
download | oslo-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.py | 10 | ||||
-rw-r--r-- | oslo_utils/tests/test_eventletutils.py | 24 |
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() |