breadthread/
object.rs

1// MIT/Apache2 License
2
3use core::{any::type_name, fmt, marker::PhantomData, mem::MaybeUninit};
4
5/// A thread-unsafe object that only has true meaning in the context of a
6/// `BreadThread` runtime.
7#[repr(transparent)]
8pub struct Object<Ty, Tag> {
9    // the tag
10    tag: PhantomData<Tag>,
11    // the real object
12    //
13    // this will never drop, since it's in the Compatible contract
14    // to never drop. that being said, we like to think of this as
15    // "just a bunch of bits", so it's best to wrap it in MaybeUninit
16    // anyhow
17    object: MaybeUninit<Ty>,
18}
19
20impl<Ty: Copy, Tag> Copy for Object<Ty, Tag> {}
21
22impl<Ty: Copy, Tag> Clone for Object<Ty, Tag> {
23    fn clone(&self) -> Self {
24        *self
25    }
26}
27
28impl<Ty, Tag> fmt::Debug for Object<Ty, Tag> {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        f.debug_struct("Object")
31            .field("object", &type_name::<Ty>())
32            .field("tag", &type_name::<Tag>())
33            .finish()
34    }
35}
36
37// SAFETY: this is safe because the object is only ever accessed from its
38// owning thread.
39// double check sync though
40unsafe impl<Ty, Tag> Send for Object<Ty, Tag> {}
41unsafe impl<Ty, Tag> Sync for Object<Ty, Tag> {}
42
43impl<Ty, Tag> Object<Ty, Tag> {
44    /// Create a new `Object` without checking to see if
45    /// we are on the correct thread.
46    ///
47    /// # Safety
48    ///
49    /// This is unsafe because it assumes that the caller is on the correct
50    /// thread.
51    pub unsafe fn new_unchecked(object: Ty) -> Self {
52        Self {
53            object: MaybeUninit::new(object),
54            tag: PhantomData,
55        }
56    }
57
58    /// Convert to the inner `Object` type.
59    ///
60    /// # Safety
61    ///
62    /// This is unsafe because it assumes that the caller is on the correct
63    /// thread.
64    pub unsafe fn into_inner_unchecked(self) -> Ty {
65        self.object.assume_init()
66    }
67
68    /// Get a reference to the inner object.
69    ///
70    /// # Safety
71    ///
72    /// This is unsafe because it assumes that the caller is on the correct
73    /// thread.
74    pub unsafe fn get_unchecked(&self) -> &Ty {
75        &*self.object.as_ptr()
76    }
77}
78
79/// A thread-unsafe object that can be used in the `BreadThread` runtime.
80///
81/// # Safety
82///
83/// `representative` must be unique for the given object, and the type must not
84/// have a `Drop` implementation of any kind.
85pub unsafe trait Compatible {
86    /// Get the representative value for this object.
87    ///
88    /// # Safety
89    ///
90    /// The representative object must be unique for this object.
91    fn representative(&self) -> usize;
92}