Skip to content

Commit 523d168

Browse files
committed
session: allow polling on a provided fd
1 parent 2fcfb9a commit 523d168

File tree

7 files changed

+58
-0
lines changed

7 files changed

+58
-0
lines changed

neovim/api/common.py

+4
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,10 @@ def threadsafe_call(self, fn, *args, **kwargs):
208208
"""Wrapper for Session.threadsafe_call."""
209209
self._session.threadsafe_call(fn, *args, **kwargs)
210210

211+
def poll_fd(self, fn, fd, readable=False, writable=False):
212+
"""Wrapper around `Session.poll_fd`."""
213+
return self._session.poll_fd(fn, fd, readable, writable)
214+
211215
def next_message(self):
212216
"""Wrapper for Session.next_message."""
213217
msg = self._session.next_message()

neovim/msgpack_rpc/async_session.py

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ def threadsafe_call(self, fn):
3232
"""Wrapper around `MsgpackStream.threadsafe_call`."""
3333
self._msgpack_stream.threadsafe_call(fn)
3434

35+
def poll_fd(self, fn, fd, readable, writable):
36+
"""Wrapper around `BaseEventLoop.poll_fd`."""
37+
return self._msgpack_stream.poll_fd(fn, fd, readable, writable)
38+
3539
def request(self, method, args, response_cb):
3640
"""Send a msgpack-rpc request to Nvim.
3741

neovim/msgpack_rpc/event_loop/asyncio.py

+12
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ def _stop(self):
110110
def _threadsafe_call(self, fn):
111111
self._loop.call_soon_threadsafe(fn)
112112

113+
def _poll_fd(self, fn, fd, readable, writable):
114+
if readable:
115+
self._loop.add_reader(fd, lambda: fn(fd, True, False))
116+
if writable:
117+
self._loop.add_writer(fd, lambda: fn(fd, False, True))
118+
def cancel():
119+
if readable:
120+
self._loop.remove_reader(fd)
121+
if writable:
122+
self._loop.remove_writer(fd)
123+
return cancel
124+
113125
def _setup_signals(self, signals):
114126
self._signals = list(signals)
115127
for signum in self._signals:

neovim/msgpack_rpc/event_loop/base.py

+11
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ def threadsafe_call(self, fn):
119119
"""
120120
self._threadsafe_call(fn)
121121

122+
def poll_fd(self, fn, fd, readable=False, writable=False):
123+
"""Call a function when the fd is ready for reading and/or writing. `readable` and `writeable`
124+
are boolean flags determing which condition/s/ should be polled for.
125+
126+
The calback signature is fn(fd, is_readable, is_writable)
127+
Only one callback may be registered per fd. Returns function to deactivate the callback.
128+
"""
129+
if not readable and not writable:
130+
raise ValueError("poll_fd: At least one of `readable` and `writable` must be True")
131+
return self._poll_fd(fn, fd, readable, writable)
132+
122133
def run(self, data_cb):
123134
"""Run the event loop."""
124135
if self._error:

neovim/msgpack_rpc/event_loop/uv.py

+15
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ def _on_async(self, handle):
106106
while self._callbacks:
107107
self._callbacks.popleft()()
108108

109+
def _poll_fd(self, fn, fd, readable, writable):
110+
poll = pyuv.Poll(self._loop, fd)
111+
events = 0
112+
if readable:
113+
events |= pyuv.UV_READABLE
114+
if writable:
115+
events |= pyuv.UV_WRITABLE
116+
def callback(poll_handle, evts, errorno):
117+
is_readable = evts & pyuv.UV_READABLE
118+
is_writable = evts & pyuv.UV_WRITABLE
119+
fn(fd, is_readable, is_writable)
120+
121+
poll.start(events, fn)
122+
return poll.stop
123+
109124
def _setup_signals(self, signals):
110125
self._signal_handles = []
111126

neovim/msgpack_rpc/msgpack_stream.py

+4
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ def threadsafe_call(self, fn):
3131
"""Wrapper around `BaseEventLoop.threadsafe_call`."""
3232
self._event_loop.threadsafe_call(fn)
3333

34+
def poll_fd(self, fn, fd, readable, writable):
35+
"""Wrapper around `BaseEventLoop.poll_fd`."""
36+
return self._event_loop.poll_fd(fn, fd, readable, writable)
37+
3438
def send(self, msg):
3539
"""Queue `msg` for sending to Nvim."""
3640
debug('sent %s', msg)

neovim/msgpack_rpc/session.py

+8
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ def greenlet_wrapper():
3939

4040
self._async_session.threadsafe_call(greenlet_wrapper)
4141

42+
def poll_fd(self, fn, fd, readable, writable):
43+
"""Wrapper around `AsyncSession.threadsafe_call`."""
44+
def greenlet_wrapper(fd, is_readable, is_writable):
45+
gr = greenlet.greenlet(fn)
46+
gr.switch(fd, is_readable, is_writable)
47+
48+
self._async_session.poll_fd(greenlet_wrapper, fd, readable, writable)
49+
4250
def next_message(self):
4351
"""Block until a message(request or notification) is available.
4452

0 commit comments

Comments
 (0)