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}