1 //! This module is full of hackery and dark magic.
2 //! Either spend a day fixing it and quietly submit a PR or don't mention it to anybody.
3 use core::cell::UnsafeCell;
4 use core::{mem, ptr};
5
ptr_size_bits() -> usize6 pub const fn ptr_size_bits() -> usize {
7 mem::size_of::<usize>() * 8
8 }
9
map_in_place_2<T, U, F: FnOnce(U, T) -> T>((k, v): (U, &mut T), f: F)10 pub fn map_in_place_2<T, U, F: FnOnce(U, T) -> T>((k, v): (U, &mut T), f: F) {
11 unsafe {
12 // # Safety
13 //
14 // If the closure panics, we must abort otherwise we could double drop `T`
15 let _promote_panic_to_abort = AbortOnPanic;
16
17 ptr::write(v, f(k, ptr::read(v)));
18 }
19 }
20
21 /// # Safety
22 ///
23 /// Requires that you ensure the reference does not become invalid.
24 /// The object has to outlive the reference.
change_lifetime_const<'a, 'b, T>(x: &'a T) -> &'b T25 pub unsafe fn change_lifetime_const<'a, 'b, T>(x: &'a T) -> &'b T {
26 &*(x as *const T)
27 }
28
29 /// # Safety
30 ///
31 /// Requires that you ensure the reference does not become invalid.
32 /// The object has to outlive the reference.
change_lifetime_mut<'a, 'b, T>(x: &'a mut T) -> &'b mut T33 pub unsafe fn change_lifetime_mut<'a, 'b, T>(x: &'a mut T) -> &'b mut T {
34 &mut *(x as *mut T)
35 }
36
37 /// A simple wrapper around `T`
38 ///
39 /// This is to prevent UB when using `HashMap::get_key_value`, because
40 /// `HashMap` doesn't expose an api to get the key and value, where
41 /// the value is a `&mut T`.
42 ///
43 /// See [#10](https://github.com/xacrimon/dashmap/issues/10) for details
44 ///
45 /// This type is meant to be an implementation detail, but must be exposed due to the `Dashmap::shards`
46 #[repr(transparent)]
47 pub struct SharedValue<T> {
48 value: UnsafeCell<T>,
49 }
50
51 impl<T: Clone> Clone for SharedValue<T> {
clone(&self) -> Self52 fn clone(&self) -> Self {
53 let inner = self.get().clone();
54
55 Self {
56 value: UnsafeCell::new(inner),
57 }
58 }
59 }
60
61 unsafe impl<T: Send> Send for SharedValue<T> {}
62
63 unsafe impl<T: Sync> Sync for SharedValue<T> {}
64
65 impl<T> SharedValue<T> {
66 /// Create a new `SharedValue<T>`
new(value: T) -> Self67 pub const fn new(value: T) -> Self {
68 Self {
69 value: UnsafeCell::new(value),
70 }
71 }
72
73 /// Get a shared reference to `T`
get(&self) -> &T74 pub fn get(&self) -> &T {
75 unsafe { &*self.value.get() }
76 }
77
78 /// Get an unique reference to `T`
get_mut(&mut self) -> &mut T79 pub fn get_mut(&mut self) -> &mut T {
80 unsafe { &mut *self.value.get() }
81 }
82
83 /// Unwraps the value
into_inner(self) -> T84 pub fn into_inner(self) -> T {
85 self.value.into_inner()
86 }
87
88 /// Get a mutable raw pointer to the underlying value
as_ptr(&self) -> *mut T89 pub(crate) fn as_ptr(&self) -> *mut T {
90 self.value.get()
91 }
92 }
93
94 struct AbortOnPanic;
95
96 impl Drop for AbortOnPanic {
drop(&mut self)97 fn drop(&mut self) {
98 if std::thread::panicking() {
99 std::process::abort()
100 }
101 }
102 }
103