summaryrefslogtreecommitdiffstats
path: root/tokio/src/util/slab/page.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tokio/src/util/slab/page.rs')
-rw-r--r--tokio/src/util/slab/page.rs187
1 files changed, 0 insertions, 187 deletions
diff --git a/tokio/src/util/slab/page.rs b/tokio/src/util/slab/page.rs
deleted file mode 100644
index 0000e934..00000000
--- a/tokio/src/util/slab/page.rs
+++ /dev/null
@@ -1,187 +0,0 @@
-use crate::loom::cell::UnsafeCell;
-use crate::util::slab::{Address, Entry, Slot, TransferStack, INITIAL_PAGE_SIZE};
-
-use std::fmt;
-
-/// Data accessed only by the thread that owns the shard.
-pub(crate) struct Local {
- head: UnsafeCell<usize>,
-}
-
-/// Data accessed by any thread.
-pub(crate) struct Shared<T> {
- remote: TransferStack,
- size: usize,
- prev_sz: usize,
- slab: UnsafeCell<Option<Box<[Slot<T>]>>>,
-}
-
-/// Returns the size of the page at index `n`
-pub(super) fn size(n: usize) -> usize {
- INITIAL_PAGE_SIZE << n
-}
-
-impl Local {
- pub(crate) fn new() -> Self {
- Self {
- head: UnsafeCell::new(0),
- }
- }
-
- fn head(&self) -> usize {
- self.head.with(|head| unsafe { *head })
- }
-
- fn set_head(&self, new_head: usize) {
- self.head.with_mut(|head| unsafe {
- *head = new_head;
- })
- }
-}
-
-impl<T: Entry> Shared<T> {
- pub(crate) fn new(size: usize, prev_sz: usize) -> Shared<T> {
- Self {
- prev_sz,
- size,
- remote: TransferStack::new(),
- slab: UnsafeCell::new(None),
- }
- }
-
- /// Allocates storage for this page if it does not allready exist.
- ///
- /// This requires unique access to the page (e.g. it is called from the
- /// thread that owns the page, or, in the case of `SingleShard`, while the
- /// lock is held). In order to indicate this, a reference to the page's
- /// `Local` data is taken by this function; the `Local` argument is not
- /// actually used, but requiring it ensures that this is only called when
- /// local access is held.
- #[cold]
- fn alloc_page(&self, _: &Local) {
- debug_assert!(self.slab.with(|s| unsafe { (*s).is_none() }));
-
- let mut slab = Vec::with_capacity(self.size);
- slab.extend((1..self.size).map(Slot::new));
- slab.push(Slot::new(Address::NULL));
-
- self.slab.with_mut(|s| {
- // this mut access is safe — it only occurs to initially
- // allocate the page, which only happens on this thread; if the
- // page has not yet been allocated, other threads will not try
- // to access it yet.
- unsafe {
- *s = Some(slab.into_boxed_slice());
- }
- });
- }
-
- pub(crate) fn alloc(&self, local: &Local) -> Option<Address> {
- let head = local.head();
-
- // are there any items on the local free list? (fast path)
- let head = if head < self.size {
- head
- } else {
- // if the local free list is empty, pop all the items on the remote
- // free list onto the local free list.
- self.remote.pop_all()?
- };
-
- // if the head is still null, both the local and remote free lists are
- // empty --- we can't fit any more items on this page.
- if head == Address::NULL {
- return None;
- }
-
- // do we need to allocate storage for this page?
- let page_needs_alloc = self.slab.with(|s| unsafe { (*s).is_none() });
- if page_needs_alloc {
- self.alloc_page(local);
- }
-
- let gen = self.slab.with(|slab| {
- let slab = unsafe { &*(slab) }
- .as_ref()
- .expect("page must have been allocated to alloc!");
-
- let slot = &slab[head];
-
- local.set_head(slot.next());
- slot.generation()
- });
-
- let index = head + self.prev_sz;
-
- Some(Address::new(index, gen))
- }
-
- pub(crate) fn get(&self, addr: Address) -> Option<&T> {
- let page_offset = addr.slot() - self.prev_sz;
-
- self.slab
- .with(|slab| unsafe { &*slab }.as_ref()?.get(page_offset))
- .map(|slot| slot.get())
- }
-
- pub(crate) fn remove_local(&self, local: &Local, addr: Address) {
- let offset = addr.slot() - self.prev_sz;
-
- self.slab.with(|slab| {
- let slab = unsafe { &*slab }.as_ref();
-
- let slot = if let Some(slot) = slab.and_then(|slab| slab.get(offset)) {
- slot
- } else {
- return;
- };
-
- if slot.reset(addr.generation()) {
- slot.set_next(local.head());
- local.set_head(offset);
- }
- })
- }
-
- pub(crate) fn remove_remote(&self, addr: Address) {
- let offset = addr.slot() - self.prev_sz;
-
- self.slab.with(|slab| {
- let slab = unsafe { &*slab }.as_ref();
-
- let slot = if let Some(slot) = slab.and_then(|slab| slab.get(offset)) {
- slot
- } else {
- return;
- };
-
- if !slot.reset(addr.generation()) {
- return;
- }
-
- self.remote.push(offset, |next| slot.set_next(next));
- })
- }
-}
-
-impl fmt::Debug for Local {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- self.head.with(|head| {
- let head = unsafe { *head };
- f.debug_struct("Local")
- .field("head", &format_args!("{:#0x}", head))
- .finish()
- })
- }
-}
-
-impl<T> fmt::Debug for Shared<T> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("Shared")
- .field("remote", &self.remote)
- .field("prev_sz", &self.prev_sz)
- .field("size", &self.size)
- // .field("slab", &self.slab)
- .finish()
- }
-}