Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to wait for POLLPRI #463

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/source/reference-hazmat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,30 @@ Unix-like systems provide the following functions:
become writable.


.. function:: wait_priority(fd)
:async:

Block until there is an "exceptional condition" on the given file
descriptor.

.. warning::

This method uses the ``POLLPRI`` flag to the ``epoll`` system call.
Its semantics are highly specific to the type of file descriptor
you're passing to it.

This test may be used to
* wait for changes to hardware inputs (Linux GPIO)
* notice changed state of a PTY slave by the master
* …

:arg fd:
integer file descriptor, or else an object with a ``fileno()`` method
:raises trio.ResourceBusyError:
if another task is already waiting for an exceptional condition on
the given fd.


Kqueue-specific API
-------------------

Expand Down
27 changes: 23 additions & 4 deletions trio/_core/_io_epoll.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@
class _EpollStatistics:
tasks_waiting_read = attr.ib()
tasks_waiting_write = attr.ib()
tasks_waiting_prio = attr.ib()
backend = attr.ib(default="epoll")


@attr.s(slots=True, cmp=False, hash=False)
class EpollWaiters:
read_task = attr.ib(default=None)
write_task = attr.ib(default=None)
prio_task = attr.ib(default=None)

def flags(self):
flags = 0
if self.read_task is not None:
flags |= select.EPOLLIN
if self.write_task is not None:
flags |= select.EPOLLOUT
if self.prio_task is not None:
flags |= select.EPOLLPRI
if not flags:
return None
# XX not sure if EPOLLEXCLUSIVE is actually safe... I think
Expand All @@ -47,14 +51,18 @@ class EpollIOManager:
def statistics(self):
tasks_waiting_read = 0
tasks_waiting_write = 0
tasks_waiting_prio = 0
for waiter in self._registered.values():
if waiter.read_task is not None:
tasks_waiting_read += 1
if waiter.write_task is not None:
tasks_waiting_write += 1
if waiter.prio_task is not None:
tasks_waiting_prio += 1
return _EpollStatistics(
tasks_waiting_read=tasks_waiting_read,
tasks_waiting_write=tasks_waiting_write,
tasks_waiting_prio=tasks_waiting_prio,
)

def close(self):
Expand All @@ -70,12 +78,19 @@ def handle_io(self, timeout):
# Clever hack stolen from selectors.EpollSelector: an event
# with EPOLLHUP or EPOLLERR flags wakes both readers and
# writers.
if flags & ~select.EPOLLIN and waiters.write_task is not None:
_core.reschedule(waiters.write_task)
waiters.write_task = None
if flags & ~select.EPOLLOUT and waiters.read_task is not None:
if flags & ~(
select.EPOLLOUT | select.EPOLLPRI
) and waiters.read_task is not None:
_core.reschedule(waiters.read_task)
waiters.read_task = None
if flags & ~(
select.EPOLLIN | select.EPOLLPRI
) and waiters.write_task is not None:
_core.reschedule(waiters.write_task)
waiters.write_task = None
if flags & select.EPOLLPRI and waiters.prio_task is not None:
_core.reschedule(waiters.prio_task)
waiters.prio_task = None
self._update_registrations(fd, True)

def _update_registrations(self, fd, currently_registered):
Expand Down Expand Up @@ -122,3 +137,7 @@ async def wait_readable(self, fd):
@_public
async def wait_writable(self, fd):
await self._epoll_wait(fd, "write_task")

@_public
async def wait_priority(self, fd):
await self._epoll_wait(fd, "prio_task")
1 change: 1 addition & 0 deletions trio/hazmat.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"add_instrument",
"current_clock",
"current_statistics",
"wait_priority",
"wait_writable",
"wait_readable",
"ParkingLot",
Expand Down