mirror of
https://github.com/servo/servo.git
synced 2025-08-06 06:00:15 +01:00
style: Implement ArcSlice::default().
Share a singleton to avoid allocating for empty lists. Differential Revision: https://phabricator.services.mozilla.com/D30543
This commit is contained in:
parent
ab8776a144
commit
5e4fdf647d
4 changed files with 52 additions and 21 deletions
|
@ -5,7 +5,7 @@
|
|||
//! A thin atomically-reference-counted slice.
|
||||
|
||||
use servo_arc::ThinArc;
|
||||
use std::mem;
|
||||
use std::{iter, mem};
|
||||
use std::ops::Deref;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
|
@ -14,7 +14,10 @@ use std::ptr::NonNull;
|
|||
/// Given we cannot use a zero-sized-type for the header, since well, C++
|
||||
/// doesn't have zsts, and we want to use cbindgen for this type, we may as well
|
||||
/// assert some sanity at runtime.
|
||||
const ARC_SLICE_CANARY: u32 = 0xf3f3f3f3;
|
||||
///
|
||||
/// We use an u64, to guarantee that we can use a single singleton for every
|
||||
/// empty slice, even if the types they hold are aligned differently.
|
||||
const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3;
|
||||
|
||||
/// A wrapper type for a refcounted slice using ThinArc.
|
||||
///
|
||||
|
@ -22,7 +25,7 @@ const ARC_SLICE_CANARY: u32 = 0xf3f3f3f3;
|
|||
/// cbindgen:derive-neq=false
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
|
||||
pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u32, T>);
|
||||
pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>);
|
||||
|
||||
impl<T> Deref for ArcSlice<T> {
|
||||
type Target = [T];
|
||||
|
@ -34,12 +37,28 @@ impl<T> Deref for ArcSlice<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
|
||||
/// The type of the pointer is a bit of a lie, we just want to preserve the type
|
||||
/// but these pointers cannot be constructed outside of this crate, so we're
|
||||
/// good.
|
||||
#[repr(C)]
|
||||
pub struct ForgottenArcSlicePtr<T>(NonNull<T>);
|
||||
lazy_static! {
|
||||
// ThinArc doesn't support alignments greater than align_of::<u64>.
|
||||
static ref EMPTY_ARC_SLICE: ArcSlice<u64> = {
|
||||
ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, iter::empty()))
|
||||
};
|
||||
}
|
||||
|
||||
impl<T> Default for ArcSlice<T> {
|
||||
#[allow(unsafe_code)]
|
||||
fn default() -> Self {
|
||||
debug_assert!(
|
||||
mem::align_of::<T>() <= mem::align_of::<u64>(),
|
||||
"Need to increase the alignment of EMPTY_ARC_SLICE"
|
||||
);
|
||||
unsafe {
|
||||
let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
|
||||
let empty: Self = mem::transmute(empty);
|
||||
debug_assert_eq!(empty.len(), 0);
|
||||
empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ArcSlice<T> {
|
||||
/// Creates an Arc for a slice using the given iterator to generate the
|
||||
|
@ -49,6 +68,9 @@ impl<T> ArcSlice<T> {
|
|||
where
|
||||
I: Iterator<Item = T> + ExactSizeIterator,
|
||||
{
|
||||
if items.len() == 0 {
|
||||
return Self::default();
|
||||
}
|
||||
ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items))
|
||||
}
|
||||
|
||||
|
@ -64,3 +86,10 @@ impl<T> ArcSlice<T> {
|
|||
ret
|
||||
}
|
||||
}
|
||||
|
||||
/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
|
||||
/// The type of the pointer is a bit of a lie, we just want to preserve the type
|
||||
/// but these pointers cannot be constructed outside of this crate, so we're
|
||||
/// good.
|
||||
#[repr(C)]
|
||||
pub struct ForgottenArcSlicePtr<T>(NonNull<T>);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue