Skip to content

Commit

Permalink
threading: add support for Clone to CxxQtThread<T>
Browse files Browse the repository at this point in the history
Related to #560
  • Loading branch information
ahayzen-kdab committed Jun 9, 2023
1 parent 28f6c74 commit 4a4efd1
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 34 deletions.
10 changes: 8 additions & 2 deletions crates/cxx-qt-gen/include/cxxqt_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ class CxxQtThread
}

~CxxQtThread() = default;
// Disable copy support for now
CxxQtThread(CxxQtThread<T>& other) = delete;
CxxQtThread(const CxxQtThread<T>& other) = default;
CxxQtThread(CxxQtThread<T>&& other) = default;

template<typename A>
Expand Down Expand Up @@ -93,6 +92,13 @@ class CxxQtThread
::std::shared_ptr<::std::recursive_mutex> m_rustObjMutex;
};

template<typename T>
CxxQtThread<T>
cxxQtThreadClone(const CxxQtThread<T>& cxxQtThread)
{
return CxxQtThread<T>(cxxQtThread);
}

template<typename T>
void
cxxQtThreadDrop(CxxQtThread<T>& cxxQtThread)
Expand Down
52 changes: 24 additions & 28 deletions crates/cxx-qt-gen/src/generator/naming/qobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,14 @@ use syn::Ident;

/// Names for parts of a Q_OBJECT
pub struct QObjectName {
// Store the ident so that cxx_qt_thread_method can use it later
ident: Ident,
/// The name of the C++ class
pub cpp_class: CombinedIdent,
/// The name of the Rust struct
pub rust_struct: CombinedIdent,
/// The name of the CxxQtThread
pub cxx_qt_thread_class: Ident,
/// The name of the drop function
pub cxx_qt_thread_drop: Ident,
/// The name of the queue function
pub cxx_qt_thread_queue_fn: Ident,
/// The name of the Rust closure wrapper to be passed in to CxxQtThread
pub cxx_qt_thread_queued_fn_struct: Ident,
}
Expand All @@ -33,16 +31,25 @@ impl From<&ParsedQObject> for QObjectName {
impl From<&Ident> for QObjectName {
fn from(ident: &Ident) -> Self {
Self {
ident: ident.clone(),
cpp_class: CombinedIdent::cpp_class_from_rust_struct(ident.clone()),
rust_struct: CombinedIdent::from_rust_struct(ident.clone()),
cxx_qt_thread_class: cxx_qt_thread_class_from_ident(ident),
cxx_qt_thread_drop: cxx_qt_thread_drop_from_ident(ident),
cxx_qt_thread_queue_fn: cxx_qt_thread_queue_fn_from_ident(ident),
cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(ident),
}
}
}

impl QObjectName {
/// For a given ident generate the mangled threading suffix ident
pub fn cxx_qt_thread_method(&self, suffix: &str) -> Ident {
format_ident!(
"cxx_qt_ffi_{ident}_{suffix}",
ident = self.ident.to_string().to_case(Case::Snake)
)
}
}

/// For a given ident generate the CxxQtThread ident
fn cxx_qt_thread_class_from_ident(ident: &Ident) -> Ident {
format_ident!("{ident}CxxQtThread")
Expand All @@ -53,22 +60,6 @@ fn cxx_qt_thread_queued_fn_struct_from_ident(ident: &Ident) -> Ident {
format_ident!("{ident}CxxQtThreadQueuedFn")
}

/// For a given ident generate the mangled threading drop ident
fn cxx_qt_thread_drop_from_ident(ident: &Ident) -> Ident {
format_ident!(
"cxx_qt_ffi_{ident}_threading_drop",
ident = ident.to_string().to_case(Case::Snake)
)
}

/// For a given ident generate the mangled queue ident
fn cxx_qt_thread_queue_fn_from_ident(ident: &Ident) -> Ident {
format_ident!(
"cxx_qt_ffi_{ident}_queue_boxed_fn",
ident = ident.to_string().to_case(Case::Snake)
)
}

impl CombinedIdent {
/// For a given ident generate the C++ class name
fn cpp_class_from_rust_struct(ident: Ident) -> Self {
Expand Down Expand Up @@ -107,16 +98,21 @@ pub mod tests {
format_ident!("MyObjectCxxQtThread")
);
assert_eq!(
names.cxx_qt_thread_drop,
"cxx_qt_ffi_my_object_threading_drop"
names.cxx_qt_thread_queued_fn_struct,
format_ident!("MyObjectCxxQtThreadQueuedFn")
);

assert_eq!(
names.cxx_qt_thread_queue_fn,
"cxx_qt_ffi_my_object_queue_boxed_fn"
names.cxx_qt_thread_method("threading_clone"),
"cxx_qt_ffi_my_object_threading_clone"
);
assert_eq!(
names.cxx_qt_thread_queued_fn_struct,
format_ident!("MyObjectCxxQtThreadQueuedFn")
names.cxx_qt_thread_method("threading_drop"),
"cxx_qt_ffi_my_object_threading_drop"
);
assert_eq!(
names.cxx_qt_thread_method("queue_boxed_fn"),
"cxx_qt_ffi_my_object_queue_boxed_fn"
);
}
}
27 changes: 25 additions & 2 deletions crates/cxx-qt-gen/src/generator/rust/threading.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ pub fn generate(
let cpp_struct_ident = &qobject_ident.cpp_class.rust;
let cxx_qt_thread_ident = &qobject_ident.cxx_qt_thread_class;
let cxx_qt_thread_queued_fn_ident = &qobject_ident.cxx_qt_thread_queued_fn_struct;
let cxx_qt_thread_queue_fn = &qobject_ident.cxx_qt_thread_queue_fn;
let cxx_qt_thread_drop = &qobject_ident.cxx_qt_thread_drop;
let cxx_qt_thread_queue_fn = qobject_ident.cxx_qt_thread_method("queue_boxed_fn");
let cxx_qt_thread_clone = qobject_ident.cxx_qt_thread_method("threading_clone");
let cxx_qt_thread_drop = qobject_ident.cxx_qt_thread_method("threading_drop");
let namespace_internals = &namespace_ident.internal;
let cxx_qt_thread_ident_type_id_str =
namespace_combine_ident(&namespace_ident.namespace, cxx_qt_thread_ident);
Expand Down Expand Up @@ -60,6 +61,11 @@ pub fn generate(
arg: Box<#cxx_qt_thread_queued_fn_ident>,
) -> Result<()>;

#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadClone"]
fn #cxx_qt_thread_clone(cxx_qt_thread: &#cxx_qt_thread_ident) -> #cxx_qt_thread_ident;

#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadDrop"]
Expand Down Expand Up @@ -105,6 +111,12 @@ pub fn generate(
#cxx_qt_thread_queue_fn(cxx_qt_thread, func, std::boxed::Box::new(arg))
}

#[doc(hidden)]
fn threading_clone(cxx_qt_thread: &#cxx_qt_thread_ident) -> #cxx_qt_thread_ident
{
#cxx_qt_thread_clone(cxx_qt_thread)
}

#[doc(hidden)]
fn threading_drop(cxx_qt_thread: &mut #cxx_qt_thread_ident)
{
Expand Down Expand Up @@ -178,6 +190,11 @@ mod tests {
arg: Box<MyObjectCxxQtThreadQueuedFn>,
) -> Result<()>;

#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadClone"]
fn cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread: &MyObjectCxxQtThread) -> MyObjectCxxQtThread;

#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadDrop"]
Expand Down Expand Up @@ -229,6 +246,12 @@ mod tests {
cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg))
}

#[doc(hidden)]
fn threading_clone(cxx_qt_thread: &MyObjectCxxQtThread) -> MyObjectCxxQtThread
{
cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread)
}

#[doc(hidden)]
fn threading_drop(cxx_qt_thread: &mut MyObjectCxxQtThread)
{
Expand Down
10 changes: 10 additions & 0 deletions crates/cxx-qt-gen/test_outputs/invokables.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ mod ffi {
) -> Result<()>;
#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadClone"]
fn cxx_qt_ffi_my_object_threading_clone(
cxx_qt_thread: &MyObjectCxxQtThread,
) -> MyObjectCxxQtThread;
#[doc(hidden)]
#[namespace = "rust::cxxqtlib1"]
#[cxx_name = "cxxQtThreadDrop"]
fn cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread: &mut MyObjectCxxQtThread);
}
Expand Down Expand Up @@ -284,6 +290,10 @@ mod cxx_qt_ffi {
cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg))
}
#[doc(hidden)]
fn threading_clone(cxx_qt_thread: &MyObjectCxxQtThread) -> MyObjectCxxQtThread {
cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread)
}
#[doc(hidden)]
fn threading_drop(cxx_qt_thread: &mut MyObjectCxxQtThread) {
cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread);
}
Expand Down
9 changes: 9 additions & 0 deletions crates/cxx-qt/src/cxxqtthread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ where
type Kind = cxx::kind::Trivial;
}

impl<T> Clone for CxxQtThread<T>
where
T: Threading,
{
fn clone(&self) -> Self {
T::threading_clone(self)
}
}

impl<T> Drop for CxxQtThread<T>
where
T: Threading,
Expand Down
3 changes: 3 additions & 0 deletions crates/cxx-qt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ pub trait Threading: Sized {
F: FnOnce(core::pin::Pin<&mut Self>),
F: Send + 'static;

#[doc(hidden)]
fn threading_clone(cxx_qt_thread: &CxxQtThread<Self>) -> CxxQtThread<Self>;

#[doc(hidden)]
fn threading_drop(cxx_qt_thread: &mut CxxQtThread<Self>);
}
5 changes: 3 additions & 2 deletions tests/basic_cxx_qt/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ mod ffi {
std::sync::atomic::AtomicUsize::new(0);

let mut handles = Vec::new();
let qt_thread = self.qt_thread();
for _ in 0..N_THREADS {
let qt_thread = self.qt_thread();
let qt_thread_cloned = qt_thread.clone();
handles.push(std::thread::spawn(move || {
qt_thread
qt_thread_cloned
.queue(|ctx| {
*ctx.update_call_count_mut() += 1;
})
Expand Down

0 comments on commit 4a4efd1

Please sign in to comment.