rrtk/
reference.rs

1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright 2024-2025 UxuginPython
3//![`Reference`] is a container holding an enum with variants containing different kinds of
4//!references, the availability of some of which depends on crate features. [`Reference`] is borrowed like
5//!a [`RefCell`]. This module contains it and its related types. [`Reference`] is also reexported at
6//!the crate level.
7use crate::*;
8#[cfg(feature = "alloc")]
9use core::cell::{Ref, RefMut};
10#[cfg(feature = "std")]
11use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
12///An immutable borrow of an RRTK [`Reference`], similar to [`Ref`] for a [`RefCell`].
13///
14///This is marked as non-exhaustive because some variants are only available with some features.
15///This means that if you write a `match` without all the features enabled, it won't cover all the
16///variants if another crate in the tree enables more features. This is a problem because features
17///are additive, so it is marked as non-exhaustive to remedy this.
18#[derive(Debug)]
19#[non_exhaustive]
20pub enum Borrow<'a, T: ?Sized> {
21    ///A raw immutable pointer.
22    Ptr(*const T, PhantomData<&'a ()>),
23    ///An immutable borrow of an `Rc<RefCell<T>>`.
24    #[cfg(feature = "alloc")]
25    RefCellRef(Ref<'a, T>),
26    ///An [`RwLockReadGuard`].
27    #[cfg(feature = "std")]
28    RwLockReadGuard(RwLockReadGuard<'a, T>),
29    ///A [`MutexGuard`].
30    #[cfg(feature = "std")]
31    MutexGuard(MutexGuard<'a, T>),
32}
33impl<T: ?Sized> Deref for Borrow<'_, T> {
34    type Target = T;
35    fn deref(&self) -> &T {
36        match self {
37            Self::Ptr(ptr, _) => unsafe { &**ptr },
38            #[cfg(feature = "alloc")]
39            Self::RefCellRef(ref_cell_ref) => ref_cell_ref,
40            #[cfg(feature = "std")]
41            Self::RwLockReadGuard(rw_lock_read_guard) => rw_lock_read_guard,
42            #[cfg(feature = "std")]
43            Self::MutexGuard(mutex_guard) => mutex_guard,
44        }
45    }
46}
47///A mutable borrow of an RRTK [`Reference`], similar to [`RefMut`] for a [`RefCell`].
48///
49///This is marked as non-exhaustive because some variants are only available with some features.
50///This means that if you write a `match` without all the features enabled, it won't cover all the
51///variants if another crate in the tree enables more features. This is a problem because features
52///are additive, so it is marked as non-exhaustive to remedy this.
53#[derive(Debug)]
54#[non_exhaustive]
55pub enum BorrowMut<'a, T: ?Sized> {
56    ///A raw mutable pointer.
57    Ptr(*mut T, PhantomData<&'a ()>),
58    ///A mutable borrow of an `Rc<RefCell<T>>`.
59    #[cfg(feature = "alloc")]
60    RefCellRefMut(RefMut<'a, T>),
61    ///An [`RwLockWriteGuard`].
62    #[cfg(feature = "std")]
63    RwLockWriteGuard(RwLockWriteGuard<'a, T>),
64    ///A [`MutexGuard`].
65    #[cfg(feature = "std")]
66    MutexGuard(MutexGuard<'a, T>),
67}
68impl<T: ?Sized> Deref for BorrowMut<'_, T> {
69    type Target = T;
70    fn deref(&self) -> &T {
71        match self {
72            Self::Ptr(ptr, _) => unsafe { &**ptr },
73            #[cfg(feature = "alloc")]
74            Self::RefCellRefMut(ref_cell_ref_mut) => ref_cell_ref_mut,
75            #[cfg(feature = "std")]
76            Self::RwLockWriteGuard(rw_lock_write_guard) => rw_lock_write_guard,
77            #[cfg(feature = "std")]
78            Self::MutexGuard(mutex_guard) => mutex_guard,
79        }
80    }
81}
82impl<T: ?Sized> DerefMut for BorrowMut<'_, T> {
83    fn deref_mut(&mut self) -> &mut T {
84        match self {
85            Self::Ptr(ptr, _) => unsafe { &mut **ptr },
86            #[cfg(feature = "alloc")]
87            Self::RefCellRefMut(ref_cell_ref_mut) => ref_cell_ref_mut,
88            #[cfg(feature = "std")]
89            Self::RwLockWriteGuard(rw_lock_write_guard) => rw_lock_write_guard,
90            #[cfg(feature = "std")]
91            Self::MutexGuard(mutex_guard) => mutex_guard,
92        }
93    }
94}
95///A special enum with variants for different kinds of references depending on your platform and
96///code structure. (Some variants are alloc- or std-only.) It is usually contained in a
97///[`Reference`], which is a safe wrapper. You should generally use [`Reference`] over
98///[`ReferenceUnsafe`] unless you specifically need to match against it, probably for some form of
99///type conversion.
100///
101///This is marked as non-exhaustive because some variants are only available with some features.
102///This means that if you write a `match` without all the features enabled, it won't cover all the
103///variants if another crate in the tree enables more features. This is a problem because features
104///are additive, so it is marked as non-exhaustive to remedy this.
105#[derive(Debug)]
106#[non_exhaustive]
107pub enum ReferenceUnsafe<T: ?Sized> {
108    ///A raw mutable pointer. This is a useful variant if you are not multithreading and you want
109    ///to avoid dynamic allocation. Making the target static is recommended.
110    Ptr(*mut T),
111    ///An `Rc<RefCell<T>>`.
112    #[cfg(feature = "alloc")]
113    RcRefCell(Rc<RefCell<T>>),
114    ///A raw immutable pointer to an [`RwLock<T>`]. Making the [`RwLock`] itself static is recommended.
115    #[cfg(feature = "std")]
116    PtrRwLock(*const RwLock<T>),
117    ///A raw pointer to a [`Mutex<T>`]. Making the [`Mutex`] itself static is recommended.
118    #[cfg(feature = "std")]
119    PtrMutex(*const Mutex<T>),
120    ///An `Arc<RwLock<T>>`.
121    #[cfg(feature = "std")]
122    ArcRwLock(Arc<RwLock<T>>),
123    ///An `Arc<Mutex<T>>`.
124    #[cfg(feature = "std")]
125    ArcMutex(Arc<Mutex<T>>),
126}
127impl<T: ?Sized> ReferenceUnsafe<T> {
128    ///Create a [`ReferenceUnsafe`] from a raw mutable pointer. This is useful if you are not
129    ///multithreading and you want to avoid dynamic allocation. Making the target static is
130    ///recommended.
131    pub const unsafe fn from_ptr(ptr: *mut T) -> Self {
132        Self::Ptr(ptr)
133    }
134    ///Create a [`ReferenceUnsafe`] from an `Rc<RefCell<T>>`.
135    #[cfg(feature = "alloc")]
136    pub const fn from_rc_ref_cell(rc_ref_cell: Rc<RefCell<T>>) -> Self {
137        Self::RcRefCell(rc_ref_cell)
138    }
139    ///Create a [`ReferenceUnsafe`] from a `*const RwLock<T>`. Making the [`RwLock`] itself static is
140    ///recommended.
141    #[cfg(feature = "std")]
142    pub const unsafe fn from_ptr_rw_lock(ptr_rw_lock: *const RwLock<T>) -> Self {
143        Self::PtrRwLock(ptr_rw_lock)
144    }
145    ///Create a [`ReferenceUnsafe`] from a `*const Mutex<T>`. Making the [`Mutex`] itself static is
146    ///recommended.
147    #[cfg(feature = "std")]
148    pub const unsafe fn from_ptr_mutex(ptr_mutex: *const Mutex<T>) -> Self {
149        Self::PtrMutex(ptr_mutex)
150    }
151    ///Create a new [`ReferenceUnsafe`] from an `Arc<RwLock<T>>`.
152    #[cfg(feature = "std")]
153    pub const fn from_arc_rw_lock(arc_rw_lock: Arc<RwLock<T>>) -> Self {
154        Self::ArcRwLock(arc_rw_lock)
155    }
156    ///Create a [`ReferenceUnsafe`] from an `Arc<Mutex<T>>`.
157    #[cfg(feature = "std")]
158    pub const fn from_arc_mutex(arc_mutex: Arc<Mutex<T>>) -> Self {
159        Self::ArcMutex(arc_mutex)
160    }
161    ///Immutably borrow the [`ReferenceUnsafe`] like a [`RefCell`]. This is unsafe because of the
162    ///potential for a dereference of the borrow to dereference a null or freed raw pointer.
163    pub unsafe fn borrow(&self) -> Borrow<'_, T> {
164        match self {
165            Self::Ptr(ptr) => Borrow::Ptr(*ptr, PhantomData),
166            #[cfg(feature = "alloc")]
167            Self::RcRefCell(rc_ref_cell) => Borrow::RefCellRef(rc_ref_cell.borrow()),
168            #[cfg(feature = "std")]
169            Self::PtrRwLock(ptr_rw_lock) => unsafe {
170                Borrow::RwLockReadGuard(
171                    (**ptr_rw_lock)
172                        .read()
173                        .expect("RRTK Reference borrow failed to get RwLock read lock"),
174                )
175            },
176            #[cfg(feature = "std")]
177            Self::PtrMutex(ptr_mutex) => unsafe {
178                Borrow::MutexGuard(
179                    (**ptr_mutex)
180                        .lock()
181                        .expect("RRTK Reference borrow failed to get Mutex lock"),
182                )
183            },
184            #[cfg(feature = "std")]
185            Self::ArcRwLock(arc_rw_lock) => Borrow::RwLockReadGuard(
186                arc_rw_lock
187                    .read()
188                    .expect("RRTK Reference borrow failed to get RwLock read lock"),
189            ),
190            #[cfg(feature = "std")]
191            Self::ArcMutex(arc_mutex) => Borrow::MutexGuard(
192                arc_mutex
193                    .lock()
194                    .expect("RRTK Reference borrow failed to get Mutex lock"),
195            ),
196        }
197    }
198    ///Mutably borrow the [`ReferenceUnsafe`] like a [`RefCell`]. Thus is unsafe because of the
199    ///potential for a dereference of the borrow to dereference a null or freed raw pointer.
200    pub unsafe fn borrow_mut(&self) -> BorrowMut<'_, T> {
201        match self {
202            Self::Ptr(ptr) => BorrowMut::Ptr(*ptr, PhantomData),
203            #[cfg(feature = "alloc")]
204            Self::RcRefCell(rc_ref_cell) => BorrowMut::RefCellRefMut(rc_ref_cell.borrow_mut()),
205            #[cfg(feature = "std")]
206            Self::PtrRwLock(ptr_rw_lock) => unsafe {
207                BorrowMut::RwLockWriteGuard(
208                    (**ptr_rw_lock)
209                        .write()
210                        .expect("RRTK Reference mutable borrow failed to get RwLock write lock"),
211                )
212            },
213            #[cfg(feature = "std")]
214            Self::PtrMutex(ptr_mutex) => unsafe {
215                BorrowMut::MutexGuard(
216                    (**ptr_mutex)
217                        .lock()
218                        .expect("RRTK Reference mutable borrow failed to get Mutex lock"),
219                )
220            },
221            #[cfg(feature = "std")]
222            Self::ArcRwLock(arc_rw_lock) => BorrowMut::RwLockWriteGuard(
223                arc_rw_lock
224                    .write()
225                    .expect("RRTK Reference mutable borrow failed to get RwLock write lock"),
226            ),
227            #[cfg(feature = "std")]
228            Self::ArcMutex(arc_mutex) => BorrowMut::MutexGuard(
229                arc_mutex
230                    .lock()
231                    .expect("RRTK Reference mutable borrow failed to get Mutex lock"),
232            ),
233        }
234    }
235}
236impl<T: ?Sized> Clone for ReferenceUnsafe<T> {
237    fn clone(&self) -> Self {
238        match self {
239            Self::Ptr(ptr) => Self::Ptr(*ptr),
240            #[cfg(feature = "alloc")]
241            Self::RcRefCell(rc_ref_cell) => Self::RcRefCell(Rc::clone(&rc_ref_cell)),
242            #[cfg(feature = "std")]
243            Self::PtrRwLock(ptr_rw_lock) => Self::PtrRwLock(*ptr_rw_lock),
244            #[cfg(feature = "std")]
245            Self::PtrMutex(ptr_mutex) => Self::PtrMutex(*ptr_mutex),
246            #[cfg(feature = "std")]
247            Self::ArcRwLock(arc_rw_lock) => Self::ArcRwLock(Arc::clone(&arc_rw_lock)),
248            #[cfg(feature = "std")]
249            Self::ArcMutex(arc_mutex) => Self::ArcMutex(Arc::clone(&arc_mutex)),
250        }
251    }
252}
253impl<T: ?Sized> From<Reference<T>> for ReferenceUnsafe<T> {
254    fn from(was: Reference<T>) -> Self {
255        was.into_inner()
256    }
257}
258///A container privately holding an enum with variants containing different kinds of references,
259///the availability of some of which depends on crate features. [`Reference`] is borrowed like a [`RefCell`].
260///It is also reexported at the crate level.
261#[derive(Debug)]
262#[repr(transparent)]
263pub struct Reference<T: ?Sized>(ReferenceUnsafe<T>);
264impl<T: ?Sized> Reference<T> {
265    ///Create a [`Reference`] from a raw mutable pointer. This is useful if you are not
266    ///multithreading and you want to avoid dynamic allocation. Making the target static is
267    ///recommended. The [`static_reference!`] macro is a convenient way of making an object
268    ///static and getting a `Reference` of the raw pointer variant to it. Because the object is
269    ///guaranteed to be static, it can be called without an unsafe block.
270    pub const unsafe fn from_ptr(ptr: *mut T) -> Self {
271        unsafe { Self(ReferenceUnsafe::from_ptr(ptr)) }
272    }
273    ///Create a [`Reference`] from an `Rc<RefCell<T>>`. The [`rc_ref_cell_reference`] function is a
274    ///convenient way of putting an object in an `Rc<RefCell<T>>` and getting a [`Reference`] of this
275    ///variant to it.
276    #[cfg(feature = "alloc")]
277    pub const fn from_rc_ref_cell(rc_ref_cell: Rc<RefCell<T>>) -> Self {
278        Self(ReferenceUnsafe::from_rc_ref_cell(rc_ref_cell))
279    }
280    ///Create a [`Reference`] from a `*const RwLock<T>`. Making the [`RwLock`] itself static is
281    ///recommended. The [`static_rw_lock_reference!`] macro is a convenient way of putting
282    ///an object in a static [`RwLock`] and getting a `Reference` of this variant to it.
283    #[cfg(feature = "std")]
284    pub const unsafe fn from_ptr_rw_lock(ptr_rw_lock: *const RwLock<T>) -> Self {
285        unsafe { Self(ReferenceUnsafe::from_ptr_rw_lock(ptr_rw_lock)) }
286    }
287    ///Create a [`Reference`] from a `*const Mutex<T>`. Making the [`Mutex`] itself static is
288    ///recommended. The [`static_mutex_reference!`] macro is a convenient way of putting an object in
289    ///a static [`Mutex`] and getting a [`Reference`] of this variant to it.
290    #[cfg(feature = "std")]
291    pub const unsafe fn from_ptr_mutex(ptr_mutex: *const Mutex<T>) -> Self {
292        unsafe { Self(ReferenceUnsafe::from_ptr_mutex(ptr_mutex)) }
293    }
294    ///Create a [`Reference`] from an `Arc<RwLock<T>>`. The [`arc_rw_lock_reference`] function is a
295    ///convenient way of putting an object in an [`Arc<RwLock>`] and getting a [`Reference`] of this
296    ///variant to it.
297    #[cfg(feature = "std")]
298    pub const fn from_arc_rw_lock(arc_rw_lock: Arc<RwLock<T>>) -> Self {
299        Self(ReferenceUnsafe::from_arc_rw_lock(arc_rw_lock))
300    }
301    ///Create a [`Reference`] from an `Arc<Mutex<T>>`. The [`arc_mutex_reference`] function is a
302    ///convenient way of putting an object in an `Arc<Mutex>` and getting a [`Reference`] of this
303    ///variant to it.
304    #[cfg(feature = "std")]
305    pub const fn from_arc_mutex(arc_mutex: Arc<Mutex<T>>) -> Self {
306        Self(ReferenceUnsafe::from_arc_mutex(arc_mutex))
307    }
308    ///Get the inner [`ReferenceUnsafe`].
309    pub fn into_inner(self) -> ReferenceUnsafe<T> {
310        self.0
311    }
312    ///Immutably borrow the [`Reference`] like a [`RefCell`].
313    pub fn borrow(&self) -> Borrow<'_, T> {
314        unsafe { self.0.borrow() }
315    }
316    ///Mutably borrow the [`Reference`] like a [`RefCell`].
317    pub fn borrow_mut(&self) -> BorrowMut<'_, T> {
318        unsafe { self.0.borrow_mut() }
319    }
320}
321//It is necessary to implement Clone like this as #[derive(Clone)] would add an unnecessary Clone
322//bound to T.
323impl<T: ?Sized> Clone for Reference<T> {
324    fn clone(&self) -> Self {
325        Self(self.0.clone())
326    }
327}
328impl<U: ?Sized + Updatable<E>, E: Copy + Debug> Updatable<E> for Reference<U> {
329    fn update(&mut self) -> NothingOrError<E> {
330        self.borrow_mut().update()
331    }
332}
333impl<G: ?Sized + Getter<T, E>, T, E: Copy + Debug> Getter<T, E> for Reference<G> {
334    fn get(&self) -> Output<T, E> {
335        self.borrow().get()
336    }
337}
338impl<TG: ?Sized + TimeGetter<E>, E: Copy + Debug> TimeGetter<E> for Reference<TG> {
339    fn get(&self) -> TimeOutput<E> {
340        self.borrow().get()
341    }
342}
343//This is currently stopped by E0515, but if this ever becomes possible (or you discover that it
344//was possible all along), do it.
345/*impl<S: ?Sized + Settable<T, E>, T: Clone, E: Copy + Debug> Settable<T, E> for Reference<S> {
346    //set must be implemented as S::set because
347    //1. implementing impl_set as S::set would nest the additional code that set adds over impl_set, and
348    //2. implementing impl_set as S::impl_set would be bad in case S::set is overridden for some reason.
349    fn set(&mut self, value: T) -> NothingOrError<E> {
350        self.borrow_mut().set(value)
351    }
352    fn impl_set(&mut self, _value: T) -> NothingOrError<E> {
353        unimplemented!();
354    }
355    fn get_settable_data_ref(&self) -> &SettableData<T, E> {
356        self.borrow().get_settable_data_ref()
357    }
358    fn get_settable_data_mut(&mut self) -> &mut SettableData<T, E> {
359        self.borrow_mut().get_settable_data_mut()
360    }
361}*/
362///If you have a `Reference<Foo>` where `Foo` implements the `Bar` trait, you may end up wanting a
363///`Reference<dyn Bar>`. To convert it, you would do this:
364///```
365///# use rrtk::*;
366///struct Foo;
367///impl Foo {
368///    fn foo_func(&self) {}
369///}
370///trait Bar {
371///    fn bar_func(&self) {}
372///}
373///impl Bar for Foo {}
374///let ref_foo = static_reference!(Foo, Foo);
375///ref_foo.borrow().foo_func();
376///ref_foo.borrow().bar_func();
377///let ref_dyn_bar = to_dyn!(Bar, ref_foo);
378///ref_dyn_bar.borrow().bar_func();
379///```
380///
381///The documentation shows `rrtk::to_dyn` and `rrtk::reference::to_dyn` separately. These are the
382///same macro exported in two different places. These paths point to the same code in RRTK. Rust's
383///scoping rules for macros are a bit odd, but you should be able to use `rrtk::to_dyn` and
384///`rrtk::reference::to_dyn` interchangably.
385#[macro_export]
386macro_rules! to_dyn {
387    ($trait_:path, $was:expr) => {{
388        #[cfg(feature = "alloc")]
389        extern crate alloc;
390        #[allow(unreachable_patterns)]
391        match $was.into_inner() {
392            reference::ReferenceUnsafe::Ptr(ptr) => unsafe {
393                Reference::from_ptr(ptr as *mut dyn $trait_)
394            },
395            #[cfg(feature = "alloc")]
396            reference::ReferenceUnsafe::RcRefCell(rc_ref_cell) => Reference::from_rc_ref_cell(
397                rc_ref_cell as alloc::rc::Rc<core::cell::RefCell<dyn $trait_>>,
398            ),
399            #[cfg(feature = "std")]
400            reference::ReferenceUnsafe::PtrRwLock(ptr_rw_lock) => unsafe {
401                Reference::from_ptr_rw_lock(ptr_rw_lock as *const std::sync::RwLock<dyn $trait_>)
402            },
403            _ => unimplemented!(),
404        }
405    }};
406}
407pub use to_dyn;
408///Create a new `Rc<RefCell>` of something and return a [`Reference`] to it. Because of how [`Rc`]
409///works, it won't be dropped until the last clone of the `Reference` is. This is reexported at the
410///crate level.
411#[cfg(feature = "alloc")]
412pub fn rc_ref_cell_reference<T>(was: T) -> Reference<T> {
413    Reference::from_rc_ref_cell(Rc::new(RefCell::new(was)))
414}
415///Create a static of something and return a `Ptr`-variant [`Reference`] to it. This contains a raw
416///mutable pointer. It will never use-after-free because its target is static, but be careful if
417///you're doing multiprocessing where multiple things could mutate it at once.
418///
419///The documentation shows `rrtk::static_reference` and `rrtk::reference::static_reference` separately. These are the
420///same macro exported in two different places. These paths point to the same code in RRTK. Rust's
421///scoping rules for macros are a bit odd, but you should be able to use `rrtk::static_reference` and
422///`rrtk::reference::static_reference` interchangably.
423#[macro_export]
424macro_rules! static_reference {
425    ($type_: ty, $was: expr) => {{
426        static mut WAS: $type_ = $was;
427        unsafe { Reference::from_ptr(core::ptr::addr_of_mut!(WAS)) }
428    }};
429}
430pub use static_reference;
431///Create a static [`RwLock`] of something and return a `PtrRwLock`-variant [`Reference`] to it.
432///
433///The documentation shows `rrtk::static_rw_lock_reference` and `rrtk::reference::static_rw_lock_reference` separately. These are the
434///same macro exported in two different places. These paths point to the same code in RRTK. Rust's
435///scoping rules for macros are a bit odd, but you should be able to use `rrtk::static_rw_lock_reference` and
436///`rrtk::reference::static_rw_lock_reference` interchangably.
437#[cfg(feature = "std")]
438#[macro_export]
439macro_rules! static_rw_lock_reference {
440    ($type_: ty, $was: expr) => {{
441        static WAS: std::sync::RwLock<$type_> = std::sync::RwLock::new($was);
442        unsafe { Reference::from_ptr_rw_lock(core::ptr::addr_of!(WAS)) }
443    }};
444}
445#[cfg(feature = "std")]
446pub use static_rw_lock_reference;
447//TODO: Fix this documentation to explain about how Reference doesn't really have variants
448///Create a new static [`Mutex`] of something and return a `PtrMutex`-variant [`Reference`] to it.
449///
450///The documentation shows `rrtk::static_mutex_reference` and `rrtk::reference::static_mutex_reference` separately. These are the
451///same macro exported in two different places. These paths point to the same code in RRTK. Rust's
452///scoping rules for macros are a bit odd, but you should be able to use `rrtk::static_mutex_reference` and
453///`rrtk::reference::static_mutex_reference` interchangably.
454#[cfg(feature = "std")]
455#[macro_export]
456macro_rules! static_mutex_reference {
457    ($type_: ty, $was: expr) => {{
458        static WAS: std::sync::Mutex<$type_> = std::sync::Mutex::new($was);
459        unsafe { Reference::from_ptr_mutex(core::ptr::addr_of!(WAS)) }
460    }};
461}
462///Create a new `Arc<RwLock>` of something and return a [`Reference`] to it. Because of how [`Arc`] and
463///[`Rc`], its single-threaded counterpart, work, it won't be dropped until the last clone of the
464///[`Reference`] is. This is reexported at the crate level.
465#[cfg(feature = "std")]
466pub fn arc_rw_lock_reference<T>(was: T) -> Reference<T> {
467    Reference::from_arc_rw_lock(Arc::new(RwLock::new(was)))
468}
469#[cfg(feature = "std")]
470pub use static_mutex_reference;
471///Create a new `Arc<Mutex>` of something and return a [`Reference`] to it. Because of how [`Arc`] and
472///[`Rc`], its single-threaded counterpart, work, it won't be dropped until the last clone of the
473///[`Reference`] is. This is reexported at the crate level.
474#[cfg(feature = "std")]
475pub fn arc_mutex_reference<T>(was: T) -> Reference<T> {
476    Reference::from_arc_mutex(Arc::new(Mutex::new(was)))
477}