use core::{marker::PhantomData, mem::MaybeUninit, pin::Pin};
use cxx::ExternType;
use thiserror::Error;
use crate::Threading;
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum ThreadingQueueError {
#[error("Cannot queue function pointer as object has been destroyed")]
ObjectDestroyed,
#[error("Cannot queue function pointer as invokeMethod on object failed")]
InvokeMethodFailed,
#[error("Cannot queue as an unknown error occurred")]
Unknown,
}
impl From<u8> for ThreadingQueueError {
fn from(value: u8) -> Self {
match value {
1 => Self::ObjectDestroyed,
2 => Self::InvokeMethodFailed,
_others => Self::Unknown,
}
}
}
#[repr(C)]
pub struct CxxQtThread<T>
where
T: Threading,
{
_space: MaybeUninit<[usize; 2]>,
_value: PhantomData<T>,
}
unsafe impl<T> ExternType for CxxQtThread<T>
where
T: ExternType + Threading,
{
type Id = T::ThreadingTypeId;
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,
{
fn drop(&mut self) {
T::threading_drop(unsafe { core::pin::Pin::new_unchecked(self) });
}
}
unsafe impl<T> Send for CxxQtThread<T> where T: Threading {}
unsafe impl<T> Sync for CxxQtThread<T> where T: Threading {}
impl<T> CxxQtThread<T>
where
T: Threading,
{
pub fn queue<F>(&self, f: F) -> Result<(), crate::ThreadingQueueError>
where
F: FnOnce(Pin<&mut T>),
F: Send + 'static,
{
T::queue(self, f)
}
pub fn is_destroyed(&self) -> bool {
T::is_destroyed(self)
}
}