forked from mirrors/gstreamer-rs
gstreamer/promise: Return a borrowed StructureRef for the reply from the Future
Prevents an usually unneeded copy of the structure.
This commit is contained in:
parent
9d851bfc48
commit
dbf6d1fd1a
1 changed files with 35 additions and 11 deletions
|
@ -13,6 +13,7 @@ use PromiseResult;
|
||||||
use Structure;
|
use Structure;
|
||||||
use StructureRef;
|
use StructureRef;
|
||||||
|
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
@ -89,16 +90,19 @@ impl Promise {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_future() -> (Self, PromiseFuture) {
|
pub fn new_future<'a>() -> (Self, PromiseFuture<'a>) {
|
||||||
use futures_channel::oneshot;
|
use futures_channel::oneshot;
|
||||||
|
|
||||||
|
// We only use the channel as a convenient waker
|
||||||
let (sender, receiver) = oneshot::channel();
|
let (sender, receiver) = oneshot::channel();
|
||||||
|
let promise = Self::new_with_change_func(move |_res| {
|
||||||
let promise = Self::new_with_change_func(move |res| {
|
let _ = sender.send(());
|
||||||
let _ = sender.send(res.map(|s| s.map(ToOwned::to_owned)));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(promise, PromiseFuture(receiver))
|
(
|
||||||
|
promise.clone(),
|
||||||
|
PromiseFuture(promise, receiver, PhantomData),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expire(&self) {
|
pub fn expire(&self) {
|
||||||
|
@ -148,17 +152,37 @@ unsafe impl Send for Promise {}
|
||||||
unsafe impl Sync for Promise {}
|
unsafe impl Sync for Promise {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PromiseFuture(
|
pub struct PromiseFuture<'a>(
|
||||||
futures_channel::oneshot::Receiver<Result<Option<Structure>, PromiseError>>,
|
Promise,
|
||||||
|
futures_channel::oneshot::Receiver<()>,
|
||||||
|
PhantomData<&'a StructureRef>,
|
||||||
);
|
);
|
||||||
|
|
||||||
impl std::future::Future for PromiseFuture {
|
impl<'a> std::future::Future for PromiseFuture<'a> {
|
||||||
type Output = Result<Option<Structure>, PromiseError>;
|
type Output = Result<Option<&'a StructureRef>, PromiseError>;
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
|
||||||
match Pin::new(&mut self.0).poll(context) {
|
match Pin::new(&mut self.1).poll(context) {
|
||||||
Poll::Ready(Err(_)) => panic!("Sender dropped before callback was called"),
|
Poll::Ready(Err(_)) => panic!("Sender dropped before callback was called"),
|
||||||
Poll::Ready(Ok(res)) => Poll::Ready(res),
|
Poll::Ready(Ok(())) => {
|
||||||
|
let res = match self.0.wait() {
|
||||||
|
PromiseResult::Replied => unsafe {
|
||||||
|
let s = gst_sys::gst_promise_get_reply(self.0.to_glib_none().0);
|
||||||
|
if s.is_null() {
|
||||||
|
Ok(None)
|
||||||
|
} else {
|
||||||
|
Ok(Some(StructureRef::from_glib_borrow(s)))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PromiseResult::Interrupted => Err(PromiseError::Interrupted),
|
||||||
|
PromiseResult::Expired => Err(PromiseError::Expired),
|
||||||
|
PromiseResult::Pending => {
|
||||||
|
panic!("Promise resolved but returned Pending");
|
||||||
|
}
|
||||||
|
err => Err(PromiseError::Other(err)),
|
||||||
|
};
|
||||||
|
Poll::Ready(res)
|
||||||
|
}
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue