arc_slice.rs (4996B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 //! A thin atomically-reference-counted slice. 6 7 use serde::de::{Deserialize, Deserializer}; 8 use serde::ser::{Serialize, Serializer}; 9 use servo_arc::ThinArc; 10 use std::ops::Deref; 11 use std::ptr::NonNull; 12 use std::sync::LazyLock; 13 use std::{ 14 hash::{Hash, Hasher}, 15 iter, mem, 16 }; 17 18 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; 19 20 /// A canary that we stash in ArcSlices. 21 /// 22 /// Given we cannot use a zero-sized-type for the header, since well, C++ 23 /// doesn't have zsts, and we want to use cbindgen for this type, we may as well 24 /// assert some sanity at runtime. 25 /// 26 /// We use an u64, to guarantee that we can use a single singleton for every 27 /// empty slice, even if the types they hold are aligned differently. 28 const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3; 29 30 /// A wrapper type for a refcounted slice using ThinArc. 31 #[repr(C)] 32 #[derive(Debug, Eq, PartialEq, ToShmem)] 33 pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>); 34 35 impl<T> Deref for ArcSlice<T> { 36 type Target = [T]; 37 38 #[inline] 39 fn deref(&self) -> &Self::Target { 40 debug_assert_eq!(self.0.header, ARC_SLICE_CANARY); 41 self.0.slice() 42 } 43 } 44 45 impl<T> Clone for ArcSlice<T> { 46 fn clone(&self) -> Self { 47 ArcSlice(self.0.clone()) 48 } 49 } 50 51 // ThinArc doesn't support alignments greater than align_of::<u64>. 52 static EMPTY_ARC_SLICE: LazyLock<ArcSlice<u64>> = 53 LazyLock::new(|| ArcSlice::from_iter_leaked(iter::empty())); 54 55 impl<T> Default for ArcSlice<T> { 56 #[allow(unsafe_code)] 57 fn default() -> Self { 58 debug_assert!( 59 mem::align_of::<T>() <= mem::align_of::<u64>(), 60 "Need to increase the alignment of EMPTY_ARC_SLICE" 61 ); 62 unsafe { 63 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone(); 64 let empty: Self = mem::transmute(empty); 65 debug_assert_eq!(empty.len(), 0); 66 empty 67 } 68 } 69 } 70 71 impl<T: Serialize> Serialize for ArcSlice<T> { 72 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 73 where 74 S: Serializer, 75 { 76 self.deref().serialize(serializer) 77 } 78 } 79 80 impl<'de, T: Deserialize<'de>> Deserialize<'de> for ArcSlice<T> { 81 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 82 where 83 D: Deserializer<'de>, 84 { 85 let r = Vec::deserialize(deserializer)?; 86 Ok(ArcSlice::from_iter(r.into_iter())) 87 } 88 } 89 90 impl<T> ArcSlice<T> { 91 /// Creates an Arc for a slice using the given iterator to generate the 92 /// slice. 93 #[inline] 94 pub fn from_iter<I>(items: I) -> Self 95 where 96 I: Iterator<Item = T> + ExactSizeIterator, 97 { 98 if items.len() == 0 { 99 return Self::default(); 100 } 101 ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items)) 102 } 103 104 /// Creates an Arc for a slice using the given iterator to generate the 105 /// slice, and marks the arc as intentionally leaked from the refcount 106 /// logging point of view. 107 #[inline] 108 pub fn from_iter_leaked<I>(items: I) -> Self 109 where 110 I: Iterator<Item = T> + ExactSizeIterator, 111 { 112 let arc = ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items); 113 arc.mark_as_intentionally_leaked(); 114 ArcSlice(arc) 115 } 116 117 /// Creates a value that can be passed via FFI, and forgets this value 118 /// altogether. 119 #[inline] 120 pub fn forget(self) -> ForgottenArcSlicePtr<T> { 121 let ret = ForgottenArcSlicePtr(self.0.raw_ptr().cast()); 122 mem::forget(self); 123 ret 124 } 125 126 /// Leaks an empty arc slice pointer, and returns it. Only to be used to 127 /// construct ArcSlices from FFI. 128 #[inline] 129 pub fn leaked_empty_ptr() -> *mut std::os::raw::c_void { 130 let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone(); 131 let ptr = empty.0.raw_ptr(); 132 std::mem::forget(empty); 133 ptr.cast().as_ptr() 134 } 135 136 /// Returns whether there's only one reference to this ArcSlice. 137 pub fn is_unique(&self) -> bool { 138 self.0.is_unique() 139 } 140 } 141 142 impl<T: MallocSizeOf> MallocUnconditionalSizeOf for ArcSlice<T> { 143 #[allow(unsafe_code)] 144 fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { 145 let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) }; 146 for el in self.iter() { 147 size += el.size_of(ops); 148 } 149 size 150 } 151 } 152 153 impl<T: Hash> Hash for ArcSlice<T> { 154 fn hash<H: Hasher>(&self, state: &mut H) { 155 T::hash_slice(&**self, state) 156 } 157 } 158 159 /// The inner pointer of an ArcSlice<T>, to be sent via FFI. 160 /// The type of the pointer is a bit of a lie, we just want to preserve the type 161 /// but these pointers cannot be constructed outside of this crate, so we're 162 /// good. 163 #[repr(C)] 164 pub struct ForgottenArcSlicePtr<T>(NonNull<T>);