mirror of
https://github.com/hexedtech/codemp.git
synced 2024-12-23 05:14:54 +01:00
feat(python): summon black magic to allow possible release of the GIL between .awaits
plus nice static runtime singleton fetcher/instantiator
This commit is contained in:
parent
5acca5ce3e
commit
3fe6d224e3
2 changed files with 38 additions and 9 deletions
|
@ -16,22 +16,22 @@ impl CursorController {
|
|||
buffer: path,
|
||||
user: None,
|
||||
};
|
||||
self.send(pos).await
|
||||
super::AllowThreads(self.send(pos)).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "try_recv")]
|
||||
async fn pytry_recv(&self) -> crate::Result<Option<Cursor>> {
|
||||
self.try_recv().await
|
||||
super::AllowThreads(self.try_recv()).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "recv")]
|
||||
async fn pyrecv(&self) -> crate::Result<Cursor> {
|
||||
self.recv().await
|
||||
super::AllowThreads(self.recv()).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "poll")]
|
||||
async fn pypoll(&self) -> crate::Result<()> {
|
||||
self.poll().await
|
||||
super::AllowThreads(self.poll()).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "stop")]
|
||||
|
@ -45,7 +45,7 @@ impl CursorController {
|
|||
impl BufferController {
|
||||
#[pyo3(name = "content")]
|
||||
async fn pycontent(&self) -> crate::Result<String> {
|
||||
self.content().await
|
||||
super::AllowThreads(Box::pin(self.content())).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "send")]
|
||||
|
@ -56,22 +56,22 @@ impl BufferController {
|
|||
content: txt,
|
||||
hash: None,
|
||||
};
|
||||
self.send(op).await
|
||||
super::AllowThreads(self.send(op)).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "try_recv")]
|
||||
async fn pytry_recv(&self) -> crate::Result<Option<TextChange>> {
|
||||
self.try_recv().await
|
||||
super::AllowThreads(self.try_recv()).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "recv")]
|
||||
async fn pyrecv(&self) -> crate::Result<TextChange> {
|
||||
self.recv().await
|
||||
super::AllowThreads(self.recv()).await
|
||||
}
|
||||
|
||||
#[pyo3(name = "poll")]
|
||||
async fn pypoll(&self) -> crate::Result<()> {
|
||||
self.poll().await
|
||||
super::AllowThreads(self.poll()).await
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@ pub mod controllers;
|
|||
pub mod workspace;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
future::Future,
|
||||
pin::{pin, Pin},
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
api::{Cursor, TextChange},
|
||||
|
@ -14,6 +19,30 @@ use pyo3::exceptions::{PyConnectionError, PyRuntimeError, PySystemError};
|
|||
use pyo3::prelude::*;
|
||||
use tokio::sync::{mpsc, Mutex};
|
||||
|
||||
fn tokio() -> &'static tokio::runtime::Runtime {
|
||||
use std::sync::OnceLock;
|
||||
static RT: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
|
||||
RT.get_or_init(|| tokio::runtime::Runtime::new().unwrap())
|
||||
}
|
||||
|
||||
// workaround to allow the GIL to be released across awaits
|
||||
struct AllowThreads<F>(F);
|
||||
|
||||
impl<F> Future for AllowThreads<F>
|
||||
where
|
||||
F: Future + Unpin + Send,
|
||||
F::Output: Send,
|
||||
{
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let waker = cx.waker();
|
||||
Python::with_gil(|gil| {
|
||||
gil.allow_threads(|| pin!(&mut self.0).poll(&mut Context::from_waker(waker)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<crate::Error> for PyErr {
|
||||
fn from(value: crate::Error) -> Self {
|
||||
match value {
|
||||
|
|
Loading…
Reference in a new issue