Browse Source

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
Thomas Herve 6 months ago
parent
commit
c2463470f5
2 changed files with 24 additions and 50 deletions
  1. 24
    47
      oslo_service/loopingcall.py
  2. 0
    3
      oslo_service/tests/test_loopingcall.py

+ 24
- 47
oslo_service/loopingcall.py View File

@@ -17,13 +17,12 @@
17 17
 
18 18
 import random
19 19
 import sys
20
-import threading
21 20
 import time
22 21
 
23 22
 from eventlet import event
24 23
 from eventlet import greenthread
24
+from eventlet import timeout as eventlettimeout
25 25
 from oslo_log import log as logging
26
-from oslo_utils import eventletutils
27 26
 from oslo_utils import excutils
28 27
 from oslo_utils import reflection
29 28
 from oslo_utils import timeutils
@@ -77,51 +76,30 @@ def _safe_wrapper(f, kind, func_name):
77 76
     return func
78 77
 
79 78
 
80
-def _Event():
81
-    if eventletutils.is_monkey_patched('thread'):
82
-        return _ThreadingEvent()
83
-    else:
84
-        return _GreenEvent()
79
+class _Event(object):
80
+    """A class that provides consistent eventlet/threading Event API.
85 81
 
86
-
87
-class _ThreadingEvent(object):
88
-    def __init__(self):
89
-        self._abort = threading.Event()
90
-
91
-    def is_running(self):
92
-        return not self._abort.is_set()
93
-
94
-    def clear(self):
95
-        self._abort.clear()
96
-
97
-    def wait(self, timeout):
98
-        self._abort.wait(timeout)
99
-
100
-    def stop(self):
101
-        self._abort.set()
102
-
103
-    def done(self):
104
-        pass
105
-
106
-
107
-class _GreenEvent(object):
108
-    def __init__(self):
109
-        self._running = False
110
-
111
-    def is_running(self):
112
-        return self._running
82
+    It's a copy from the oslo_utils repository, as we need the private version
83
+    because we don't want to use the threading.Event version.
84
+    """
85
+    def __init__(self, *args, **kwargs):
86
+        self.clear()
113 87
 
114 88
     def clear(self):
115
-        self._running = True
89
+        self._set = False
90
+        self._event = event.Event()
116 91
 
117
-    def wait(self, timeout):
118
-        greenthread.sleep(timeout)
92
+    def is_set(self):
93
+        return self._set
119 94
 
120
-    def stop(self):
121
-        self._running = False
95
+    def set(self):
96
+        self._set = True
97
+        self._event.send(True)
122 98
 
123
-    def done(self):
124
-        self._running = False
99
+    def wait(self, timeout=None):
100
+        with eventlettimeout.Timeout(timeout, False):
101
+            self._event.wait()
102
+        return self.is_set()
125 103
 
126 104
 
127 105
 class LoopingCallBase(object):
@@ -136,24 +114,23 @@ class LoopingCallBase(object):
136 114
         self.f = f
137 115
         self._thread = None
138 116
         self.done = None
139
-        self._event = _Event()
117
+        self._abort = _Event()
140 118
 
141 119
     @property
142 120
     def _running(self):
143
-        return self._event.is_running()
121
+        return not self._abort.is_set()
144 122
 
145 123
     def stop(self):
146
-        self._event.stop()
124
+        self._abort.set()
147 125
 
148 126
     def wait(self):
149 127
         return self.done.wait()
150 128
 
151 129
     def _on_done(self, gt, *args, **kwargs):
152 130
         self._thread = None
153
-        self._event.done()
154 131
 
155 132
     def _sleep(self, timeout):
156
-        self._event.wait(timeout)
133
+        self._abort.wait(timeout)
157 134
 
158 135
     def _start(self, idle_for, initial_delay=None, stop_on_exception=True):
159 136
         """Start the looping
@@ -171,7 +148,7 @@ class LoopingCallBase(object):
171 148
         if self._thread is not None:
172 149
             raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)
173 150
         self.done = event.Event()
174
-        self._event.clear()
151
+        self._abort.clear()
175 152
         self._thread = greenthread.spawn(
176 153
             self._run_loop, idle_for,
177 154
             initial_delay=initial_delay, stop_on_exception=stop_on_exception)

+ 0
- 3
oslo_service/tests/test_loopingcall.py View File

@@ -20,9 +20,6 @@ from oslotest import base as test_base
20 20
 import oslo_service
21 21
 from oslo_service import loopingcall
22 22
 
23
-threading = eventlet.patcher.original('threading')
24
-time = eventlet.patcher.original('time')
25
-
26 23
 
27 24
 class LoopingCallTestCase(test_base.BaseTestCase):
28 25
 

Loading…
Cancel
Save