Threads
*******

Eventlet is thread-safe and can be used in conjunction with normal
Python threads.  The way this works is that coroutines are confined to
their 'parent' Python thread.  It's like each thread contains its own
little world of coroutines that can switch between themselves but not
between coroutines in other threads.

[image]

You can only communicate cross-thread using the "real" thread
primitives and pipes.  Fortunately, there's little reason to use
threads for concurrency when you're already using coroutines.

The vast majority of the times you'll want to use threads are to wrap
some operation that is not "green", such as a C library that uses its
own OS calls to do socket operations.  The "tpool" module is provided
to make these uses simpler.


Tpool - Simple thread pool
==========================

The simplest thing to do with "tpool" is to "execute()" a function
with it.  The function will be run in a random thread in the pool,
while the calling coroutine blocks on its completion:

   >>> import thread
   >>> from eventlet import tpool
   >>> def my_func(starting_ident):
   ...     print("running in new thread:", starting_ident != thread.get_ident())
   ...
   >>> tpool.execute(my_func, thread.get_ident())
   running in new thread: True

By default there are 20 threads in the pool, but you can configure
this by setting the environment variable "EVENTLET_THREADPOOL_SIZE" to
the desired pool size before importing tpool.

class eventlet.tpool.Proxy(obj, autowrap=(), autowrap_names=())

   a simple proxy-wrapper of any object that comes with a methods-only
   interface, in order to forward every method invocation onto a
   thread in the native-thread pool.  A key restriction is that the
   object's methods should not switch greenlets or use Eventlet
   primitives, since they are in a different thread from the main hub,
   and therefore might behave unexpectedly.  This is for running
   native-threaded code only.

   It's common to want to have some of the attributes or return values
   also wrapped in Proxy objects (for example, database connection
   objects produce cursor objects which also should be wrapped in
   Proxy objects to remain nonblocking).  *autowrap*, if supplied, is
   a collection of types; if an attribute or return value matches one
   of those types (via isinstance), it will be wrapped in a Proxy.
   *autowrap_names* is a collection of strings, which represent the
   names of attributes that should be wrapped in Proxy objects when
   accessed.

eventlet.tpool.execute(meth, *args, **kwargs)

   Execute *meth* in a Python thread, blocking the current coroutine/
   greenthread until the method completes.

   The primary use case for this is to wrap an object or module that
   is not amenable to monkeypatching or any of the other tricks that
   Eventlet uses to achieve cooperative yielding.  With tpool, you can
   force such objects to cooperate with green threads by sticking them
   in native threads, at the cost of some overhead.
