# Path: lib/gruvi/callbacks.py
# def add_callback(obj, callback, args=()):
#     """Add a callback to an object."""
#     callbacks = obj._callbacks
#     node = Node(callback, args)
#     # Store a single callback directly in _callbacks
#     if callbacks is None:
#         obj._callbacks = node
#         return node
#     # Otherwise use a dllist.
#     if not isinstance(callbacks, dllist):
#         obj._callbacks = dllist()
#         obj._callbacks.insert(callbacks)
#         callbacks = obj._callbacks
#     callbacks.insert(node)
#     return node
# 
# def remove_callback(obj, handle):
#     """Remove a callback from an object."""
#     callbacks = obj._callbacks
#     if callbacks is handle:
#         obj._callbacks = None
#     elif isinstance(callbacks, dllist):
#         callbacks.remove(handle)
#         if not callbacks:
#             obj._callbacks = None
# 
# def walk_callbacks(obj, func, log=None):
#     """Call func(callback, args) for all callbacks and keep only those
#     callbacks for which the function returns True."""
#     callbacks = obj._callbacks
#     if isinstance(callbacks, Node):
#         node = callbacks
#         try:
#             if not func(node.data, node.extra):
#                 obj._callbacks = None
#         except Exception:
#             if log is None:
#                 log = logging.get_logger()
#             log.exception('uncaught exception in callback')
#     elif isinstance(callbacks, dllist):
#         for node in callbacks:
#             try:
#                 if func(node.data, node.extra):
#                     continue
#                 callbacks.remove(node)
#             except Exception:
#                 if log is None:
#                     log = logging.get_logger()
#                 log.exception('uncaught exception in callback')
#         if not callbacks:
#             obj._callbacks = None
# 
# Path: lib/gruvi/callbacks.py
# def has_callback(obj, handle):
#     """Return whether a callback is currently registered for an object."""
#     callbacks = obj._callbacks
#     if not callbacks:
#         return False
#     if isinstance(callbacks, Node):
#         return handle is callbacks
#     else:
#         return handle in callbacks
# 
# def clear_callbacks(obj):
#     """Remove all callbacks from an object."""
#     callbacks = obj._callbacks
#     if isinstance(callbacks, dllist):
#         # Help the garbage collector by clearing all links.
#         callbacks.clear()
#     obj._callbacks = None


import pyuv
from .callbacks import add_callback, remove_callback, walk_callbacks
from .callbacks import has_callback, clear_callbacks

    def add_callback(self, events, callback):
        """Add a new callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')
        if events & ~(READABLE|WRITABLE):
            raise ValueError('illegal event mask: {}'.format(events))
        if events & READABLE:
            self._readers += 1
        if events & WRITABLE:
            self._writers += 1
        handle = add_callback(self, callback, events)
        self._sync()
        return handle

    def remove_callback(self, handle):
        """Remove a callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')
        remove_callback(self, handle)
        if handle.extra & READABLE:
            self._readers -= 1
        if handle.extra & WRITABLE:
            self._writers -= 1
        self._sync()

    def update_callback(self, handle, events):
        """Update the event mask for a callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')

# Path: lib/gruvi/callbacks.py
# def add_callback(obj, callback, args=()):
#     """Add a callback to an object."""
#     callbacks = obj._callbacks
#     node = Node(callback, args)
#     # Store a single callback directly in _callbacks
#     if callbacks is None:
#         obj._callbacks = node
#         return node
#     # Otherwise use a dllist.
#     if not isinstance(callbacks, dllist):
#         obj._callbacks = dllist()
#         obj._callbacks.insert(callbacks)
#         callbacks = obj._callbacks
#     callbacks.insert(node)
#     return node
# 
# def remove_callback(obj, handle):
#     """Remove a callback from an object."""
#     callbacks = obj._callbacks
#     if callbacks is handle:
#         obj._callbacks = None
#     elif isinstance(callbacks, dllist):
#         callbacks.remove(handle)
#         if not callbacks:
#             obj._callbacks = None
# 
# def walk_callbacks(obj, func, log=None):
#     """Call func(callback, args) for all callbacks and keep only those
#     callbacks for which the function returns True."""
#     callbacks = obj._callbacks
#     if isinstance(callbacks, Node):
#         node = callbacks
#         try:
#             if not func(node.data, node.extra):
#                 obj._callbacks = None
#         except Exception:
#             if log is None:
#                 log = logging.get_logger()
#             log.exception('uncaught exception in callback')
#     elif isinstance(callbacks, dllist):
#         for node in callbacks:
#             try:
#                 if func(node.data, node.extra):
#                     continue
#                 callbacks.remove(node)
#             except Exception:
#                 if log is None:
#                     log = logging.get_logger()
#                 log.exception('uncaught exception in callback')
#         if not callbacks:
#             obj._callbacks = None
# 
# Path: lib/gruvi/callbacks.py
# def has_callback(obj, handle):
#     """Return whether a callback is currently registered for an object."""
#     callbacks = obj._callbacks
#     if not callbacks:
#         return False
#     if isinstance(callbacks, Node):
#         return handle is callbacks
#     else:
#         return handle in callbacks
# 
# def clear_callbacks(obj):
#     """Remove all callbacks from an object."""
#     callbacks = obj._callbacks
#     if isinstance(callbacks, dllist):
#         # Help the garbage collector by clearing all links.
#         callbacks.clear()
#     obj._callbacks = None


# Path: lib/gruvi/poll.py
import pyuv
from .callbacks import add_callback, remove_callback, walk_callbacks
from .callbacks import has_callback, clear_callbacks


    def add_callback(self, events, callback):
        """Add a new callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')
        if events & ~(READABLE|WRITABLE):
            raise ValueError('illegal event mask: {}'.format(events))
        if events & READABLE:
            self._readers += 1
        if events & WRITABLE:
            self._writers += 1
        handle = add_callback(self, callback, events)
        self._sync()
        return handle

    def remove_callback(self, handle):
        """Remove a callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')
        remove_callback(self, handle)
        if handle.extra & READABLE:
            self._readers -= 1
        if handle.extra & WRITABLE:
            self._writers -= 1
        self._sync()

    def update_callback(self, handle, events):
        """Update the event mask for a callback."""
        if self._poll is None:
            raise RuntimeError('poll instance is closed')

        if not has_callback(self, handle):