thingbuf.rs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. use crate::loom::atomic::Ordering;
  2. use crate::{Core, Full, Ref, Slot};
  3. use alloc::boxed::Box;
  4. use core::{fmt, ptr};
  5. #[cfg(all(loom, test))]
  6. mod tests;
  7. #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
  8. pub struct ThingBuf<T> {
  9. pub(crate) core: Core,
  10. pub(crate) slots: Box<[Slot<T>]>,
  11. }
  12. // === impl ThingBuf ===
  13. impl<T: Default> ThingBuf<T> {
  14. pub fn new(capacity: usize) -> Self {
  15. assert!(capacity > 0);
  16. Self {
  17. core: Core::new(capacity),
  18. slots: Slot::make_boxed_array(capacity),
  19. }
  20. }
  21. pub fn push_ref(&self) -> Result<Ref<'_, T>, Full> {
  22. self.core.push_ref(&*self.slots).map_err(|e| match e {
  23. crate::mpsc::TrySendError::Full(()) => Full(()),
  24. _ => unreachable!(),
  25. })
  26. }
  27. #[inline]
  28. pub fn push_with<U>(&self, f: impl FnOnce(&mut T) -> U) -> Result<U, Full> {
  29. self.push_ref().map(|mut r| r.with_mut(f))
  30. }
  31. pub fn pop_ref(&self) -> Option<Ref<'_, T>> {
  32. self.core.pop_ref(&*self.slots).ok()
  33. }
  34. #[inline]
  35. pub fn pop_with<U>(&self, f: impl FnOnce(&mut T) -> U) -> Option<U> {
  36. self.pop_ref().map(|mut r| r.with_mut(f))
  37. }
  38. }
  39. impl<T> ThingBuf<T> {
  40. #[inline]
  41. pub fn capacity(&self) -> usize {
  42. self.slots.len()
  43. }
  44. #[inline]
  45. pub fn len(&self) -> usize {
  46. self.core.len()
  47. }
  48. #[inline]
  49. pub fn is_empty(&self) -> bool {
  50. self.len() == 0
  51. }
  52. }
  53. impl<T> Drop for ThingBuf<T> {
  54. fn drop(&mut self) {
  55. let tail = self.core.tail.load(Ordering::SeqCst);
  56. let (idx, gen) = self.core.idx_gen(tail);
  57. let num_initialized = if gen > 0 { self.capacity() } else { idx };
  58. for slot in &self.slots[..num_initialized] {
  59. unsafe {
  60. slot.value
  61. .with_mut(|value| ptr::drop_in_place((*value).as_mut_ptr()));
  62. }
  63. }
  64. }
  65. }
  66. impl<T> fmt::Debug for ThingBuf<T> {
  67. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  68. f.debug_struct("ThingBuf")
  69. .field("len", &self.len())
  70. .field("slots", &format_args!("[...]"))
  71. .field("core", &self.core)
  72. .finish()
  73. }
  74. }