Improve slab_rc implementation (#162)

This commit is contained in:
Ryan Johnson 2022-11-29 17:14:04 -08:00 committed by GitHub
parent 58f8197913
commit 0e28e5ad05
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 83 additions and 91 deletions

View file

@ -56,16 +56,6 @@ impl<C: Config> PlayerLists<C> {
(PlayerListId(key), pl) (PlayerListId(key), pl)
} }
/// Returns the number of player lists.
pub fn len(&self) -> usize {
self.slab.len()
}
/// Returns `true` if there are no player lists.
pub fn is_empty(&self) -> bool {
self.slab.len() == 0
}
/// Gets a shared reference to the player list with the given player list /// Gets a shared reference to the player list with the given player list
/// ID. /// ID.
/// ///
@ -83,8 +73,7 @@ impl<C: Config> PlayerLists<C> {
} }
pub(crate) fn update(&mut self) { pub(crate) fn update(&mut self) {
self.slab.collect_garbage(); for pl in self.slab.iter_mut() {
for (_, pl) in self.slab.iter_mut() {
for entry in pl.entries.values_mut() { for entry in pl.entries.values_mut() {
entry.bits = EntryBits::new(); entry.bits = EntryBits::new();
} }

View file

@ -5,32 +5,80 @@ use std::hash::{Hash, Hasher};
use std::iter::FusedIterator; use std::iter::FusedIterator;
use std::sync::Arc; use std::sync::Arc;
use rayon::iter::{IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator}; use flume::{Receiver, Sender};
use crate::slab::Slab;
#[derive(Clone, Debug)]
pub struct RcSlab<T> {
slab: Slab<Slot<T>>,
}
#[derive(Debug)] #[derive(Debug)]
struct Slot<T> { pub struct RcSlab<T> {
value: T, entries: Vec<T>,
key: Key, free_send: Sender<usize>,
free_recv: Receiver<usize>,
} }
impl<T: Clone> Clone for Slot<T> { impl<T> RcSlab<T> {
fn clone(&self) -> Self { pub fn new() -> Self {
let (free_send, free_recv) = flume::unbounded();
Self { Self {
value: self.value.clone(), entries: Vec::new(),
key: Key(Arc::new(*self.key.0)), free_send,
free_recv,
} }
} }
pub fn insert(&mut self, value: T) -> (Key, &mut T) {
match self.free_recv.try_recv() {
Ok(idx) => {
self.entries[idx] = value;
let k = Key(Arc::new(KeyInner {
index: idx,
free_send: self.free_send.clone(),
}));
(k, &mut self.entries[idx])
}
Err(_) => {
let idx = self.entries.len();
self.entries.push(value);
let k = Key(Arc::new(KeyInner {
index: idx,
free_send: self.free_send.clone(),
}));
(k, &mut self.entries[idx])
}
}
}
pub fn get(&self, key: &Key) -> &T {
&self.entries[key.0.index]
}
pub fn get_mut(&mut self, key: &Key) -> &mut T {
&mut self.entries[key.0.index]
}
pub fn iter(&self) -> impl FusedIterator<Item = &T> + Clone + '_ {
self.entries.iter()
}
pub fn iter_mut(&mut self) -> impl FusedIterator<Item = &mut T> + '_ {
self.entries.iter_mut()
}
} }
#[derive(Clone, Eq, Debug)] #[derive(Clone, Debug)]
pub struct Key(Arc<usize>); pub struct Key(Arc<KeyInner>);
#[derive(Debug)]
struct KeyInner {
index: usize,
free_send: Sender<usize>,
}
impl Drop for KeyInner {
fn drop(&mut self) {
let _ = self.free_send.send(self.index);
}
}
impl PartialEq for Key { impl PartialEq for Key {
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
@ -38,6 +86,8 @@ impl PartialEq for Key {
} }
} }
impl Eq for Key {}
impl PartialOrd for Key { impl PartialOrd for Key {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Arc::as_ptr(&self.0).partial_cmp(&Arc::as_ptr(&other.0)) Arc::as_ptr(&self.0).partial_cmp(&Arc::as_ptr(&other.0))
@ -56,70 +106,23 @@ impl Hash for Key {
} }
} }
impl<T> RcSlab<T> { #[cfg(test)]
pub const fn new() -> Self { pub mod tests {
Self { slab: Slab::new() } use super::*;
}
pub fn get(&self, key: &Key) -> &T { #[test]
let slot = self.slab.get(*key.0).expect("invalid key"); fn rc_slab_insert() {
debug_assert_eq!(&slot.key, key, "invalid key"); let mut slab = RcSlab::new();
let (k, v) = slab.insert(123);
assert_eq!(*v, 123);
&slot.value let k2 = slab.insert(456).0;
} assert_ne!(k, k2);
assert_eq!(slab.entries.len(), 2);
pub fn get_mut(&mut self, key: &Key) -> &mut T { drop(k);
let slot = self.slab.get_mut(*key.0).expect("invalid key"); drop(k2);
debug_assert_eq!(&slot.key, key, "invalid key"); slab.insert(789);
assert_eq!(slab.entries.len(), 2);
&mut slot.value
}
pub fn len(&self) -> usize {
self.slab.len()
}
pub fn insert(&mut self, value: T) -> (Key, &mut T) {
let (_, slot) = self.slab.insert_with(|idx| Slot {
value,
key: Key(Arc::new(idx)),
});
(slot.key.clone(), &mut slot.value)
}
pub fn iter(&self) -> impl ExactSizeIterator<Item = (&Key, &T)> + FusedIterator + Clone + '_ {
self.slab.iter().map(|(_, slot)| (&slot.key, &slot.value))
}
pub fn iter_mut(
&mut self,
) -> impl ExactSizeIterator<Item = (&Key, &mut T)> + FusedIterator + '_ {
self.slab
.iter_mut()
.map(|(_, slot)| (&slot.key, &mut slot.value))
}
pub fn par_iter(&self) -> impl ParallelIterator<Item = (&Key, &T)> + Clone + '_
where
T: Sync,
{
self.slab
.par_iter()
.map(|(_, slot)| (&slot.key, &slot.value))
}
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (&Key, &mut T)> + '_
where
T: Send + Sync,
{
self.slab
.par_iter_mut()
.map(|(_, slot)| (&slot.key, &mut slot.value))
}
pub fn collect_garbage(&mut self) {
self.slab
.retain(|_, slot| Arc::strong_count(&slot.key.0) > 1);
} }
} }