mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 14:31:30 +11:00
Improve slab_rc implementation (#162)
This commit is contained in:
parent
58f8197913
commit
0e28e5ad05
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
161
src/slab_rc.rs
161
src/slab_rc.rs
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue