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}