# Path: guv/hubs/hub.py
# def get_hub():
#     """Get the current event hub singleton object
# 
#     .. note :: |internal|
#     """
#     try:
#         hub = _threadlocal.hub
#     except AttributeError:
#         # instantiate a Hub
#         try:
#             _threadlocal.Hub
#         except AttributeError:
#             use_hub()
# 
#         hub = _threadlocal.hub = _threadlocal.Hub()
#     return hub
# 
# Path: guv/timeout.py
# class Timeout(BaseException):
#     """Raise `exception` in the current greenthread after `timeout` seconds.
# 
#     When `exception` is omitted or ``None``, the :class:`Timeout` instance itself is raised. If
#     `seconds` is None, the timer is not scheduled, and is only useful if you're planning to raise it
#     directly.
# 
#     Timeout objects are context managers, and so can be used in with statements. When used in a with
#     statement, if `exception` is ``False``, the timeout is still raised, but the context manager
#     suppresses it, so the code outside the with-block won't see it.
#     """
# 
#     def __init__(self, seconds=None, exception=None):
#         """
#         :param float seconds: timeout seconds
#         :param exception: exception to raise when timeout occurs
#         """
#         self.seconds = seconds
#         self.exception = exception
#         self.timer = None
#         self.start()
# 
#     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
# 
#     @property
#     def pending(self):
#         """True if the timeout is scheduled to be raised
#         """
#         if self.timer is not None:
#             return self.timer.pending
#         else:
#             return False
# 
#     def cancel(self):
#         """If the timeout is pending, cancel it
# 
#         If not using Timeouts in ``with`` statements, always call cancel() in a ``finally`` after
#         the block of code that is getting timed out. If not canceled, the timeout will be raised
#         later on, in some unexpected section of the application.
#         """
#         if self.timer is not None:
#             self.timer.cancel()
#             self.timer = None
# 
#     def __repr__(self):
#         classname = self.__class__.__name__
#         if self.pending:
#             pending = ' pending'
#         else:
#             pending = ''
#         if self.exception is None:
#             exception = ''
#         else:
#             exception = ' exception=%r' % self.exception
#         return '<%s at %s seconds=%s%s%s>' % (
#             classname, hex(id(self)), self.seconds, exception, pending)
# 
#     def __str__(self):
#         if self.seconds is None:
#             return ''
#         if self.seconds == 1:
#             suffix = ''
#         else:
#             suffix = 's'
#         if self.exception is None or self.exception is True:
#             return '%s second%s' % (self.seconds, suffix)
#         elif self.exception is False:
#             return '%s second%s (silent)' % (self.seconds, suffix)
#         else:
#             return '%s second%s (%s)' % (self.seconds, suffix, self.exception)
# 
#     def __enter__(self):
#         if self.timer is None:
#             self.start()
#         return self
# 
#     def __exit__(self, typ, value, tb):
#         self.cancel()
#         if value is self and self.exception is False:
#             return True


import greenlet
from .hub import get_hub
from ..timeout import Timeout
    """
    current = greenlet.getcurrent()
    hub = get_hub()
    if switch_back:
        hub.schedule_call_now(current.switch)
    hub.switch()


def trampoline(fd, evtype, timeout=None, timeout_exc=Timeout):
    """Jump from the current greenlet to the hub and wait until the given file descriptor is ready
    for I/O, or the specified timeout elapses

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

    When the specified file descriptor is ready for I/O, the hub internally calls the callback to
    switch back to the current (this) greenlet.

    Conditions:

    - must not be called from the hub greenlet (can be called from any other greenlet)
    - `evtype` must be either :attr:`~guv.const.READ` or :attr:`~guv.const.WRITE` (not possible to
      watch for  both  simultaneously)

    :param int fd: file descriptor
    :param int evtype: either the constant :attr:`~guv.const.READ` or :attr:`~guv.const.WRITE`
    :param float timeout: (optional) maximum time to wait in seconds
    :param Exception timeout_exc: (optional) timeout Exception class
    """
    #: :type: AbstractHub

# Path: guv/hubs/hub.py
# def get_hub():
#     """Get the current event hub singleton object
# 
#     .. note :: |internal|
#     """
#     try:
#         hub = _threadlocal.hub
#     except AttributeError:
#         # instantiate a Hub
#         try:
#             _threadlocal.Hub
#         except AttributeError:
#             use_hub()
# 
#         hub = _threadlocal.hub = _threadlocal.Hub()
#     return hub
# 
# Path: guv/timeout.py
# class Timeout(BaseException):
#     """Raise `exception` in the current greenthread after `timeout` seconds.
# 
#     When `exception` is omitted or ``None``, the :class:`Timeout` instance itself is raised. If
#     `seconds` is None, the timer is not scheduled, and is only useful if you're planning to raise it
#     directly.
# 
#     Timeout objects are context managers, and so can be used in with statements. When used in a with
#     statement, if `exception` is ``False``, the timeout is still raised, but the context manager
#     suppresses it, so the code outside the with-block won't see it.
#     """
# 
#     def __init__(self, seconds=None, exception=None):
#         """
#         :param float seconds: timeout seconds
#         :param exception: exception to raise when timeout occurs
#         """
#         self.seconds = seconds
#         self.exception = exception
#         self.timer = None
#         self.start()
# 
#     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
# 
#     @property
#     def pending(self):
#         """True if the timeout is scheduled to be raised
#         """
#         if self.timer is not None:
#             return self.timer.pending
#         else:
#             return False
# 
#     def cancel(self):
#         """If the timeout is pending, cancel it
# 
#         If not using Timeouts in ``with`` statements, always call cancel() in a ``finally`` after
#         the block of code that is getting timed out. If not canceled, the timeout will be raised
#         later on, in some unexpected section of the application.
#         """
#         if self.timer is not None:
#             self.timer.cancel()
#             self.timer = None
# 
#     def __repr__(self):
#         classname = self.__class__.__name__
#         if self.pending:
#             pending = ' pending'
#         else:
#             pending = ''
#         if self.exception is None:
#             exception = ''
#         else:
#             exception = ' exception=%r' % self.exception
#         return '<%s at %s seconds=%s%s%s>' % (
#             classname, hex(id(self)), self.seconds, exception, pending)
# 
#     def __str__(self):
#         if self.seconds is None:
#             return ''
#         if self.seconds == 1:
#             suffix = ''
#         else:
#             suffix = 's'
#         if self.exception is None or self.exception is True:
#             return '%s second%s' % (self.seconds, suffix)
#         elif self.exception is False:
#             return '%s second%s (silent)' % (self.seconds, suffix)
#         else:
#             return '%s second%s (%s)' % (self.seconds, suffix, self.exception)
# 
#     def __enter__(self):
#         if self.timer is None:
#             self.start()
#         return self
# 
#     def __exit__(self, typ, value, tb):
#         self.cancel()
#         if value is self and self.exception is False:
#             return True


# Path: guv/hubs/switch.py
import greenlet
from .hub import get_hub
from ..timeout import Timeout

    """
    current = greenlet.getcurrent()
    hub = get_hub()
    if switch_back:
        hub.schedule_call_now(current.switch)
    hub.switch()


def trampoline(fd, evtype, timeout=None, timeout_exc=Timeout):
    """Jump from the current greenlet to the hub and wait until the given file descriptor is ready
    for I/O, or the specified timeout elapses

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

    When the specified file descriptor is ready for I/O, the hub internally calls the callback to
    switch back to the current (this) greenlet.

    Conditions:

    - must not be called from the hub greenlet (can be called from any other greenlet)
    - `evtype` must be either :attr:`~guv.const.READ` or :attr:`~guv.const.WRITE` (not possible to
      watch for  both  simultaneously)

    :param int fd: file descriptor
    :param int evtype: either the constant :attr:`~guv.const.READ` or :attr:`~guv.const.WRITE`
    :param float timeout: (optional) maximum time to wait in seconds
    :param Exception timeout_exc: (optional) timeout Exception class
    """
    #: :type: AbstractHub

    hub = get_hub()