Skip to content

Commit

Permalink
Merge pull request #135 from ratijas/futures
Browse files Browse the repository at this point in the history
Cosmetic changes in futures.rs reduce cognitive load and localize unsafe blocks.
  • Loading branch information
ratijas authored Apr 23, 2021
2 parents 9bceb2e + da57a01 commit ad28e6c
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 47 deletions.
87 changes: 42 additions & 45 deletions qmetaobject/src/future.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
use crate::connections::SignalArgArrayToTuple;
use std::future::Future;
use std::os::raw::c_void;
use std::pin::Pin;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use crate::connections::SignalArgArrayToTuple;

static QT_WAKER_VTABLE: std::task::RawWakerVTable = unsafe {
std::task::RawWakerVTable::new(
|s: *const ()| {
std::task::RawWaker::new(
cpp!([s as "Waker*"] -> *const() as "Waker*" {
s->refs++;
return s;
}),
&QT_WAKER_VTABLE,
)
},
|s: *const ()| {
cpp!([s as "Waker*"] {
s->wake();
s->deref();
})
},
|s: *const ()| {
cpp!([s as "Waker*"] {
s->wake();
})
},
|s: *const ()| {
cpp!([s as "Waker*"] {
s->deref();
})
},
)
};
static QT_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
|s: *const ()| {
RawWaker::new(
cpp!(unsafe [s as "Waker *"] -> *const() as "Waker *" {
s->refs++;
return s;
}),
&QT_WAKER_VTABLE,
)
},
|s: *const ()| {
cpp!(unsafe [s as "Waker *"] {
s->wake();
s->deref();
})
},
|s: *const ()| {
cpp!(unsafe [s as "Waker *"] {
s->wake();
})
},
|s: *const ()| {
cpp!(unsafe [s as "Waker *"] {
s->deref();
})
},
);

cpp! {{

Expand Down Expand Up @@ -61,8 +61,8 @@ cpp! {{
return;
}
completed = rust!(ProcessQtEvent [
this: *const () as "Waker*",
future: *mut dyn Future<Output=()> as "TraitObject"
this: *const () as "Waker *",
future: *mut dyn Future<Output = ()> as "TraitObject"
] -> bool as "bool" {
poll_with_qt_waker(this, Pin::new_unchecked(&mut *future))
});
Expand All @@ -89,7 +89,7 @@ cpp! {{
}

~Waker() {
rust!(QtDestroyFuture [future: *mut dyn Future<Output=()> as "TraitObject"] {
rust!(QtDestroyFuture [future: *mut dyn Future<Output = ()> as "TraitObject"] {
std::mem::drop(Box::from_raw(future))
});
}
Expand All @@ -107,7 +107,7 @@ cpp! {{
pub fn execute_async(f: impl Future<Output = ()> + 'static) {
let f: *mut dyn Future<Output = ()> = Box::into_raw(Box::new(f));
unsafe {
let waker = cpp!([f as "TraitObject"] -> *const() as "Waker*" {
let waker = cpp!([f as "TraitObject"] -> *const() as "Waker *" {
return new Waker(f);
});
poll_with_qt_waker(waker, Pin::new_unchecked(&mut *f));
Expand All @@ -116,10 +116,10 @@ pub fn execute_async(f: impl Future<Output = ()> + 'static) {

// SAFETY: caller must ensure that given future hasn't returned Poll::Ready earlier.
unsafe fn poll_with_qt_waker(waker: *const (), future: Pin<&mut dyn Future<Output = ()>>) -> bool {
cpp!([waker as "Waker*"] { waker->refs++; });
let waker = std::task::RawWaker::new(waker, &QT_WAKER_VTABLE);
let waker = std::task::Waker::from_raw(waker);
let mut context = std::task::Context::from_waker(&waker);
cpp!([waker as "Waker *"] { waker->refs++; });
let waker = RawWaker::new(waker, &QT_WAKER_VTABLE);
let waker = Waker::from_raw(waker);
let mut context = Context::from_waker(&waker);
future.poll(&mut context).is_ready()
}

Expand All @@ -139,7 +139,7 @@ pub unsafe fn wait_on_signal<Args: SignalArgArrayToTuple>(
) -> impl Future<Output = <Args as SignalArgArrayToTuple>::Tuple> {
enum ConnectionFutureState<Args: SignalArgArrayToTuple> {
Init { sender: *const c_void, signal: crate::connections::Signal<Args> },
Started { handle: crate::connections::ConnectionHandle, waker: std::task::Waker },
Started { handle: crate::connections::ConnectionHandle, waker: Waker },
Finished { result: <Args as SignalArgArrayToTuple>::Tuple },
Invalid,
}
Expand All @@ -158,14 +158,11 @@ pub unsafe fn wait_on_signal<Args: SignalArgArrayToTuple>(

impl<Args: SignalArgArrayToTuple> Future for ConnectionFuture<Args> {
type Output = <Args as SignalArgArrayToTuple>::Tuple;
fn poll(
mut self: Pin<&mut Self>,
ctx: &mut std::task::Context,
) -> std::task::Poll<Self::Output> {
fn poll(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Self::Output> {
let state = &mut self.0;
*state = match std::mem::replace(state, ConnectionFutureState::Invalid) {
ConnectionFutureState::Finished { result } => {
return std::task::Poll::Ready(result);
return Poll::Ready(result);
}
ConnectionFutureState::Init { sender, signal } => {
let s_ptr = state as *mut ConnectionFutureState<_>;
Expand All @@ -176,7 +173,7 @@ pub unsafe fn wait_on_signal<Args: SignalArgArrayToTuple>(
s @ ConnectionFutureState::Started { .. } => s,
ConnectionFutureState::Invalid => unreachable!(),
};
std::task::Poll::Pending
Poll::Pending
}
}

Expand Down
3 changes: 1 addition & 2 deletions qmetaobject/src/itemmodel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ pub trait QAbstractItemModel: QObject {
/// Refer to the Qt documentation of QAbstractListModel::layoutAboutToBeChanged
///
/// update_model_indexes need to be called between layout_about_to_be_changed and layout_changed
fn update_model_indexes(&self, f: &mut dyn FnMut(QModelIndex) -> QModelIndex)
{
fn update_model_indexes(&self, f: &mut dyn FnMut(QModelIndex) -> QModelIndex) {
let obj = self.get_cpp_object();
cpp!(unsafe [obj as "Rust_QAbstractItemModel *", f as "TraitObject"] {
if (!obj) return;
Expand Down

0 comments on commit ad28e6c

Please sign in to comment.