1# Copyright (c) 2009-2016 Denis Bilenko, gevent contributors. See LICENSE for details. 2# cython: auto_pickle=False,embedsignature=True,always_allow_keywords=False,infer_types=True 3 4"""Basic synchronization primitives: Event and AsyncResult""" 5from __future__ import print_function 6 7from gevent._util import _NONE 8from gevent._compat import reraise 9from gevent._tblib import dump_traceback, load_traceback 10 11from gevent.timeout import Timeout 12 13 14__all__ = [ 15 'Event', 16 'AsyncResult', 17] 18 19def _get_linkable(): 20 x = __import__('gevent._abstract_linkable') 21 return x._abstract_linkable.AbstractLinkable 22locals()['AbstractLinkable'] = _get_linkable() 23del _get_linkable 24 25 26class Event(AbstractLinkable): # pylint:disable=undefined-variable 27 """ 28 A synchronization primitive that allows one greenlet to wake up 29 one or more others. It has the same interface as 30 :class:`threading.Event` but works across greenlets. 31 32 .. important:: 33 This object is for communicating among greenlets within the 34 same thread *only*! Do not try to use it to communicate across threads. 35 36 An event object manages an internal flag that can be set to true 37 with the :meth:`set` method and reset to false with the 38 :meth:`clear` method. The :meth:`wait` method blocks until the 39 flag is true; as soon as the flag is set to true, all greenlets 40 that are currently blocked in a call to :meth:`wait` will be scheduled 41 to awaken. 42 43 Note that the flag may be cleared and set many times before 44 any individual greenlet runs; all the greenlet can know for sure is that the 45 flag was set *at least once* while it was waiting. 46 If the greenlet cares whether the flag is still 47 set, it must check with :meth:`ready` and possibly call back into 48 :meth:`wait` again. 49 50 .. note:: 51 52 The exact order and timing in which waiting greenlets are awakened is not determined. 53 54 Once the event is set, other greenlets may run before any waiting greenlets 55 are awakened. 56 57 While the code here will awaken greenlets in the order in which they 58 waited, each such greenlet that runs may in turn cause other greenlets 59 to run. 60 61 These details may change in the future. 62 63 .. versionchanged:: 1.5a3 64 65 Waiting greenlets are now awakened in 66 the order in which they waited. 67 68 .. versionchanged:: 1.5a3 69 70 The low-level ``rawlink`` method (most users won't use this) now 71 automatically unlinks waiters before calling them. 72 73 .. versionchanged:: 20.5.1 74 75 Callers to ``wait`` that find the event already set will now run 76 after any other waiters that had to block. See :issue:`1520`. 77 """ 78 79 __slots__ = ('_flag',) 80 81 def __init__(self): 82 super(Event, self).__init__() 83 self._flag = False 84 85 def __str__(self): 86 return '<%s %s _links[%s]>' % ( 87 self.__class__.__name__, 88 'set' if self._flag else 'clear', 89 self.linkcount() 90 ) 91 92 def is_set(self): 93 """Return true if and only if the internal flag is true.""" 94 return self._flag 95 96 def isSet(self): 97 # makes it a better drop-in replacement for threading.Event 98 return self._flag 99 100 def ready(self): 101 # makes it compatible with AsyncResult and Greenlet (for 102 # example in wait()) 103 return self._flag 104 105 def set(self): 106 """ 107 Set the internal flag to true. 108 109 All greenlets waiting for it to become true are awakened in 110 some order at some time in the future. Greenlets that call 111 :meth:`wait` once the flag is true will not block at all 112 (until :meth:`clear` is called). 113 """ 114 self._flag = True 115 self._check_and_notify() 116 117 def clear(self): 118 """ 119 Reset the internal flag to false. 120 121 Subsequently, threads calling :meth:`wait` will block until 122 :meth:`set` is called to set the internal flag to true again. 123 """ 124 self._flag = False 125 126 def _wait_return_value(self, waited, wait_success): 127 # To avoid the race condition outlined in http://bugs.python.org/issue13502, 128 # if we had to wait, then we need to return whether or not 129 # the condition got changed. Otherwise we simply echo 130 # the current state of the flag (which should be true) 131 if not waited: 132 flag = self._flag 133 assert flag, "if we didn't wait we should already be set" 134 return flag 135 136 return wait_success 137 138 def wait(self, timeout=None): 139 """ 140 Block until this object is :meth:`ready`. 141 142 If the internal flag is true on entry, return immediately. Otherwise, 143 block until another thread (greenlet) calls :meth:`set` to set the flag to true, 144 or until the optional *timeout* expires. 145 146 When the *timeout* argument is present and not ``None``, it should be a 147 floating point number specifying a timeout for the operation in seconds 148 (or fractions thereof). 149 150 :return: This method returns true if and only if the internal flag has been set to 151 true, either before the wait call or after the wait starts, so it will 152 always return ``True`` except if a timeout is given and the operation 153 times out. 154 155 .. versionchanged:: 1.1 156 The return value represents the flag during the elapsed wait, not 157 just after it elapses. This solves a race condition if one greenlet 158 sets and then clears the flag without switching, while other greenlets 159 are waiting. When the waiters wake up, this will return True; previously, 160 they would still wake up, but the return value would be False. This is most 161 noticeable when the *timeout* is present. 162 """ 163 return self._wait(timeout) 164 165 def _reset_internal_locks(self): # pragma: no cover 166 # for compatibility with threading.Event 167 # Exception AttributeError: AttributeError("'Event' object has no attribute '_reset_internal_locks'",) 168 # in <module 'threading' from '/usr/lib/python2.7/threading.pyc'> ignored 169 pass 170 171 172class AsyncResult(AbstractLinkable): # pylint:disable=undefined-variable 173 """ 174 A one-time event that stores a value or an exception. 175 176 Like :class:`Event` it wakes up all the waiters when :meth:`set` 177 or :meth:`set_exception` is called. Waiters may receive the passed 178 value or exception by calling :meth:`get` instead of :meth:`wait`. 179 An :class:`AsyncResult` instance cannot be reset. 180 181 .. important:: 182 This object is for communicating among greenlets within the 183 same thread *only*! Do not try to use it to communicate across threads. 184 185 To pass a value call :meth:`set`. Calls to :meth:`get` (those that 186 are currently blocking as well as those made in the future) will 187 return the value:: 188 189 >>> from gevent.event import AsyncResult 190 >>> result = AsyncResult() 191 >>> result.set(100) 192 >>> result.get() 193 100 194 195 To pass an exception call :meth:`set_exception`. This will cause 196 :meth:`get` to raise that exception:: 197 198 >>> result = AsyncResult() 199 >>> result.set_exception(RuntimeError('failure')) 200 >>> result.get() 201 Traceback (most recent call last): 202 ... 203 RuntimeError: failure 204 205 :class:`AsyncResult` implements :meth:`__call__` and thus can be 206 used as :meth:`link` target:: 207 208 >>> import gevent 209 >>> result = AsyncResult() 210 >>> gevent.spawn(lambda : 1/0).link(result) 211 >>> try: 212 ... result.get() 213 ... except ZeroDivisionError: 214 ... print('ZeroDivisionError') 215 ZeroDivisionError 216 217 .. note:: 218 219 The order and timing in which waiting greenlets are awakened is not determined. 220 As an implementation note, in gevent 1.1 and 1.0, waiting greenlets are awakened in a 221 undetermined order sometime *after* the current greenlet yields to the event loop. Other greenlets 222 (those not waiting to be awakened) may run between the current greenlet yielding and 223 the waiting greenlets being awakened. These details may change in the future. 224 225 .. versionchanged:: 1.1 226 227 The exact order in which waiting greenlets 228 are awakened is not the same as in 1.0. 229 230 .. versionchanged:: 1.1 231 232 Callbacks :meth:`linked <rawlink>` to this object are required to 233 be hashable, and duplicates are merged. 234 235 .. versionchanged:: 1.5a3 236 237 Waiting greenlets are now awakened in the order in which they 238 waited. 239 240 .. versionchanged:: 1.5a3 241 242 The low-level ``rawlink`` method 243 (most users won't use this) now automatically unlinks waiters 244 before calling them. 245 """ 246 247 __slots__ = ('_value', '_exc_info', '_imap_task_index') 248 249 def __init__(self): 250 super(AsyncResult, self).__init__() 251 self._value = _NONE 252 self._exc_info = () 253 254 @property 255 def _exception(self): 256 return self._exc_info[1] if self._exc_info else _NONE 257 258 @property 259 def value(self): 260 """ 261 Holds the value passed to :meth:`set` if :meth:`set` was called. Otherwise, 262 ``None`` 263 """ 264 return self._value if self._value is not _NONE else None 265 266 @property 267 def exc_info(self): 268 """ 269 The three-tuple of exception information if :meth:`set_exception` was called. 270 """ 271 if self._exc_info: 272 return (self._exc_info[0], self._exc_info[1], load_traceback(self._exc_info[2])) 273 return () 274 275 def __str__(self): 276 result = '<%s ' % (self.__class__.__name__, ) 277 if self.value is not None or self._exception is not _NONE: 278 result += 'value=%r ' % self.value 279 if self._exception is not None and self._exception is not _NONE: 280 result += 'exception=%r ' % self._exception 281 if self._exception is _NONE: 282 result += 'unset ' 283 return result + ' _links[%s]>' % self.linkcount() 284 285 def ready(self): 286 """Return true if and only if it holds a value or an exception""" 287 return self._exc_info or self._value is not _NONE 288 289 def successful(self): 290 """Return true if and only if it is ready and holds a value""" 291 return self._value is not _NONE 292 293 @property 294 def exception(self): 295 """Holds the exception instance passed to :meth:`set_exception` if :meth:`set_exception` was called. 296 Otherwise ``None``.""" 297 if self._exc_info: 298 return self._exc_info[1] 299 300 def set(self, value=None): 301 """Store the value and wake up any waiters. 302 303 All greenlets blocking on :meth:`get` or :meth:`wait` are awakened. 304 Subsequent calls to :meth:`wait` and :meth:`get` will not block at all. 305 """ 306 self._value = value 307 self._check_and_notify() 308 309 def set_exception(self, exception, exc_info=None): 310 """Store the exception and wake up any waiters. 311 312 All greenlets blocking on :meth:`get` or :meth:`wait` are awakened. 313 Subsequent calls to :meth:`wait` and :meth:`get` will not block at all. 314 315 :keyword tuple exc_info: If given, a standard three-tuple of type, value, :class:`traceback` 316 as returned by :func:`sys.exc_info`. This will be used when the exception 317 is re-raised to propagate the correct traceback. 318 """ 319 if exc_info: 320 self._exc_info = (exc_info[0], exc_info[1], dump_traceback(exc_info[2])) 321 else: 322 self._exc_info = (type(exception), exception, dump_traceback(None)) 323 324 self._check_and_notify() 325 326 def _raise_exception(self): 327 reraise(*self.exc_info) 328 329 def get(self, block=True, timeout=None): 330 """Return the stored value or raise the exception. 331 332 If this instance already holds a value or an exception, return or raise it immediately. 333 Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception` or 334 until the optional timeout occurs. 335 336 When the *timeout* argument is present and not ``None``, it should be a 337 floating point number specifying a timeout for the operation in seconds 338 (or fractions thereof). If the *timeout* elapses, the *Timeout* exception will 339 be raised. 340 341 :keyword bool block: If set to ``False`` and this instance is not ready, 342 immediately raise a :class:`Timeout` exception. 343 """ 344 if self._value is not _NONE: 345 return self._value 346 if self._exc_info: 347 return self._raise_exception() 348 349 if not block: 350 # Not ready and not blocking, so immediately timeout 351 raise Timeout() 352 353 self._capture_hub(True) 354 355 # Wait, raising a timeout that elapses 356 self._wait_core(timeout, ()) 357 358 # by definition we are now ready 359 return self.get(block=False) 360 361 def get_nowait(self): 362 """ 363 Return the value or raise the exception without blocking. 364 365 If this object is not yet :meth:`ready <ready>`, raise 366 :class:`gevent.Timeout` immediately. 367 """ 368 return self.get(block=False) 369 370 def _wait_return_value(self, waited, wait_success): 371 # pylint:disable=unused-argument 372 # Always return the value. Since this is a one-shot event, 373 # no race condition should reset it. 374 return self.value 375 376 def wait(self, timeout=None): 377 """Block until the instance is ready. 378 379 If this instance already holds a value, it is returned immediately. If this 380 instance already holds an exception, ``None`` is returned immediately. 381 382 Otherwise, block until another greenlet calls :meth:`set` or :meth:`set_exception` 383 (at which point either the value or ``None`` will be returned, respectively), 384 or until the optional timeout expires (at which point ``None`` will also be 385 returned). 386 387 When the *timeout* argument is present and not ``None``, it should be a 388 floating point number specifying a timeout for the operation in seconds 389 (or fractions thereof). 390 391 .. note:: If a timeout is given and expires, ``None`` will be returned 392 (no timeout exception will be raised). 393 394 """ 395 return self._wait(timeout) 396 397 # link protocol 398 def __call__(self, source): 399 if source.successful(): 400 self.set(source.value) 401 else: 402 self.set_exception(source.exception, getattr(source, 'exc_info', None)) 403 404 # Methods to make us more like concurrent.futures.Future 405 406 def result(self, timeout=None): 407 return self.get(timeout=timeout) 408 409 set_result = set 410 411 def done(self): 412 return self.ready() 413 414 # we don't support cancelling 415 416 def cancel(self): 417 return False 418 419 def cancelled(self): 420 return False 421 422 # exception is a method, we use it as a property 423 424 425from gevent._util import import_c_accel 426import_c_accel(globals(), 'gevent._event') 427