Added `CachelineBuffer` and `AlignedCachelineBuffer`: Byte buffers that are the size of one cacheline (2nd: and aligned to cacheline boundary.)

Fortune for reverse's current commit: Half blessing − 半吉
refactor-thread-pool-no-channel-cmpext
Avril 1 month ago
parent 03a3a1bfd0
commit 0ce496cafd
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -7,8 +7,121 @@ pub use std::{
convert::{
TryFrom, TryInto,
},
borrow::*,
};
/// Add forwarding borrow + deref (+ optional `into_inner()`) impls for a type.
///
/// # Usage
/// For a mutable forwarding newtype:
/// ```
/// # use crate::forward_newtype;
/// # use core::borrow::*;
///
/// /// A mutable buffer newtype over an array.
/// struct Buffer([u8; 16]);
/// forward_newtype!(mut Buffer => [u8], 0); // Generates `Borrow<[u8]>`, `BorrowMut<[u8]>`, `Deref<Target=[u8]>`, and `DerefMut` impls for `Buffer` that return `<&[mut] self.>0` (as specified by `0`.)
/// ```
///
/// For an immutable forwarding newtype:
/// ```
/// # use crate::forward_newtype;
/// # use core::borrow::*;
///
/// /// A mutable buffer newtype over an array.
/// struct Data([u8; 16]);
/// forward_newtype!(ref Buffer => [u8], 0); // Generates `Borrow<[u8]>` and `Deref<Target=[u8]>` impls for `Buffer` that return `<& self.>0` (as specified by `0`.) Immutable access only is specified by `ref`.
/// ```
///
/// ## Consuming into inner
/// To generate an `into_inner(self) -> T` inherent impl for the type, the syntax `forward_newtype!(move [const] Type => Inner, accessor)` can be used.
/// If `const` is passed, then the `into_inner()` function will be a `const fn`, if not, then it won't be.
///
/// To combine with ref-forwarding accessors, the syntax `forward_newtype!(move [const] {ref/mut} Type => Inner, accessor)` can be used to generate them all; the `Borrow`, `BorrowMut`, `Deref`, `DerefMut` and `pub [const] fn into_inner()`.
/// This is the most likely to be useful.
///
/// If you need a seperate `into_inner()` impl, you can either not use the `move` declarator, or use the `ref`/`mut` accessor generator in a different statement than the `move` one:
/// ```
/// # use crate::forward_newtype;
/// # use core::borrow::*;
///
/// /// A mutable buffer newtype over an array.
/// struct Buffer([u8; 16]);
/// forward_newtype!(mut Buffer => [u8], 0); // Generate a mutable & immutable forwarding ref to a slice of bytes.
/// forward_newtype!(move const Buffer => [u8; 16], 0); // Generate a seperately typed `into_inner()` that returns the sized array.
/// ```
macro_rules! forward_newtype {
(ref $type:ty => $inner:ty, $($expr:tt)+) => {
impl Borrow<$inner> for $type
{
#[inline]
fn borrow(&self) -> &$inner
{
&self.$($expr)+
}
}
impl ::std::ops::Deref for $type {
type Target = $inner;
#[inline]
fn deref(&self) -> &Self::Target {
self.borrow()
}
}
};
(mut $type:ty => $inner:ty, $($expr:tt)+) => {
forward_newtype!(ref $type => $inner, $($expr)+);
impl BorrowMut<$inner> for $type
{
#[inline]
fn borrow_mut(&mut self) -> &mut $inner
{
&mut self.$($expr)+
}
}
impl ::std::ops::DerefMut for $type {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.borrow_mut()
}
}
};
(move const $type:ty => $inner:ty, $($expr:tt)+) => {
impl $type {
/// Consume into the inner value.
pub const fn into_inner(self) -> $inner {
self.$($expr)+
}
}
};
(move $type:ty => $inner:ty, $($expr:tt)+) => {
impl $type {
/// Consume into the inner value.
pub fn into_inner(self) -> $inner {
self.$($expr)+
}
}
};
(move const ref $type:ty => $inner:ty, $($expr:tt)+) => {
forward_newtype!(move const $type => $inner, $($expr)+);
forward_newtype!(ref $type => $inner, $($expr)+);
};
(move ref $type:ty => $inner:ty, $($expr:tt)+) => {
forward_newtype!(move $type => $inner, $($expr)+);
forward_newtype!(ref $type => $inner, $($expr)+);
};
(move const mut $type:ty => $inner:ty, $($expr:tt)+) => {
forward_newtype!(move const $type => $inner, $($expr)+);
forward_newtype!(mut $type => $inner, $($expr)+);
};
(move mut $type:ty => $inner:ty, $($expr:tt)+) => {
forward_newtype!(move $type => $inner, $($expr)+);
forward_newtype!(mut $type => $inner, $($expr)+);
};
}
/// The default bottom type.
///
/// To use the `unwrap_infallible()`-like interface, functions that return `-> !` should be changed to `-> Never`.

@ -11,6 +11,65 @@ use std::{
/// TODO: Make this comptime env-var configurable (`option_env!()`) on debug builds. (See `SEARCH_CAP_GROW`.)
const CACHELINE_SIZE: usize = std::mem::size_of::<crossbeam_utils::CachePadded<u8>>();
/// A buffer that takes up exactly one cache-line.
///
/// This type is not `Copy` to ensure copies are made safely. `clone()` is trivial, and to copy explicitly in a const context use `.copied()`
///
/// # Alignment
/// Note that the buffer is *not* 1-cacheline aligned itself by default.
/// To ensure its alignment, you should use `crossbeam_utils::CachePadded<CachelineBuffer>` (or the type-alias `AlignedCachelineBuffer`.)
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct CachelineBuffer([u8; CACHELINE_SIZE]);
impl Default for CachelineBuffer
{
#[inline]
fn default() -> Self
{
Self::new()
}
}
/// A buffer that takes up exactly one cache-line, which is itself aligned to 1 cacheline.
pub type AlignedCachelineBuffer = crossbeam_utils::CachePadded<CachelineBuffer>;
impl CachelineBuffer {
/// The size of the buffer (1 cacheline of bytes.)
pub const SIZE: usize = CACHELINE_SIZE;
/// Create a new, empty buffer.
#[inline]
pub const fn new() -> Self
{
Self([0; Self::SIZE])
}
/// Clone this value.
///
/// This is a `const fn` explicit trivial copy of the data.
#[inline]
pub const fn copied(&self) -> Self
{
Self(self.0)
}
/// Get a reference to the byte array.
pub const fn as_bytes(&self) -> &[u8; Self::SIZE]
{
&self.0
}
}
forward_newtype!(mut CachelineBuffer => [u8], 0);
forward_newtype!(move const CachelineBuffer => [u8; CACHELINE_SIZE], 0);
const _: () = {
debug_assert!(CachelineBuffer::SIZE > std::mem::size_of::<u8>(), "Invalid cacheline-padding size (`CACHELINE_SIZE`)");
//debug_assert!(CACHELINE_SIZE == 128, "Unexpected `CACHELINE_SIZE`");
};
/// Grow capacity exponentially when search fails.
///
/// TODO: Make this comptime env-var settable (`option_env!()`) on debug builds.
@ -331,6 +390,8 @@ where S: MidpointFBSearcher<u8>
#[cfg(test)]
mod test
{
use super::*;
use std::hint::black_box;
//TODO: Add a generic randomised lorem-ipsum-like text data generator & a generic assertion tester that can take a unique `MidpointFBSearcher`.
#[test]
@ -360,4 +421,6 @@ mod test
{
unimplemented!("A pure async parallel searcher has not yet been implemented")
}
//TODO: Benchmarking the searchers' configuration about capacity size, growth and bounding.
}

Loading…
Cancel
Save