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}