Source code for uv.handles.poll

# -*- coding: utf-8 -*-

# Copyright (C) 2016, Maximilian Köhl <mail@koehlma.de>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License version 3 as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

from __future__ import absolute_import, division, print_function, unicode_literals

from .. import base, common, error, handle
from ..library import lib


[docs]class PollEvent(common.Enumeration): """ Events reported by :class:`uv.Poll` on IO events. """ READABLE = lib.UV_READABLE """ File descriptor is readable. :type: uv.PollEvent """ WRITABLE = lib.UV_WRITABLE """ File descriptor is writable. :type: uv.PollEvent """
@base.handle_callback('uv_poll_cb') def poll_callback(poll_handle, status, events): """ :type poll_handle: uv.Poll :type status: int :type events: int """ poll_handle.on_event(poll_handle, error.StatusCodes.get(status), events) @handle.HandleTypes.POLL
[docs]class Poll(handle.UVHandle): """ Poll handles are used to watch file descriptors for readability and writability. The purpose of poll handles is to enable integrating external libraries that rely on the event loop to signal them about the socket status changes. Using them for any other purpose is not recommended. Use :class:`uv.TCP`, :class:`uv.UDP`, etc. instead, which provide faster and more scalable implementations, than what can be archived with :class:`uv.Poll`, especially on Windows. It is possible that poll handles occasionally signal that a file descriptor is readable or writable even when it is not. The user should therefore always be prepared to handle `EAGAIN` or equivalent when it attempts to read from or write to the fd. It is not okay to have multiple active poll handles for the same socket, this can cause libuv to busyloop or otherwise malfunction. Do not close a file descriptor while it is being polled by an active poll handle. This can cause the handle to report an error, but it might also start polling another socket. However the fd can be safely closed immediately after :func:`uv.Poll.stop` or :func:`uv.Handle.close` has been called. .. note:: On Windows only sockets can be polled with :class:`uv.Poll` handles. On Unix any file descriptor that would be accepted by :manpage:`poll(2)` can be used. :raises uv.UVError: error while initializing the handle :param fd: file descriptor to be polled (is set to non-blocking mode) :param loop: event loop the handle should run on :param on_event: callback which should be called on IO events after the handle has been started :type fd: int :type loop: uv.Loop :type on_event: ((uv.Poll, uv.StatusCode, int) -> None) | ((Any, uv.Poll, uv.StatusCode, int) -> None) """ __slots__ = ['uv_poll', 'fd', 'on_event'] uv_handle_type = 'uv_poll_t*' uv_handle_init = lib.cross_uv_poll_init_socket def __init__(self, fd, loop=None, on_event=None): super(Poll, self).__init__(loop, (fd, )) self.uv_poll = self.base_handle.uv_object self.fd = fd """ File descriptor the handle polls on. :readonly: True :type: int """ self.on_event = on_event or common.dummy_callback """ Callback which should be called on IO events after the handle has been started. .. function:: on_event(poll_handle, status, events) :param poll_handle: handle the call originates from :param status: may indicate any errors :param events: bitmask of the triggered IO events :type poll_handle: uv.Poll :type status: uv.StatusCode :type events: int :readonly: False :type: ((uv.Poll, uv.StatusCode, int) -> None) | ((Any, uv.Poll, uv.StatusCode, int) -> None) """
[docs] def fileno(self): """ Number of the file descriptor polled on. :rtype: int """ return self.fd
[docs] def start(self, events=PollEvent.READABLE, on_event=None): """ Start polling the file descriptor for the given events. As soon as an event is detected the callback will be called with status code class:`uv.StatusCode.SUCCESS` and the triggered events. If an error happens while polling the callback gets called with status code != 0 which corresponds to a :class:`uv.StatusCode`. Calling this on a handle that is already active is fine. Doing so will update the events mask that is being polled for. :raises uv.UVError: error while starting the handle :raises uv.ClosedHandleError: handle has already been closed or is closing :param events: bitmask of events to be polled for :param on_event: callback which should be called on IO events (overrides the current callback if specified) :type events: int :type on_event: ((uv.Poll, uv.StatusCode, int) -> None) | ((Any, uv.Poll, uv.StatusCode, int) -> None) """ if self.closing: raise error.ClosedHandleError() self.on_event = on_event or self.on_event code = lib.uv_poll_start(self.uv_poll, events, poll_callback) if code != error.StatusCodes.SUCCESS: raise error.UVError(code) if events: self.set_pending() else: self.clear_pending()
[docs] def stop(self): """ Stop the handle. The callback will no longer be called. :raises uv.UVError error while stopping the handle """ if self.closing: return code = lib.uv_poll_stop(self.uv_poll) if code != error.StatusCodes.SUCCESS: raise error.UVError(code) self.clear_pending()
__call__ = start