sync_unsafe_cell/
lib.rs

1#![no_std]
2
3//! This is a backport of the `SyncUnsafeCell` type from the standard library. The backport allows
4//! it to be used in older Rust versions, where it either does not exist yet or is not stable. Its
5//! minimum supported Rust version is 1.59, though
6//! it may work with older versions too.
7//!
8//! A few changes have been made accordingly:
9//! * `UnsafeCell::into_inner` is not stably `const`, so `SyncUnsafeCell::into_inner` is also not
10//!   `const`.
11//! * `const_mut_refs` is not stable, so `SyncUnsafeCell::get_mut` is not `const`.
12//! * `CoerceUnsized` is not stable, so `SyncUnsafeCell` does not implement it.
13//!
14//! Thanks to Mara Bos (m-ou-se) for [the standard library
15//! implementation](https://github.com/rust-lang/rust/pull/95438) of which this is a copy.
16
17use core::cell::UnsafeCell;
18
19/// [`UnsafeCell`], but [`Sync`].
20///
21/// This is just an `UnsafeCell`, except it implements `Sync` if `T` implements `Sync`.
22///
23/// `UnsafeCell` doesn't implement `Sync`, to prevent accidental mis-use. You can use
24/// `SyncUnsafeCell` instead of `UnsafeCell` to allow it to be shared between threads, if that's
25/// intentional. Providing proper synchronization is still the task of the user, making this type
26/// just as unsafe to use.
27///
28/// See [`UnsafeCell`] for details.
29#[repr(transparent)]
30pub struct SyncUnsafeCell<T: ?Sized> {
31	value: UnsafeCell<T>,
32}
33
34unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {}
35
36impl<T> SyncUnsafeCell<T> {
37	/// Constructs a new instance of `SyncUnsafeCell` which will wrap the specified value.
38	#[inline]
39	pub const fn new(value: T) -> Self {
40		Self {
41			value: UnsafeCell::new(value),
42		}
43	}
44
45	/// Unwraps the value.
46	#[inline]
47	pub fn into_inner(self) -> T {
48		self.value.into_inner()
49	}
50}
51
52impl<T: ?Sized> SyncUnsafeCell<T> {
53	/// Gets a mutable pointer to the wrapped value.
54	///
55	/// This can be cast to a pointer of any kind. Ensure that the access is unique (no active
56	/// references, mutable or not) when casting to `&mut T`, and ensure that there are no
57	/// mutations or mutable aliases going on when casting to `&T`
58	#[inline]
59	pub const fn get(&self) -> *mut T {
60		self.value.get()
61	}
62
63	/// Returns a mutable reference to the underlying data.
64	///
65	/// This call borrows the `SyncUnsafeCell` mutably (at compile-time) which guarantees that we
66	/// possess the only reference.
67	#[inline]
68	pub fn get_mut(&mut self) -> &mut T {
69		self.value.get_mut()
70	}
71
72	/// Gets a mutable pointer to the wrapped value.
73	///
74	/// See [`UnsafeCell::get`] for details.
75	#[inline]
76	pub const fn raw_get(this: *const Self) -> *mut T {
77		// We can just cast the pointer from `SyncUnsafeCell<T>` to `T` because
78		// of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell.
79		// See UnsafeCell::raw_get.
80		this as *const T as *mut T
81	}
82}
83
84impl<T: Default> Default for SyncUnsafeCell<T> {
85	/// Creates an `SyncUnsafeCell`, with the `Default` value for T.
86	fn default() -> SyncUnsafeCell<T> {
87		SyncUnsafeCell::new(Default::default())
88	}
89}
90
91impl<T> From<T> for SyncUnsafeCell<T> {
92	/// Creates a new `SyncUnsafeCell<T>` containing the given value.
93	fn from(t: T) -> SyncUnsafeCell<T> {
94		SyncUnsafeCell::new(t)
95	}
96}