# Understanding Eventlet Hubs

A hub forms the basis of Eventlet’s event loop, which dispatches I/O events and schedules greenthreads. It is the existence of the hub that promotes coroutines (which can be tricky to program with) into greenthreads (which are easy).

Eventlet has multiple hub implementations, and when you start using it, it tries to select the best hub implementation for your system. The hubs that it supports are (in order of preference):

asyncio
  Asyncio based hub. Run Eventlet code in an Asyncio eventloop.
  By using this hub, Asyncio and Eventlet can be run the same thread in the same process.
  We discourage new Eventlet projects.
  We encourage existing Eventlet projects to migrate from Eventlet to Asyncio.
  This hub allow you incremental and smooth migration.
  See the Migrating off of Eventlet for further details.
  See the Asyncio compatibility in eventlet for the current state of the art.
epolls

  Linux. This is the fastest hub for Linux.

kqueue

  FreeBSD and Mac OSX. Fastest hub for OS with kqueue.

poll

  On platforms that support it.

selects

  Lowest-common-denominator, available everywhere.

The only non-pure Python, pyevent hub (using libevent) was removed because it was not maintained. You are warmly welcome to contribute fast hub implementation using Cython, CFFI or other technology of your choice.

If the selected hub is not ideal for the application, another can be selected. You can make the selection either with the environment variable EVENTLET_HUB, or with `eventlet.hubs.use_hub()`.

eventlet.hubs.use_hub(hub=None)

  Use this to control which hub Eventlet selects. Call it with the name of the desired hub module. Make sure to do this before the application starts doing any I/O! Calling use_hub completely eliminates the old hub, and any file descriptors or timers that it had been managing will be forgotten. Put the call as one of the first lines in the main module.:

      """ This is the main module """
      import eventlet.hubs
      eventlet.hubs.use_hub("eventlet.hubs.epolls")

  Hubs are implemented as thread-local class instances. `eventlet.hubs.use_hub()` only operates on the current thread. When using multiple threads that each need their own hub, call `eventlet.hubs.use_hub()` at the beginning of each thread function that needs a specific hub. In practice, it may not be necessary to specify a hub in each thread; it works to use one special hub for the main thread, and let other threads use the default hub; this hybrid hub configuration will work fine.

  It is also possible to use a third-party hub module in place of one of the built-in ones. Simply pass the module itself to `eventlet.hubs.use_hub()`. The task of writing such a hub is a little beyond the scope of this document, it’s probably a good idea to simply inspect the code of the existing hubs to see how they work.:

      import eventlet.hubs
      import mypackage.myhub
      eventlet.hubs.use_hub(mypackage.myhub)

  Supplying None as the argument to `eventlet.hubs.use_hub()` causes it to select the default hub.

## How the Hubs Work

The hub has a main greenlet, MAINLOOP. When one of the running coroutines needs to do some I/O, it registers a listener with the hub (so that the hub knows when to wake it up again), and then switches to MAINLOOP (via `get_hub().switch()`). If there are other coroutines that are ready to run, MAINLOOP switches to them, and when they complete or need to do more I/O, they switch back to the MAINLOOP. In this manner, MAINLOOP ensures that every coroutine gets scheduled when it has some work to do.

MAINLOOP is launched only when the first I/O operation happens, and it is not the same greenlet that __main__ is running in. This lazy launching means that code can start using Eventlet without needing to be substantially restructured.

## More Hub-Related Functions

eventlet.hubs.get_hub()

  Get the current event hub singleton object.

  Note

  This is considered an internal API, and it might change unexpectedly without being deprecated first.

eventlet.hubs.get_default_hub()

  Select the default hub implementation based on what multiplexing libraries are installed. The order that the hubs are tried is:

  - epoll

  - kqueue

  - poll

  - select

  Note

  This is considered an internal API, and it might change unexpectedly without being deprecated first.

eventlet.hubs.trampoline(fd, read=None, write=None, timeout=None, timeout_exc=<class 'eventlet.timeout.Timeout'>, mark_as_closed=None)

  Suspend the current coroutine until the given socket object or file descriptor is ready to read, ready to write, or the specified timeout elapses, depending on arguments specified.

  To wait for fd to be ready to read, pass read `=True`; ready to write, pass write `=True`. To specify a timeout, pass the timeout argument in seconds.

  If the specified timeout elapses before the socket is ready to read or write, timeout_exc will be raised instead of `trampoline()` returning normally.

  Note

  This is considered an internal API, and it might change unexpectedly without being deprecated first.