Synchronous calls from an asynchronous context
I have a use case which I'd think is really common. From an asynchronous context I want to get the result of a synchronous call. E.g., in this asynchronous method I want to access the current buffer content:
class MyPlugin:
@neovim.autocmd(..., sync=False)
def my_async_cmd(self):
# This obviously doesn't work because the function is async
code = self._vim.current.buffer[:]
Of course, I could hack together my own synchronization construct using e.g. threading.Event:
import threading
class MyPlugin:
...
def _wait_for(self, func):
event = threading.Event()
res = None
def wrapper():
nonlocal res
res = func()
event.set()
self._vim.async_call(wrapper)
event.wait()
return res
With that I could now just use code = self._wait_for(lambda: self._vim.current.buffer[:]) to get the code, but this seems really sketchy and I feel there must be an elegant pattern (which would maybe be more obvious to me if I had a firmer grasp of greenlets).
Could you point me in the right direction here? (I've also read #229 but it doesn't seem to refer to the same problem.)
the code
class MyPlugin:
@neovim.autocmd(..., sync=False)
def my_async_cmd(self):
# This obviously doesn't work because the function is async
code = self._vim.current.buffer[:]
should actually work. Using threading.Event should only be necessary for multi-threaded code. An alternative can also be to use expr='some code' as documented in http://pynvim.readthedocs.io/en/latest/usage/remote-plugins.html, to avoid extra RPC overhead, or to be sure to evaluate the expression in context of the autocmd.
@bfredl Thanks for the quick follow-up. I'm sorry, you're absolutely right. The code does indeed work.
In fact, I'm making that call from a thread. In that case, is my solution using threading.Event as good as it gets or is there a more elegant way?
import threading
class MyPlugin:
@neovim.autocmd(..., sync=False)
def my_async_cmd(self):
def func():
code = self._vim.current.buffer[:]
...
thread = threading.Thread(target=func)
thread.start()