def set(self): """Set the internal flag to true. All greenlets waiting for it to become true are awakened. Greenlets that call :meth:`wait` once the flag is true will not block at all. """ self._flag = True if self._links: # schedule a job to notify the links already set core.active_event(self._notify_links, list(self._links))
def spawn_raw(function, *args, **kwargs): if kwargs: g = greenlet(_switch_helper, get_hub()) core.active_event(g.switch, function, args, kwargs) return g else: g = greenlet(function, get_hub()) core.active_event(g.switch, *args) return g
def kill(greenlet, exception=GreenletExit): """Kill greenlet asynchronously. The current greenlet is not unscheduled. Note, that :meth:`gevent.Greenlet.kill` method does the same and more. However, MAIN greenlet - the one that exists initially - does not have ``kill()`` method so you have to use this function. """ if not greenlet.dead: core.active_event(greenlet.throw, exception)
def killall(greenlets, exception=GreenletExit, block=True, polling_period=0.2): """Kill all the greenlets with exception (GreenletExit by default). Wait for them to die if block is true. """ waiter = Waiter() core.active_event(_killall, greenlets, exception, waiter) if block: alive = waiter.wait() if alive: joinall(alive, polling_period=polling_period)
def kill(greenlet, exception=GreenletExit, block=True, polling_period=0.2): """Kill greenlet with exception (GreenletExit by default). Wait for it to die if block is true. """ if not greenlet.dead: waiter = Waiter() core.active_event(_kill, greenlet, exception, waiter) if block: waiter.wait() join(greenlet, polling_period=polling_period)
def rawlink(self, callback): """Register a callback to call when the internal flag is set to true. *callback* will be called in the :class:`Hub <gevent.hub.Hub>`, so it must not use blocking gevent API. *callback* will be passed one argument: this instance. """ if not callable(callback): raise TypeError('Expected callable: %r' % (callback, )) self._links.append(callback) if self._flag: core.active_event(self._notify_links, list(self._links)) # XXX just pass [callback]
def test_put_nowait_simple(self): result = [] q = queue.Queue(1) def store_result(func, *args): result.append(func(*args)) core.active_event(store_result, util.wrap_errors(Exception, q.put_nowait), 2) core.active_event(store_result, util.wrap_errors(Exception, q.put_nowait), 3) gevent.sleep(0) assert len(result) == 2, result assert result[0] == None, result assert isinstance(result[1], queue.Full), result
def kill(self, exception=GreenletExit, block=False, timeout=None): """Raise the exception in the greenlet. If block is ``False`` (the default), the current greenlet is not unscheduled. If block is ``True``, wait until the greenlet dies or the optional timeout expires. Return ``None``. """ if not self.dead: waiter = Waiter() core.active_event(_kill, self, exception, waiter) if block: waiter.wait() self.join(timeout)
def killall(greenlets, exception=GreenletExit, block=False, timeout=None): if block: waiter = Waiter() core.active_event(_killall3, greenlets, exception, waiter) if block: t = Timeout.start_new(timeout) try: alive = waiter.wait() if alive: joinall(alive, raise_error=False) finally: t.cancel() else: core.active_event(_killall, greenlets, exception)
def throw(self, *args): """Immediatelly switch into the greenlet and raise an exception in it. Should only be called from the HUB, otherwise the current greenlet is left unscheduled forever. To raise an exception in a safely manner from any greenlet, use :meth:`kill`. """ if self._start_event is not None: self._start_event.cancel() self._start_event = None if not self.dead: if self: return greenlet.throw(self, *args) else: # special case for when greenlet is not yet started, because _report_error is not executed if len(args)==1: self._exception = args[0] elif not args: self._exception = GreenletExit() else: self._exception = args[1] try: try: # Even though the greenlet is not yet started, we calling throw() here # so that its 'dead' attribute becomes True return greenlet.throw(self, *args) except: # since this function is called from the Hub, which is the parent of *greenlet* # the above statement will re-reraise here whatever we've thrown in it # this traceback is useless, so we silent it pass finally: if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def set_exception(self, exception): """Store the exception. Wake up the waiters. All greenlets blocking on :meth:`get` or :meth:`wait` are woken up. Sequential calls to :meth:`wait` and :meth:`get` will not block at all. """ self._exception = exception if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def kill(self, exception=GreenletExit, block=True, timeout=None): """Raise the exception in the greenlet. If block is ``True`` (the default), wait until the greenlet dies or the optional timeout expires. If block is ``False``, the current greenlet is not unscheduled. The function always returns ``None`` and never raises an error. `Changed in version 0.13.0:` *block* is now ``True`` by default. """ if self._start_event is not None: self._start_event.cancel() self._start_event = None if not self.dead: waiter = Waiter() core.active_event(_kill, self, exception, waiter) if block: waiter.get() self.join(timeout)
def _report_error(self, exc_info): self._exc_info = exc_info exception = exc_info[1] if isinstance(exception, GreenletExit): self._report_result(exception) return self._exception = exception if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def rawlink(self, callback): """Register a callable to be executed when the greenlet finishes the execution. WARNING: the callable will be called in the HUB greenlet. """ if not callable(callback): raise TypeError('Expected callable: %r' % (callback, )) self._links.add(callback) if self.ready() and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def rawlink(self, callback): """Register a callback to call when a value or an exception is set. *callback* will be called in the :class:`Hub <gevent.hub.Hub>`, so it must not use blocking gevent API. *callback* will be passed one argument: this instance. """ if not callable(callback): raise TypeError('Expected callable: %r' % (callback, )) self._links.add(callback) if self.ready() and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def test_put_nowait_unlock(self): result = [] q = queue.Queue(0) p = gevent.spawn(q.get) def store_result(func, *args): result.append(func(*args)) assert q.empty(), q assert q.full(), q gevent.sleep(0) assert q.empty(), q assert q.full(), q core.active_event(store_result, util.wrap_errors(Exception, q.put_nowait), 10) assert not p.ready(), p gevent.sleep(0) assert result == [None], result assert p.ready(), p assert q.full(), q assert q.empty(), q
def rawlink(self, callback): """Register a callback to call when a counter is more than zero. *callback* will be called in the :class:`Hub <gevent.hub.Hub>`, so it must not use blocking gevent API. *callback* will be passed one argument: this instance. """ if not callable(callback): raise TypeError('Expected callable: %r' % (callback, )) self._links.append(callback) if self.counter > 0 and self._notifier is None: self._notifier = active_event(self._notify_links, list(self._links))
def _report_error(self, exc_info): try: if exc_info[0] is not None: traceback.print_exception(*exc_info) finally: self._exception = exc_info[1] if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links) info = str(self) + ' failed with ' try: info += self._exception.__class__.__name__ except Exception: info += str(self._exception) or repr(self._exception) sys.stderr.write(info + '\n\n')
def _report_error(self, exc_info): exception = exc_info[1] if isinstance(exception, GreenletExit): self._report_result(exception) return try: traceback.print_exception(*exc_info) except: pass self._exception = exception if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links) info = str(self) + ' failed with ' try: info += self._exception.__class__.__name__ except Exception: info += str(self._exception) or repr(self._exception) sys.stderr.write(info + '\n\n')
def _wrap_signal_handler(handler, args, kwargs): try: handler(*args, **kwargs) except: core.active_event(MAIN.throw, *sys.exc_info())
def start(self): """Schedule the greenlet to run in this loop iteration""" assert self._start_event is None, 'Greenlet already started' self._start_event = core.active_event(self.switch)
def _schedule_unlock(self): if self._event_unlock is None: self._event_unlock = core.active_event(self._unlock)
def cancel_wait(event): core.active_event(__cancel_wait, event)
def release(self): self.counter += 1 if self._links and self.counter > 0 and self._notifier is None: self._notifier = active_event(self._notify_links, list(self._links))
def release(self, blocking=True): # `blocking' parameter is for consistency with BoundedSemaphore and is ignored self.counter += 1 if self._waiters and self.counter > 0: active_event(self._do_acquire) return True
def _report_result(self, result): self._exception = None self.value = result if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links)