def test_explicit_hub(self): oldhub = hubs.get_hub() try: hubs.use_hub(Foo) assert isinstance(hubs.get_hub(), Foo), hubs.get_hub() finally: hubs._threadlocal.hub = oldhub
def test_cancel_proportion(self): # if fewer than half the pending timers are canceled, it should # not clean them out hub = hubs.get_hub() uncanceled_timers = [] stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(1000): # 2/3rds of new timers are uncanceled t = hubs.get_hub().schedule_call_global(60, noop) t2 = hubs.get_hub().schedule_call_global(60, noop) t3 = hubs.get_hub().schedule_call_global(60, noop) eventlet.sleep() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) uncanceled_timers.append(t2) uncanceled_timers.append(t3) # 3000 new timers, plus a few extras self.assert_less_than_equal(stimers + 3000, stimers + hub.get_timers_count()) self.assertEqual(hub.timers_canceled, 1000) for t in uncanceled_timers: t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count()) eventlet.sleep()
def add(self, greenlet, name = None): ref = weakref.ref(greenlet) self.greenlets.append((ref, name)) try: get_hub()._addManagedGreenlets(greenlet) except AttributeError: pass
def acquire(self, blocking=True): """Acquire a semaphore. When invoked without arguments: if the internal counter is larger than zero on entry, decrement it by one and return immediately. If it is zero on entry, block, waiting until some other thread has called release() to make it larger than zero. This is done with proper interlocking so that if multiple acquire() calls are blocked, release() will wake exactly one of them up. The implementation may pick one at random, so the order in which blocked threads are awakened should not be relied on. There is no return value in this case. When invoked with blocking set to true, do the same thing as when called without arguments, and return true. When invoked with blocking set to false, do not block. If a call without an argument would block, return false immediately; otherwise, do the same thing as when called without arguments, and return true.""" if not blocking and self.locked(): return False if self.counter <= 0: self._waiters.add(greenthread.getcurrent()) try: while self.counter <= 0: hubs.get_hub().switch() finally: self._waiters.discard(greenthread.getcurrent()) self.counter -= 1 return True
def killall(self): if len(self.greenlets) == 0: return t = spawn(_killall_helper, self.greenlets) try: get_hub()._addManagedGreenlets(t) except: pass
def main(): cage = d6cage.d6Cage() sa = service_a.serviceA() sb = service_b.serviceB() cage.createservice(sa, "service a") cage.createservice(sb, "service b") hubs.get_hub().switch()
def hub_exceptions(state): """Toggles whether the hub prints exceptions that are raised from its timers. This can be useful to see how greenthreads are terminating. """ from eventlet import hubs hubs.get_hub().set_timer_exceptions(state) from eventlet import greenpool greenpool.DEBUG = state
def __call__(self, *args): if not self.called: self.called = True cb, args, kw = self.tpl try: cb(*args, **kw) finally: get_hub().timer_finished(self)
def close(self): _Socket.close(self) if self._eventlet_listener is not None: hubs.get_hub().remove(self._eventlet_listener) self._eventlet_listener = None # wake any blocked threads self._eventlet_send_event.wake() self._eventlet_recv_event.wake()
def close(self, linger=None): super(Socket, self).close(linger) if self._eventlet_listener is not None: hubs.get_hub().remove(self._eventlet_listener) self.__dict__['_eventlet_listener'] = None # wake any blocked threads self._eventlet_send_event.wake() self._eventlet_recv_event.wake()
def spawn_greenlet(function, *args): """Create a new greenlet that will run ``function(*args)``. The current greenlet won't be unscheduled. Keyword arguments aren't supported (limitation of greenlet), use :func:`spawn` to work around that. """ g = api.Greenlet(function) g.parent = hubs.get_hub().greenlet hubs.get_hub().schedule_call_global(0, g.switch, *args) return g
def hub_listener_stacks(state): """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 eventlet import hubs hubs.get_hub().set_debug_listeners(state)
def test_explicit_hub(self): if getattr(hubs.get_hub(), 'uses_twisted_reactor', None): # doesn't work with twisted return oldhub = hubs.get_hub() try: hubs.use_hub(Foo) self.assert_(isinstance(hubs.get_hub(), Foo), hubs.get_hub()) finally: hubs._threadlocal.hub = oldhub
def __call__(self, *args): if not self.called: self.called = True if self.greenlet is not None and self.greenlet.dead: return cb, args, kw = self.tpl try: cb(*args, **kw) finally: get_hub().timer_finished(self)
def cancel(self): """Prevent this timer from being called. If the timer has already been called or canceled, has no effect.""" if not self.called: self.called = True get_hub().io_loop.remove_timeout(self.scheduled_time) try: del self.tpl except AttributeError: pass
def test_cancel_immediate(self): hub = hubs.get_hub() stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(2000): t = hubs.get_hub().schedule_call_global(60, noop) t.cancel() self.assert_less_than_equal(hub.timers_canceled - scanceled, hub.get_timers_count() - stimers + 1) # there should be fewer than 1000 new timers and canceled self.assert_less_than_equal(hub.get_timers_count(), 1000 + stimers) self.assert_less_than_equal(hub.timers_canceled, 1000)
def release(self, blocking=True): """Release a semaphore, incrementing the internal counter by one. When it was zero on entry and another thread is waiting for it to become larger than zero again, wake up that thread. The *blocking* argument is for consistency with CappedSemaphore and is ignored""" self.counter += 1 if self._waiters: hubs.get_hub().schedule_call_global(0, self._do_acquire) return True
def killall(procs, *throw_args, **kwargs): if not throw_args: throw_args = (ProcExit, ) wait = kwargs.pop('wait', False) if kwargs: raise TypeError('Invalid keyword argument for proc.killall(): %s' % ', '.join(kwargs.keys())) for g in procs: if not g.dead: hubs.get_hub().schedule_call_global(0, g.throw, *throw_args) if wait and api.getcurrent() is not hubs.get_hub().greenlet: api.sleep(0)
def cancel(self): """Prevent this timer from being called. If the timer has already been called or canceled, has no effect. """ if not self.called: self.called = True get_hub().timer_canceled(self) try: del self.tpl except AttributeError: pass
def start(self, start_listeners=True): self.log("Server", "info", 'starting server "%s" (%s)' % (self.name, self.procid)) # setup ipc connections blisten = self.server_config.get("broker_listen", "") for i in blisten.split(","): if i: host, _, port = i.partition(":") port = int(port) self.broker.connections.listen((host, port)) conns = self.get_config_section("connections") for k, v in conns: host, _, port = v.partition(":") port = int(port) self.broker.connections.connect((host, port), target=k) self.broker.start() # wsgi server... self.wsgi = WSGIServer(self, self.name, config=self.get_config_section("http")) dirs = self.server_config.get("static_directories", None) if dirs is not None: from drivel.contrib.fileserver import StaticFileServer self.wsgi.app = StaticFileServer(dirs.split(","), self.wsgi.app, self) # components... components = self.get_config_section("components") for name in components: self.log("Server", "info", 'adding "%s" component to %s' % (name, self.procid)) self.components[name] = components.import_(name)(self, name) # start everything listening... if start_listeners and "backdoor_port" in self.config.server: # enable backdoor console bdport = self.server_config.getint("backdoor_port") self.log("Server", "info", "enabling backdoor on port %s" % bdport) eventlet.spawn( backdoor.backdoor_server, listen(("127.0.0.1", bdport)), locals={ "server": self, "debug": debug, "exit": safe_exit(), "quit": safe_exit(), "stats": lambda: pprint.pprint(self.stats()), }, ) if start_listeners and self.server_config.getboolean("start_www", True): self.wsgi.start(listen=listen) if start_listeners: try: hubs.get_hub().switch() except KeyboardInterrupt, e: pass
def wait(self): """Wait until send or send_exception is called. Return value passed into send() or raise exception passed into send_exception(). """ assert self.greenlet is None current = api.getcurrent() assert current is not hubs.get_hub().greenlet self.greenlet = current try: return hubs.get_hub().switch() finally: self.greenlet = None
def _do_send(self, links, consult): while links: listener, link = links.pop() try: if listener in consult: try: link(self) finally: consult.pop(listener, None) except: hubs.get_hub().schedule_call_global(0, self._do_send, links, consult) raise
def _dothrow(self, gt, cgt): #print 'throwing cancel from:%s to:%s current:%s' % (gt, cgt, # greenthread.getcurrent()) if isinstance(cgt, weakref.ref): cgt = cgt() if cgt is None: return if isinstance(cgt, greenthread.GreenThread): cgt.kill(CancelOperation, None, None) else: hubs.get_hub().schedule_call_local(0, greenthread.getcurrent().switch) cgt.throw(CancelOperation())
def kill(self, *throw_args): """ Raise an exception in the greenlet. Unschedule the current greenlet so that this :class:`Proc` can handle the exception (or die). The exception can be specified with *throw_args*. By default, :class:`ProcExit` is raised. """ if not self.dead: if not throw_args: throw_args = (ProcExit, ) hubs.get_hub().schedule_call_global(0, self.greenlet.throw, *throw_args) if api.getcurrent() is not hubs.get_hub().greenlet: api.sleep(0)
def test_cancel_accumulated(self): hub = hubs.get_hub() stimers = hub.get_timers_count() scanceled = hub.timers_canceled for i in xrange(2000): t = hubs.get_hub().schedule_call_global(60, noop) eventlet.sleep() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1) t.cancel() self.assert_less_than_equal(hub.timers_canceled, hub.get_timers_count() + 1, hub.timers) # there should be fewer than 1000 new timers and canceled self.assert_less_than_equal(hub.get_timers_count(), 1000 + stimers) self.assert_less_than_equal(hub.timers_canceled, 1000)
def start(self): """Schedule the timeout. This is called on construction, so it should not be called explicitly, unless the timer has been canceled.""" assert not self.pending, \ '%r is already started; to restart it, cancel it first' % self if self.seconds is None: # "fake" timeout (never expires) self.timer = None elif self.exception is None or isinstance(self.exception, bool): # timeout that raises self self.timer = get_hub().schedule_call_global( self.seconds, greenlet.getcurrent().throw, self) else: # regular timeout with user-provided exception self.timer = get_hub().schedule_call_global( self.seconds, greenlet.getcurrent().throw, self.exception) return self
def callMethodInEventLoop(func, *args, **kwargs): if not get_hub().running or getcurrent() is get_hub().greenlet: return func(*args, **kwargs) done = Event() def wrapper(): assert getcurrent() is get_hub().greenlet try: result = func(*args, **kwargs) done.send(result) except Exception as e: done.send_exception(e) clear_sys_exc_info() QTimer.singleShot(0, wrapper) return done.wait()
def wait(self): """Wait until another coroutine calls :meth:`send`. Returns the value the other coroutine passed to :meth:`send`. >>> from eventlet import event >>> import eventlet >>> evt = event.Event() >>> def wait_on(): ... retval = evt.wait() ... print("waited for {0}".format(retval)) >>> _ = eventlet.spawn(wait_on) >>> evt.send('result') >>> eventlet.sleep(0) waited for result Returns immediately if the event has already occured. >>> evt.wait() 'result' """ current = greenlet.getcurrent() if self._result is NOT_USED: self._waiters.add(current) try: return hubs.get_hub().switch() finally: self._waiters.discard(current) if self._exc is not None: current.throw(*self._exc) return self._result
def verify_hub_empty(): from eventlet import hubs hub = hubs.get_hub() num_readers = len(hub.get_readers()) num_writers = len(hub.get_writers()) num_timers = hub.get_timers_count() assert num_readers == 0 and num_writers == 0, "Readers: %s Writers: %s" % (num_readers, num_writers)
def __init__(self, context, socket_type): super(Socket, self).__init__(context, socket_type) self.__dict__['_eventlet_send_event'] = _BlockedThread() self.__dict__['_eventlet_recv_event'] = _BlockedThread() self.__dict__['_eventlet_send_lock'] = _QueueLock() self.__dict__['_eventlet_recv_lock'] = _QueueLock() def event(fd): # Some events arrived at the zmq socket. This may mean # there's a message that can be read or there's space for # a message to be written. send_wake = self._eventlet_send_event.wake() recv_wake = self._eventlet_recv_event.wake() if not send_wake and not recv_wake: # if no waiting send or recv thread was woken up, then # force the zmq socket's events to be processed to # avoid repeated wakeups _Socket_getsockopt(self, EVENTS) hub = hubs.get_hub() self.__dict__['_eventlet_listener'] = hub.add(hub.READ, self.getsockopt(FD), event, lambda _: None, lambda: None)