def hub_exceptions(state=True): """Toggles whether the hub prints exceptions that are raised from its timers. This can be useful to see how greenthreads are terminating. """ from guv import hubs hubs.get_hub().set_timer_exceptions(state) from guv import greenpool greenpool.DEBUG = state
def hub_listener_stacks(state=False): """Toggles whether or not the hub records the stack when clients register listeners on file descriptors. This can be useful when trying to figure out what the hub is up to at any given moment. To inspect the stacks of the current listeners, call :func:`format_hub_listeners` at critical junctures in the application logic. """ from guv import hubs hubs.get_hub().set_debug_listeners(state)
def wait(self): """Wait until switch() or throw() is called. """ assert self.greenlet is None, 'This Waiter is already used by %r' % (self.greenlet, ) self.greenlet = greenlet.getcurrent() try: return get_hub().switch() finally: self.greenlet = None
def wait(self): """Wait until switch() or throw() is called. """ assert self.greenlet is None, 'This Waiter is already used by %r' % ( self.greenlet, ) self.greenlet = greenlet.getcurrent() try: return get_hub().switch() finally: self.greenlet = None
def throw(self, *throw_args): """Make greenlet calling wait() wake up (if there is a wait()). Can only be called from Hub's greenlet. """ assert greenlet.getcurrent() is get_hub(), "Can only use Waiter.switch method from the " \ "mainloop" if self.greenlet is not None: try: self.greenlet.throw(*throw_args) except: traceback.print_exc()
def switch(self, value=None): """Wake up the greenlet that is calling wait() currently (if there is one). Can only be called from Hub's greenlet. """ assert greenlet.getcurrent() is get_hub(), "Can only use Waiter.switch method from the " \ "mainloop" if self.greenlet is not None: try: self.greenlet.switch(value) except: traceback.print_exc()
def format_hub_timers(): """ Returns a formatted string of the current timers on the current hub. This can be useful in determining what's going on in the event system, especially when used in conjunction with :func:`hub_timer_stacks`. """ from guv import hubs hub = hubs.get_hub() result = ['TIMERS:'] for l in hub.timers: result.append(repr(l)) return os.linesep.join(result)
def hub_blocking_detection(state=False, resolution=1): """Toggles whether Eventlet makes an effort to detect blocking behavior in an application. It does this by telling the kernel to raise a SIGALARM after a short timeout, and clearing the timeout every time the hub greenlet is resumed. Therefore, any code that runs for a long time without yielding to the hub will get interrupted by the blocking detector (don't use it in production!). The *resolution* argument governs how long the SIGALARM timeout waits in seconds. The implementation uses :func:`signal.setitimer` and can be specified as a floating-point value. The shorter the resolution, the greater the chance of false positives. """ from guv import hubs assert resolution > 0 hubs.get_hub().debug_blocking = state hubs.get_hub().debug_blocking_resolution = resolution if not state: hubs.get_hub().block_detect_post()
def put(self, item, block=True, timeout=None): """Put an item into the queue. If optional arg `block` is true and `timeout` is ``None`` (the default), block if necessary until a free slot is available. If `timeout` is a positive number, it blocks at most `timeout` seconds and raises the :class:`queue.Full` exception if no free slot was available within that time. Otherwise (`block` is false), put an item on the queue if a free slot is immediately available, else raise the :class:`queue.Full` exception (`timeout` is ignored in that case). """ if self.maxsize is None or self.qsize() < self.maxsize: # there's a free slot, put an item right away self._put(item) if self.getters: self._schedule_unlock() elif not block and get_hub() is greenlet.getcurrent(): # we're in the mainloop, so we cannot wait; we can switch() to other greenlets though # find a getter and deliver an item to it while self.getters: getter = self.getters.pop() if getter: self._put(item) item = self._get() getter.switch(item) return raise Full elif block: waiter = ItemWaiter(item) self.putters.add(waiter) timeout = Timeout(timeout, Full) try: if self.getters: self._schedule_unlock() result = waiter.wait() assert result is waiter, "Invalid switch into Queue.put: %r" % ( result, ) if waiter.item is not _NONE: self._put(item) finally: timeout.cancel() self.putters.discard(waiter) else: raise Full
def put(self, item, block=True, timeout=None): """Put an item into the queue. If optional arg `block` is true and `timeout` is ``None`` (the default), block if necessary until a free slot is available. If `timeout` is a positive number, it blocks at most `timeout` seconds and raises the :class:`queue.Full` exception if no free slot was available within that time. Otherwise (`block` is false), put an item on the queue if a free slot is immediately available, else raise the :class:`queue.Full` exception (`timeout` is ignored in that case). """ if self.maxsize is None or self.qsize() < self.maxsize: # there's a free slot, put an item right away self._put(item) if self.getters: self._schedule_unlock() elif not block and get_hub() is greenlet.getcurrent(): # we're in the mainloop, so we cannot wait; we can switch() to other greenlets though # find a getter and deliver an item to it while self.getters: getter = self.getters.pop() if getter: self._put(item) item = self._get() getter.switch(item) return raise Full elif block: waiter = ItemWaiter(item) self.putters.add(waiter) timeout = Timeout(timeout, Full) try: if self.getters: self._schedule_unlock() result = waiter.wait() assert result is waiter, "Invalid switch into Queue.put: %r" % (result, ) if waiter.item is not _NONE: self._put(item) finally: timeout.cancel() self.putters.discard(waiter) else: raise Full
def get(self, block=True, timeout=None): """Remove and return an item from the queue. If optional args `block` is true and `timeout` is ``None`` (the default), block if necessary until an item is available. If `timeout` is a positive number, it blocks at most `timeout` seconds and raises the :class:`queue.Empty` exception if no item was available within that time. Otherwise (`block` is false), return an item if one is immediately available, else raise the :class:`queue.Empty` exception (`timeout` is ignored in that case). """ if self.qsize(): if self.putters: self._schedule_unlock() return self._get() elif not block and get_hub() is greenlet.getcurrent(): # special case to make get_nowait() runnable in the mainloop greenlet # there are no items in the queue; try to fix the situation by unlocking putters while self.putters: putter = self.putters.pop() if putter: putter.switch(putter) if self.qsize(): return self._get() raise Empty elif block: waiter = Waiter() timeout = Timeout(timeout, Empty) try: self.getters.add(waiter) if self.putters: self._schedule_unlock() return waiter.wait() finally: self.getters.discard(waiter) timeout.cancel() else: raise Empty
def _schedule_unlock(self): if self._event_unlock is None: # self._event_unlock = get_hub().schedule_call_global(0, self._unlock) self._event_unlock = get_hub().schedule_call_now(self._unlock)