1 //! A lock-free concurrent slab. 2 //! 3 //! Slabs provide pre-allocated storage for many instances of a single data 4 //! type. When a large number of values of a single type are required, 5 //! this can be more efficient than allocating each item individually. Since the 6 //! allocated items are the same size, memory fragmentation is reduced, and 7 //! creating and removing new items can be very cheap. 8 //! 9 //! This crate implements a lock-free concurrent slab, indexed by `usize`s. 10 //! 11 //! ## Usage 12 //! 13 //! First, add this to your `Cargo.toml`: 14 //! 15 //! ```toml 16 //! sharded-slab = "0.1.1" 17 //! ``` 18 //! 19 //! This crate provides two types, [`Slab`] and [`Pool`], which provide 20 //! slightly different APIs for using a sharded slab. 21 //! 22 //! [`Slab`] implements a slab for _storing_ small types, sharing them between 23 //! threads, and accessing them by index. New entries are allocated by 24 //! [inserting] data, moving it in by value. Similarly, entries may be 25 //! deallocated by [taking] from the slab, moving the value out. This API is 26 //! similar to a `Vec<Option<T>>`, but allowing lock-free concurrent insertion 27 //! and removal. 28 //! 29 //! In contrast, the [`Pool`] type provides an [object pool] style API for 30 //! _reusing storage_. Rather than constructing values and moving them into the 31 //! pool, as with [`Slab`], [allocating an entry][create] from the pool takes a 32 //! closure that's provided with a mutable reference to initialize the entry in 33 //! place. When entries are deallocated, they are [cleared] in place. Types 34 //! which own a heap allocation can be cleared by dropping any _data_ they 35 //! store, but retaining any previously-allocated capacity. This means that a 36 //! [`Pool`] may be used to reuse a set of existing heap allocations, reducing 37 //! allocator load. 38 //! 39 //! [inserting]: Slab::insert 40 //! [taking]: Slab::take 41 //! [create]: Pool::create 42 //! [cleared]: Clear 43 //! [object pool]: https://en.wikipedia.org/wiki/Object_pool_pattern 44 //! 45 //! # Examples 46 //! 47 //! Inserting an item into the slab, returning an index: 48 //! ```rust 49 //! # use sharded_slab::Slab; 50 //! let slab = Slab::new(); 51 //! 52 //! let key = slab.insert("hello world").unwrap(); 53 //! assert_eq!(slab.get(key).unwrap(), "hello world"); 54 //! ``` 55 //! 56 //! To share a slab across threads, it may be wrapped in an `Arc`: 57 //! ```rust 58 //! # use sharded_slab::Slab; 59 //! use std::sync::Arc; 60 //! let slab = Arc::new(Slab::new()); 61 //! 62 //! let slab2 = slab.clone(); 63 //! let thread2 = std::thread::spawn(move || { 64 //! let key = slab2.insert("hello from thread two").unwrap(); 65 //! assert_eq!(slab2.get(key).unwrap(), "hello from thread two"); 66 //! key 67 //! }); 68 //! 69 //! let key1 = slab.insert("hello from thread one").unwrap(); 70 //! assert_eq!(slab.get(key1).unwrap(), "hello from thread one"); 71 //! 72 //! // Wait for thread 2 to complete. 73 //! let key2 = thread2.join().unwrap(); 74 //! 75 //! // The item inserted by thread 2 remains in the slab. 76 //! assert_eq!(slab.get(key2).unwrap(), "hello from thread two"); 77 //!``` 78 //! 79 //! If items in the slab must be mutated, a `Mutex` or `RwLock` may be used for 80 //! each item, providing granular locking of items rather than of the slab: 81 //! 82 //! ```rust 83 //! # use sharded_slab::Slab; 84 //! use std::sync::{Arc, Mutex}; 85 //! let slab = Arc::new(Slab::new()); 86 //! 87 //! let key = slab.insert(Mutex::new(String::from("hello world"))).unwrap(); 88 //! 89 //! let slab2 = slab.clone(); 90 //! let thread2 = std::thread::spawn(move || { 91 //! let hello = slab2.get(key).expect("item missing"); 92 //! let mut hello = hello.lock().expect("mutex poisoned"); 93 //! *hello = String::from("hello everyone!"); 94 //! }); 95 //! 96 //! thread2.join().unwrap(); 97 //! 98 //! let hello = slab.get(key).expect("item missing"); 99 //! let mut hello = hello.lock().expect("mutex poisoned"); 100 //! assert_eq!(hello.as_str(), "hello everyone!"); 101 //! ``` 102 //! 103 //! # Configuration 104 //! 105 //! For performance reasons, several values used by the slab are calculated as 106 //! constants. In order to allow users to tune the slab's parameters, we provide 107 //! a [`Config`] trait which defines these parameters as associated `consts`. 108 //! The `Slab` type is generic over a `C: Config` parameter. 109 //! 110 //! [`Config`]: trait.Config.html 111 //! 112 //! # Comparison with Similar Crates 113 //! 114 //! - [`slab`]: Carl Lerche's `slab` crate provides a slab implementation with a 115 //! similar API, implemented by storing all data in a single vector. 116 //! 117 //! Unlike `sharded_slab`, inserting and removing elements from the slab 118 //! requires mutable access. This means that if the slab is accessed 119 //! concurrently by multiple threads, it is necessary for it to be protected 120 //! by a `Mutex` or `RwLock`. Items may not be inserted or removed (or 121 //! accessed, if a `Mutex` is used) concurrently, even when they are 122 //! unrelated. In many cases, the lock can become a significant bottleneck. On 123 //! the other hand, this crate allows separate indices in the slab to be 124 //! accessed, inserted, and removed concurrently without requiring a global 125 //! lock. Therefore, when the slab is shared across multiple threads, this 126 //! crate offers significantly better performance than `slab`. 127 //! 128 //! However, the lock free slab introduces some additional constant-factor 129 //! overhead. This means that in use-cases where a slab is _not_ shared by 130 //! multiple threads and locking is not required, this crate will likely offer 131 //! slightly worse performance. 132 //! 133 //! In summary: `sharded-slab` offers significantly improved performance in 134 //! concurrent use-cases, while `slab` should be preferred in single-threaded 135 //! use-cases. 136 //! 137 //! [`slab`]: https://crates.io/crates/loom 138 //! 139 //! # Safety and Correctness 140 //! 141 //! Most implementations of lock-free data structures in Rust require some 142 //! amount of unsafe code, and this crate is not an exception. In order to catch 143 //! potential bugs in this unsafe code, we make use of [`loom`], a 144 //! permutation-testing tool for concurrent Rust programs. All `unsafe` blocks 145 //! this crate occur in accesses to `loom` `UnsafeCell`s. This means that when 146 //! those accesses occur in this crate's tests, `loom` will assert that they are 147 //! valid under the C11 memory model across multiple permutations of concurrent 148 //! executions of those tests. 149 //! 150 //! In order to guard against the [ABA problem][aba], this crate makes use of 151 //! _generational indices_. Each slot in the slab tracks a generation counter 152 //! which is incremented every time a value is inserted into that slot, and the 153 //! indices returned by [`Slab::insert`] include the generation of the slot when 154 //! the value was inserted, packed into the high-order bits of the index. This 155 //! ensures that if a value is inserted, removed, and a new value is inserted 156 //! into the same slot in the slab, the key returned by the first call to 157 //! `insert` will not map to the new value. 158 //! 159 //! Since a fixed number of bits are set aside to use for storing the generation 160 //! counter, the counter will wrap around after being incremented a number of 161 //! times. To avoid situations where a returned index lives long enough to see the 162 //! generation counter wrap around to the same value, it is good to be fairly 163 //! generous when configuring the allocation of index bits. 164 //! 165 //! [`loom`]: https://crates.io/crates/loom 166 //! [aba]: https://en.wikipedia.org/wiki/ABA_problem 167 //! [`Slab::insert`]: struct.Slab.html#method.insert 168 //! 169 //! # Performance 170 //! 171 //! These graphs were produced by [benchmarks] of the sharded slab implementation, 172 //! using the [`criterion`] crate. 173 //! 174 //! The first shows the results of a benchmark where an increasing number of 175 //! items are inserted and then removed into a slab concurrently by five 176 //! threads. It compares the performance of the sharded slab implementation 177 //! with a `RwLock<slab::Slab>`: 178 //! 179 //! <img width="1124" alt="Screen Shot 2019-10-01 at 5 09 49 PM" src="https://user-images.githubusercontent.com/2796466/66078398-cd6c9f80-e516-11e9-9923-0ed6292e8498.png"> 180 //! 181 //! The second graph shows the results of a benchmark where an increasing 182 //! number of items are inserted and then removed by a _single_ thread. It 183 //! compares the performance of the sharded slab implementation with an 184 //! `RwLock<slab::Slab>` and a `mut slab::Slab`. 185 //! 186 //! <img width="925" alt="Screen Shot 2019-10-01 at 5 13 45 PM" src="https://user-images.githubusercontent.com/2796466/66078469-f0974f00-e516-11e9-95b5-f65f0aa7e494.png"> 187 //! 188 //! These benchmarks demonstrate that, while the sharded approach introduces 189 //! a small constant-factor overhead, it offers significantly better 190 //! performance across concurrent accesses. 191 //! 192 //! [benchmarks]: https://github.com/hawkw/sharded-slab/blob/master/benches/bench.rs 193 //! [`criterion`]: https://crates.io/crates/criterion 194 //! 195 //! # Implementation Notes 196 //! 197 //! See [this page](crate::implementation) for details on this crate's design 198 //! and implementation. 199 //! 200 #![doc(html_root_url = "https://docs.rs/sharded-slab/0.1.4")] 201 #![warn(missing_debug_implementations, missing_docs)] 202 #![cfg_attr(docsrs, warn(rustdoc::broken_intra_doc_links))] 203 #[macro_use] 204 mod macros; 205 206 pub mod implementation; 207 pub mod pool; 208 209 pub(crate) mod cfg; 210 pub(crate) mod sync; 211 212 mod clear; 213 mod iter; 214 mod page; 215 mod shard; 216 mod tid; 217 218 pub use self::{ 219 cfg::{Config, DefaultConfig}, 220 clear::Clear, 221 iter::UniqueIter, 222 }; 223 #[doc(inline)] 224 pub use pool::Pool; 225 226 pub(crate) use tid::Tid; 227 228 use cfg::CfgPrivate; 229 use shard::Shard; 230 use std::{fmt, marker::PhantomData, ptr, sync::Arc}; 231 232 /// A sharded slab. 233 /// 234 /// See the [crate-level documentation](crate) for details on using this type. 235 pub struct Slab<T, C: cfg::Config = DefaultConfig> { 236 shards: shard::Array<Option<T>, C>, 237 _cfg: PhantomData<C>, 238 } 239 240 /// A handle that allows access to an occupied entry in a [`Slab`]. 241 /// 242 /// While the guard exists, it indicates to the slab that the item the guard 243 /// references is currently being accessed. If the item is removed from the slab 244 /// while a guard exists, the removal will be deferred until all guards are 245 /// dropped. 246 pub struct Entry<'a, T, C: cfg::Config = DefaultConfig> { 247 inner: page::slot::Guard<Option<T>, C>, 248 value: ptr::NonNull<T>, 249 shard: &'a Shard<Option<T>, C>, 250 key: usize, 251 } 252 253 /// A handle to a vacant entry in a [`Slab`]. 254 /// 255 /// `VacantEntry` allows constructing values with the key that they will be 256 /// assigned to. 257 /// 258 /// # Examples 259 /// 260 /// ``` 261 /// # use sharded_slab::Slab; 262 /// let mut slab = Slab::new(); 263 /// 264 /// let hello = { 265 /// let entry = slab.vacant_entry().unwrap(); 266 /// let key = entry.key(); 267 /// 268 /// entry.insert((key, "hello")); 269 /// key 270 /// }; 271 /// 272 /// assert_eq!(hello, slab.get(hello).unwrap().0); 273 /// assert_eq!("hello", slab.get(hello).unwrap().1); 274 /// ``` 275 #[derive(Debug)] 276 pub struct VacantEntry<'a, T, C: cfg::Config = DefaultConfig> { 277 inner: page::slot::InitGuard<Option<T>, C>, 278 key: usize, 279 _lt: PhantomData<&'a ()>, 280 } 281 282 /// An owned reference to an occupied entry in a [`Slab`]. 283 /// 284 /// While the guard exists, it indicates to the slab that the item the guard 285 /// references is currently being accessed. If the item is removed from the slab 286 /// while the guard exists, the removal will be deferred until all guards are 287 /// dropped. 288 /// 289 /// Unlike [`Entry`], which borrows the slab, an `OwnedEntry` clones the [`Arc`] 290 /// around the slab. Therefore, it keeps the slab from being dropped until all 291 /// such guards have been dropped. This means that an `OwnedEntry` may be held for 292 /// an arbitrary lifetime. 293 /// 294 /// # Examples 295 /// 296 /// ``` 297 /// # use sharded_slab::Slab; 298 /// use std::sync::Arc; 299 /// 300 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 301 /// let key = slab.insert("hello world").unwrap(); 302 /// 303 /// // Look up the created key, returning an `OwnedEntry`. 304 /// let value = slab.clone().get_owned(key).unwrap(); 305 /// 306 /// // Now, the original `Arc` clone of the slab may be dropped, but the 307 /// // returned `OwnedEntry` can still access the value. 308 /// assert_eq!(value, "hello world"); 309 /// ``` 310 /// 311 /// Unlike [`Entry`], an `OwnedEntry` may be stored in a struct which must live 312 /// for the `'static` lifetime: 313 /// 314 /// ``` 315 /// # use sharded_slab::Slab; 316 /// use sharded_slab::OwnedEntry; 317 /// use std::sync::Arc; 318 /// 319 /// pub struct MyStruct { 320 /// entry: OwnedEntry<&'static str>, 321 /// // ... other fields ... 322 /// } 323 /// 324 /// // Suppose this is some arbitrary function which requires a value that 325 /// // lives for the 'static lifetime... 326 /// fn function_requiring_static<T: 'static>(t: &T) { 327 /// // ... do something extremely important and interesting ... 328 /// } 329 /// 330 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 331 /// let key = slab.insert("hello world").unwrap(); 332 /// 333 /// // Look up the created key, returning an `OwnedEntry`. 334 /// let entry = slab.clone().get_owned(key).unwrap(); 335 /// let my_struct = MyStruct { 336 /// entry, 337 /// // ... 338 /// }; 339 /// 340 /// // We can use `my_struct` anywhere where it is required to have the 341 /// // `'static` lifetime: 342 /// function_requiring_static(&my_struct); 343 /// ``` 344 /// 345 /// `OwnedEntry`s may be sent between threads: 346 /// 347 /// ``` 348 /// # use sharded_slab::Slab; 349 /// use std::{thread, sync::Arc}; 350 /// 351 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 352 /// let key = slab.insert("hello world").unwrap(); 353 /// 354 /// // Look up the created key, returning an `OwnedEntry`. 355 /// let value = slab.clone().get_owned(key).unwrap(); 356 /// 357 /// thread::spawn(move || { 358 /// assert_eq!(value, "hello world"); 359 /// // ... 360 /// }).join().unwrap(); 361 /// ``` 362 /// 363 /// [`get`]: Slab::get 364 /// [`Arc`]: std::sync::Arc 365 pub struct OwnedEntry<T, C = DefaultConfig> 366 where 367 C: cfg::Config, 368 { 369 inner: page::slot::Guard<Option<T>, C>, 370 value: ptr::NonNull<T>, 371 slab: Arc<Slab<T, C>>, 372 key: usize, 373 } 374 375 impl<T> Slab<T> { 376 /// Returns a new slab with the default configuration parameters. new() -> Self377 pub fn new() -> Self { 378 Self::new_with_config() 379 } 380 381 /// Returns a new slab with the provided configuration parameters. new_with_config<C: cfg::Config>() -> Slab<T, C>382 pub fn new_with_config<C: cfg::Config>() -> Slab<T, C> { 383 C::validate(); 384 Slab { 385 shards: shard::Array::new(), 386 _cfg: PhantomData, 387 } 388 } 389 } 390 391 impl<T, C: cfg::Config> Slab<T, C> { 392 /// The number of bits in each index which are used by the slab. 393 /// 394 /// If other data is packed into the `usize` indices returned by 395 /// [`Slab::insert`], user code is free to use any bits higher than the 396 /// `USED_BITS`-th bit freely. 397 /// 398 /// This is determined by the [`Config`] type that configures the slab's 399 /// parameters. By default, all bits are used; this can be changed by 400 /// overriding the [`Config::RESERVED_BITS`][res] constant. 401 /// 402 /// [res]: crate::Config#RESERVED_BITS 403 pub const USED_BITS: usize = C::USED_BITS; 404 405 /// Inserts a value into the slab, returning the integer index at which that 406 /// value was inserted. This index can then be used to access the entry. 407 /// 408 /// If this function returns `None`, then the shard for the current thread 409 /// is full and no items can be added until some are removed, or the maximum 410 /// number of shards has been reached. 411 /// 412 /// # Examples 413 /// ```rust 414 /// # use sharded_slab::Slab; 415 /// let slab = Slab::new(); 416 /// 417 /// let key = slab.insert("hello world").unwrap(); 418 /// assert_eq!(slab.get(key).unwrap(), "hello world"); 419 /// ``` insert(&self, value: T) -> Option<usize>420 pub fn insert(&self, value: T) -> Option<usize> { 421 let (tid, shard) = self.shards.current(); 422 test_println!("insert {:?}", tid); 423 let mut value = Some(value); 424 shard 425 .init_with(|idx, slot| { 426 let gen = slot.insert(&mut value)?; 427 Some(gen.pack(idx)) 428 }) 429 .map(|idx| tid.pack(idx)) 430 } 431 432 /// Return a handle to a vacant entry allowing for further manipulation. 433 /// 434 /// This function is useful when creating values that must contain their 435 /// slab index. The returned [`VacantEntry`] reserves a slot in the slab and 436 /// is able to return the index of the entry. 437 /// 438 /// # Examples 439 /// 440 /// ``` 441 /// # use sharded_slab::Slab; 442 /// let mut slab = Slab::new(); 443 /// 444 /// let hello = { 445 /// let entry = slab.vacant_entry().unwrap(); 446 /// let key = entry.key(); 447 /// 448 /// entry.insert((key, "hello")); 449 /// key 450 /// }; 451 /// 452 /// assert_eq!(hello, slab.get(hello).unwrap().0); 453 /// assert_eq!("hello", slab.get(hello).unwrap().1); 454 /// ``` vacant_entry(&self) -> Option<VacantEntry<'_, T, C>>455 pub fn vacant_entry(&self) -> Option<VacantEntry<'_, T, C>> { 456 let (tid, shard) = self.shards.current(); 457 test_println!("vacant_entry {:?}", tid); 458 shard.init_with(|idx, slot| { 459 let inner = slot.init()?; 460 let key = inner.generation().pack(tid.pack(idx)); 461 Some(VacantEntry { 462 inner, 463 key, 464 _lt: PhantomData, 465 }) 466 }) 467 } 468 469 /// Remove the value at the given index in the slab, returning `true` if a 470 /// value was removed. 471 /// 472 /// Unlike [`take`], this method does _not_ block the current thread until 473 /// the value can be removed. Instead, if another thread is currently 474 /// accessing that value, this marks it to be removed by that thread when it 475 /// finishes accessing the value. 476 /// 477 /// # Examples 478 /// 479 /// ```rust 480 /// let slab = sharded_slab::Slab::new(); 481 /// let key = slab.insert("hello world").unwrap(); 482 /// 483 /// // Remove the item from the slab. 484 /// assert!(slab.remove(key)); 485 /// 486 /// // Now, the slot is empty. 487 /// assert!(!slab.contains(key)); 488 /// ``` 489 /// 490 /// ```rust 491 /// use std::sync::Arc; 492 /// 493 /// let slab = Arc::new(sharded_slab::Slab::new()); 494 /// let key = slab.insert("hello world").unwrap(); 495 /// 496 /// let slab2 = slab.clone(); 497 /// let thread2 = std::thread::spawn(move || { 498 /// // Depending on when this thread begins executing, the item may 499 /// // or may not have already been removed... 500 /// if let Some(item) = slab2.get(key) { 501 /// assert_eq!(item, "hello world"); 502 /// } 503 /// }); 504 /// 505 /// // The item will be removed by thread2 when it finishes accessing it. 506 /// assert!(slab.remove(key)); 507 /// 508 /// thread2.join().unwrap(); 509 /// assert!(!slab.contains(key)); 510 /// ``` 511 /// [`take`]: Slab::take remove(&self, idx: usize) -> bool512 pub fn remove(&self, idx: usize) -> bool { 513 // The `Drop` impl for `Entry` calls `remove_local` or `remove_remote` based 514 // on where the guard was dropped from. If the dropped guard was the last one, this will 515 // call `Slot::remove_value` which actually clears storage. 516 let tid = C::unpack_tid(idx); 517 518 test_println!("rm_deferred {:?}", tid); 519 let shard = self.shards.get(tid.as_usize()); 520 if tid.is_current() { 521 shard.map(|shard| shard.remove_local(idx)).unwrap_or(false) 522 } else { 523 shard.map(|shard| shard.remove_remote(idx)).unwrap_or(false) 524 } 525 } 526 527 /// Removes the value associated with the given key from the slab, returning 528 /// it. 529 /// 530 /// If the slab does not contain a value for that key, `None` is returned 531 /// instead. 532 /// 533 /// If the value associated with the given key is currently being 534 /// accessed by another thread, this method will block the current thread 535 /// until the item is no longer accessed. If this is not desired, use 536 /// [`remove`] instead. 537 /// 538 /// **Note**: This method blocks the calling thread by spinning until the 539 /// currently outstanding references are released. Spinning for long periods 540 /// of time can result in high CPU time and power consumption. Therefore, 541 /// `take` should only be called when other references to the slot are 542 /// expected to be dropped soon (e.g., when all accesses are relatively 543 /// short). 544 /// 545 /// # Examples 546 /// 547 /// ```rust 548 /// let slab = sharded_slab::Slab::new(); 549 /// let key = slab.insert("hello world").unwrap(); 550 /// 551 /// // Remove the item from the slab, returning it. 552 /// assert_eq!(slab.take(key), Some("hello world")); 553 /// 554 /// // Now, the slot is empty. 555 /// assert!(!slab.contains(key)); 556 /// ``` 557 /// 558 /// ```rust 559 /// use std::sync::Arc; 560 /// 561 /// let slab = Arc::new(sharded_slab::Slab::new()); 562 /// let key = slab.insert("hello world").unwrap(); 563 /// 564 /// let slab2 = slab.clone(); 565 /// let thread2 = std::thread::spawn(move || { 566 /// // Depending on when this thread begins executing, the item may 567 /// // or may not have already been removed... 568 /// if let Some(item) = slab2.get(key) { 569 /// assert_eq!(item, "hello world"); 570 /// } 571 /// }); 572 /// 573 /// // The item will only be removed when the other thread finishes 574 /// // accessing it. 575 /// assert_eq!(slab.take(key), Some("hello world")); 576 /// 577 /// thread2.join().unwrap(); 578 /// assert!(!slab.contains(key)); 579 /// ``` 580 /// [`remove`]: Slab::remove take(&self, idx: usize) -> Option<T>581 pub fn take(&self, idx: usize) -> Option<T> { 582 let tid = C::unpack_tid(idx); 583 584 test_println!("rm {:?}", tid); 585 let shard = self.shards.get(tid.as_usize())?; 586 if tid.is_current() { 587 shard.take_local(idx) 588 } else { 589 shard.take_remote(idx) 590 } 591 } 592 593 /// Return a reference to the value associated with the given key. 594 /// 595 /// If the slab does not contain a value for the given key, or if the 596 /// maximum number of concurrent references to the slot has been reached, 597 /// `None` is returned instead. 598 /// 599 /// # Examples 600 /// 601 /// ```rust 602 /// let slab = sharded_slab::Slab::new(); 603 /// let key = slab.insert("hello world").unwrap(); 604 /// 605 /// assert_eq!(slab.get(key).unwrap(), "hello world"); 606 /// assert!(slab.get(12345).is_none()); 607 /// ``` get(&self, key: usize) -> Option<Entry<'_, T, C>>608 pub fn get(&self, key: usize) -> Option<Entry<'_, T, C>> { 609 let tid = C::unpack_tid(key); 610 611 test_println!("get {:?}; current={:?}", tid, Tid::<C>::current()); 612 let shard = self.shards.get(tid.as_usize())?; 613 shard.with_slot(key, |slot| { 614 let inner = slot.get(C::unpack_gen(key))?; 615 let value = ptr::NonNull::from(slot.value().as_ref().unwrap()); 616 Some(Entry { 617 inner, 618 value, 619 shard, 620 key, 621 }) 622 }) 623 } 624 625 /// Return an owned reference to the value at the given index. 626 /// 627 /// If the slab does not contain a value for the given key, `None` is 628 /// returned instead. 629 /// 630 /// Unlike [`get`], which borrows the slab, this method _clones_ the [`Arc`] 631 /// around the slab. This means that the returned [`OwnedEntry`] can be held 632 /// for an arbitrary lifetime. However, this method requires that the slab 633 /// itself be wrapped in an `Arc`. 634 /// 635 /// # Examples 636 /// 637 /// ``` 638 /// # use sharded_slab::Slab; 639 /// use std::sync::Arc; 640 /// 641 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 642 /// let key = slab.insert("hello world").unwrap(); 643 /// 644 /// // Look up the created key, returning an `OwnedEntry`. 645 /// let value = slab.clone().get_owned(key).unwrap(); 646 /// 647 /// // Now, the original `Arc` clone of the slab may be dropped, but the 648 /// // returned `OwnedEntry` can still access the value. 649 /// assert_eq!(value, "hello world"); 650 /// ``` 651 /// 652 /// Unlike [`Entry`], an `OwnedEntry` may be stored in a struct which must live 653 /// for the `'static` lifetime: 654 /// 655 /// ``` 656 /// # use sharded_slab::Slab; 657 /// use sharded_slab::OwnedEntry; 658 /// use std::sync::Arc; 659 /// 660 /// pub struct MyStruct { 661 /// entry: OwnedEntry<&'static str>, 662 /// // ... other fields ... 663 /// } 664 /// 665 /// // Suppose this is some arbitrary function which requires a value that 666 /// // lives for the 'static lifetime... 667 /// fn function_requiring_static<T: 'static>(t: &T) { 668 /// // ... do something extremely important and interesting ... 669 /// } 670 /// 671 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 672 /// let key = slab.insert("hello world").unwrap(); 673 /// 674 /// // Look up the created key, returning an `OwnedEntry`. 675 /// let entry = slab.clone().get_owned(key).unwrap(); 676 /// let my_struct = MyStruct { 677 /// entry, 678 /// // ... 679 /// }; 680 /// 681 /// // We can use `my_struct` anywhere where it is required to have the 682 /// // `'static` lifetime: 683 /// function_requiring_static(&my_struct); 684 /// ``` 685 /// 686 /// [`OwnedEntry`]s may be sent between threads: 687 /// 688 /// ``` 689 /// # use sharded_slab::Slab; 690 /// use std::{thread, sync::Arc}; 691 /// 692 /// let slab: Arc<Slab<&'static str>> = Arc::new(Slab::new()); 693 /// let key = slab.insert("hello world").unwrap(); 694 /// 695 /// // Look up the created key, returning an `OwnedEntry`. 696 /// let value = slab.clone().get_owned(key).unwrap(); 697 /// 698 /// thread::spawn(move || { 699 /// assert_eq!(value, "hello world"); 700 /// // ... 701 /// }).join().unwrap(); 702 /// ``` 703 /// 704 /// [`get`]: Slab::get 705 /// [`Arc`]: std::sync::Arc get_owned(self: Arc<Self>, key: usize) -> Option<OwnedEntry<T, C>>706 pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedEntry<T, C>> { 707 let tid = C::unpack_tid(key); 708 709 test_println!("get_owned {:?}; current={:?}", tid, Tid::<C>::current()); 710 let shard = self.shards.get(tid.as_usize())?; 711 shard.with_slot(key, |slot| { 712 let inner = slot.get(C::unpack_gen(key))?; 713 let value = ptr::NonNull::from(slot.value().as_ref().unwrap()); 714 Some(OwnedEntry { 715 inner, 716 value, 717 slab: self.clone(), 718 key, 719 }) 720 }) 721 } 722 723 /// Returns `true` if the slab contains a value for the given key. 724 /// 725 /// # Examples 726 /// 727 /// ``` 728 /// let slab = sharded_slab::Slab::new(); 729 /// 730 /// let key = slab.insert("hello world").unwrap(); 731 /// assert!(slab.contains(key)); 732 /// 733 /// slab.take(key).unwrap(); 734 /// assert!(!slab.contains(key)); 735 /// ``` contains(&self, key: usize) -> bool736 pub fn contains(&self, key: usize) -> bool { 737 self.get(key).is_some() 738 } 739 740 /// Returns an iterator over all the items in the slab. 741 /// 742 /// Because this iterator exclusively borrows the slab (i.e. it holds an 743 /// `&mut Slab<T>`), elements will not be added or removed while the 744 /// iteration is in progress. unique_iter(&mut self) -> iter::UniqueIter<'_, T, C>745 pub fn unique_iter(&mut self) -> iter::UniqueIter<'_, T, C> { 746 let mut shards = self.shards.iter_mut(); 747 748 let (pages, slots) = match shards.next() { 749 Some(shard) => { 750 let mut pages = shard.iter(); 751 let slots = pages.next().and_then(page::Shared::iter); 752 (pages, slots) 753 } 754 None => ([].iter(), None), 755 }; 756 757 iter::UniqueIter { 758 shards, 759 pages, 760 slots, 761 } 762 } 763 } 764 765 impl<T> Default for Slab<T> { default() -> Self766 fn default() -> Self { 767 Self::new() 768 } 769 } 770 771 impl<T: fmt::Debug, C: cfg::Config> fmt::Debug for Slab<T, C> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result772 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 773 f.debug_struct("Slab") 774 .field("shards", &self.shards) 775 .field("config", &C::debug()) 776 .finish() 777 } 778 } 779 780 unsafe impl<T: Send, C: cfg::Config> Send for Slab<T, C> {} 781 unsafe impl<T: Sync, C: cfg::Config> Sync for Slab<T, C> {} 782 783 // === impl Entry === 784 785 impl<'a, T, C: cfg::Config> Entry<'a, T, C> { 786 /// Returns the key used to access the guard. key(&self) -> usize787 pub fn key(&self) -> usize { 788 self.key 789 } 790 791 #[inline(always)] value(&self) -> &T792 fn value(&self) -> &T { 793 unsafe { 794 // Safety: this is always going to be valid, as it's projected from 795 // the safe reference to `self.value` --- this is just to avoid 796 // having to `expect` an option in the hot path when dereferencing. 797 self.value.as_ref() 798 } 799 } 800 } 801 802 impl<'a, T, C: cfg::Config> std::ops::Deref for Entry<'a, T, C> { 803 type Target = T; 804 deref(&self) -> &Self::Target805 fn deref(&self) -> &Self::Target { 806 self.value() 807 } 808 } 809 810 impl<'a, T, C: cfg::Config> Drop for Entry<'a, T, C> { drop(&mut self)811 fn drop(&mut self) { 812 let should_remove = unsafe { 813 // Safety: calling `slot::Guard::release` is unsafe, since the 814 // `Guard` value contains a pointer to the slot that may outlive the 815 // slab containing that slot. Here, the `Entry` guard owns a 816 // borrowed reference to the shard containing that slot, which 817 // ensures that the slot will not be dropped while this `Guard` 818 // exists. 819 self.inner.release() 820 }; 821 if should_remove { 822 self.shard.clear_after_release(self.key) 823 } 824 } 825 } 826 827 impl<'a, T, C> fmt::Debug for Entry<'a, T, C> 828 where 829 T: fmt::Debug, 830 C: cfg::Config, 831 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result832 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 833 fmt::Debug::fmt(self.value(), f) 834 } 835 } 836 837 impl<'a, T, C> PartialEq<T> for Entry<'a, T, C> 838 where 839 T: PartialEq<T>, 840 C: cfg::Config, 841 { eq(&self, other: &T) -> bool842 fn eq(&self, other: &T) -> bool { 843 self.value().eq(other) 844 } 845 } 846 847 // === impl VacantEntry === 848 849 impl<'a, T, C: cfg::Config> VacantEntry<'a, T, C> { 850 /// Insert a value in the entry. 851 /// 852 /// To get the integer index at which this value will be inserted, use 853 /// [`key`] prior to calling `insert`. 854 /// 855 /// # Examples 856 /// 857 /// ``` 858 /// # use sharded_slab::Slab; 859 /// let mut slab = Slab::new(); 860 /// 861 /// let hello = { 862 /// let entry = slab.vacant_entry().unwrap(); 863 /// let key = entry.key(); 864 /// 865 /// entry.insert((key, "hello")); 866 /// key 867 /// }; 868 /// 869 /// assert_eq!(hello, slab.get(hello).unwrap().0); 870 /// assert_eq!("hello", slab.get(hello).unwrap().1); 871 /// ``` 872 /// 873 /// [`key`]: VacantEntry::key insert(mut self, val: T)874 pub fn insert(mut self, val: T) { 875 let value = unsafe { 876 // Safety: this `VacantEntry` only lives as long as the `Slab` it was 877 // borrowed from, so it cannot outlive the entry's slot. 878 self.inner.value_mut() 879 }; 880 debug_assert!( 881 value.is_none(), 882 "tried to insert to a slot that already had a value!" 883 ); 884 *value = Some(val); 885 let _released = unsafe { 886 // Safety: again, this `VacantEntry` only lives as long as the 887 // `Slab` it was borrowed from, so it cannot outlive the entry's 888 // slot. 889 self.inner.release() 890 }; 891 debug_assert!( 892 !_released, 893 "removing a value before it was inserted should be a no-op" 894 ) 895 } 896 897 /// Return the integer index at which this entry will be inserted. 898 /// 899 /// A value stored in this entry will be associated with this key. 900 /// 901 /// # Examples 902 /// 903 /// ``` 904 /// # use sharded_slab::*; 905 /// let mut slab = Slab::new(); 906 /// 907 /// let hello = { 908 /// let entry = slab.vacant_entry().unwrap(); 909 /// let key = entry.key(); 910 /// 911 /// entry.insert((key, "hello")); 912 /// key 913 /// }; 914 /// 915 /// assert_eq!(hello, slab.get(hello).unwrap().0); 916 /// assert_eq!("hello", slab.get(hello).unwrap().1); 917 /// ``` key(&self) -> usize918 pub fn key(&self) -> usize { 919 self.key 920 } 921 } 922 // === impl OwnedEntry === 923 924 impl<T, C> OwnedEntry<T, C> 925 where 926 C: cfg::Config, 927 { 928 /// Returns the key used to access this guard key(&self) -> usize929 pub fn key(&self) -> usize { 930 self.key 931 } 932 933 #[inline(always)] value(&self) -> &T934 fn value(&self) -> &T { 935 unsafe { 936 // Safety: this is always going to be valid, as it's projected from 937 // the safe reference to `self.value` --- this is just to avoid 938 // having to `expect` an option in the hot path when dereferencing. 939 self.value.as_ref() 940 } 941 } 942 } 943 944 impl<T, C> std::ops::Deref for OwnedEntry<T, C> 945 where 946 C: cfg::Config, 947 { 948 type Target = T; 949 deref(&self) -> &Self::Target950 fn deref(&self) -> &Self::Target { 951 self.value() 952 } 953 } 954 955 impl<T, C> Drop for OwnedEntry<T, C> 956 where 957 C: cfg::Config, 958 { drop(&mut self)959 fn drop(&mut self) { 960 test_println!("drop OwnedEntry: try clearing data"); 961 let should_clear = unsafe { 962 // Safety: calling `slot::Guard::release` is unsafe, since the 963 // `Guard` value contains a pointer to the slot that may outlive the 964 // slab containing that slot. Here, the `OwnedEntry` owns an `Arc` 965 // clone of the pool, which keeps it alive as long as the `OwnedEntry` 966 // exists. 967 self.inner.release() 968 }; 969 if should_clear { 970 let shard_idx = Tid::<C>::from_packed(self.key); 971 test_println!("-> shard={:?}", shard_idx); 972 if let Some(shard) = self.slab.shards.get(shard_idx.as_usize()) { 973 shard.clear_after_release(self.key) 974 } else { 975 test_println!("-> shard={:?} does not exist! THIS IS A BUG", shard_idx); 976 debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedEntry` to a slot on a shard that never existed!"); 977 } 978 } 979 } 980 } 981 982 impl<T, C> fmt::Debug for OwnedEntry<T, C> 983 where 984 T: fmt::Debug, 985 C: cfg::Config, 986 { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result987 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 988 fmt::Debug::fmt(self.value(), f) 989 } 990 } 991 992 impl<T, C> PartialEq<T> for OwnedEntry<T, C> 993 where 994 T: PartialEq<T>, 995 C: cfg::Config, 996 { eq(&self, other: &T) -> bool997 fn eq(&self, other: &T) -> bool { 998 *self.value() == *other 999 } 1000 } 1001 1002 unsafe impl<T, C> Sync for OwnedEntry<T, C> 1003 where 1004 T: Sync, 1005 C: cfg::Config, 1006 { 1007 } 1008 1009 unsafe impl<T, C> Send for OwnedEntry<T, C> 1010 where 1011 T: Sync, 1012 C: cfg::Config, 1013 { 1014 } 1015 1016 // === pack === 1017 1018 pub(crate) trait Pack<C: cfg::Config>: Sized { 1019 // ====== provided by each implementation ================================= 1020 1021 /// The number of bits occupied by this type when packed into a usize. 1022 /// 1023 /// This must be provided to determine the number of bits into which to pack 1024 /// the type. 1025 const LEN: usize; 1026 /// The type packed on the less significant side of this type. 1027 /// 1028 /// If this type is packed into the least significant bit of a usize, this 1029 /// should be `()`, which occupies no bytes. 1030 /// 1031 /// This is used to calculate the shift amount for packing this value. 1032 type Prev: Pack<C>; 1033 1034 // ====== calculated automatically ======================================== 1035 1036 /// A number consisting of `Self::LEN` 1 bits, starting at the least 1037 /// significant bit. 1038 /// 1039 /// This is the higest value this type can represent. This number is shifted 1040 /// left by `Self::SHIFT` bits to calculate this type's `MASK`. 1041 /// 1042 /// This is computed automatically based on `Self::LEN`. 1043 const BITS: usize = { 1044 let shift = 1 << (Self::LEN - 1); 1045 shift | (shift - 1) 1046 }; 1047 /// The number of bits to shift a number to pack it into a usize with other 1048 /// values. 1049 /// 1050 /// This is caculated automatically based on the `LEN` and `SHIFT` constants 1051 /// of the previous value. 1052 const SHIFT: usize = Self::Prev::SHIFT + Self::Prev::LEN; 1053 1054 /// The mask to extract only this type from a packed `usize`. 1055 /// 1056 /// This is calculated by shifting `Self::BITS` left by `Self::SHIFT`. 1057 const MASK: usize = Self::BITS << Self::SHIFT; 1058 as_usize(&self) -> usize1059 fn as_usize(&self) -> usize; from_usize(val: usize) -> Self1060 fn from_usize(val: usize) -> Self; 1061 1062 #[inline(always)] pack(&self, to: usize) -> usize1063 fn pack(&self, to: usize) -> usize { 1064 let value = self.as_usize(); 1065 debug_assert!(value <= Self::BITS); 1066 1067 (to & !Self::MASK) | (value << Self::SHIFT) 1068 } 1069 1070 #[inline(always)] from_packed(from: usize) -> Self1071 fn from_packed(from: usize) -> Self { 1072 let value = (from & Self::MASK) >> Self::SHIFT; 1073 debug_assert!(value <= Self::BITS); 1074 Self::from_usize(value) 1075 } 1076 } 1077 1078 impl<C: cfg::Config> Pack<C> for () { 1079 const BITS: usize = 0; 1080 const LEN: usize = 0; 1081 const SHIFT: usize = 0; 1082 const MASK: usize = 0; 1083 1084 type Prev = (); 1085 as_usize(&self) -> usize1086 fn as_usize(&self) -> usize { 1087 unreachable!() 1088 } from_usize(_val: usize) -> Self1089 fn from_usize(_val: usize) -> Self { 1090 unreachable!() 1091 } 1092 pack(&self, _to: usize) -> usize1093 fn pack(&self, _to: usize) -> usize { 1094 unreachable!() 1095 } 1096 from_packed(_from: usize) -> Self1097 fn from_packed(_from: usize) -> Self { 1098 unreachable!() 1099 } 1100 } 1101 1102 #[cfg(test)] 1103 pub(crate) use self::tests::util as test_util; 1104 1105 #[cfg(test)] 1106 mod tests; 1107