concurrent-initializer 0.5.1

A rust library of concurrent initializer to ensure initialization only once per key.
Documentation
use std::{
  borrow::{Borrow, BorrowMut},
  hash::{Hash, Hasher},
  ops::{Deref, DerefMut},
  sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
  },
};

use crossbeam_epoch::Owned;

#[derive(Clone, Debug)]
pub(crate) struct NoisyDropper<T: ?Sized> {
  parent: Arc<DropNotifier>,
  pub elem: T,
}

impl<T> NoisyDropper<T> {
  pub(crate) fn new(parent: Arc<DropNotifier>, elem: T) -> Self {
    Self { parent, elem }
  }
}

impl<T: ?Sized> Drop for NoisyDropper<T> {
  fn drop(&mut self) {
    assert!(!self.parent.dropped.swap(true, Ordering::Relaxed));
  }
}

impl<T: ?Sized + PartialEq> PartialEq for NoisyDropper<T> {
  fn eq(&self, other: &Self) -> bool {
    self.elem == other.elem
  }
}

impl<T: ?Sized + PartialEq> PartialEq<T> for NoisyDropper<T> {
  fn eq(&self, other: &T) -> bool {
    &self.elem == other
  }
}

impl<T: ?Sized + Eq> Eq for NoisyDropper<T> {}

impl<T: ?Sized + Hash> Hash for NoisyDropper<T> {
  fn hash<H: Hasher>(&self, hasher: &mut H) {
    self.elem.hash(hasher);
  }
}

impl<T: ?Sized> AsRef<T> for NoisyDropper<T> {
  fn as_ref(&self) -> &T {
    &self.elem
  }
}

impl<T: ?Sized> AsMut<T> for NoisyDropper<T> {
  fn as_mut(&mut self) -> &mut T {
    &mut self.elem
  }
}

impl<T: ?Sized> Borrow<T> for NoisyDropper<T> {
  fn borrow(&self) -> &T {
    &self.elem
  }
}

impl<T: ?Sized> BorrowMut<T> for NoisyDropper<T> {
  fn borrow_mut(&mut self) -> &mut T {
    &mut self.elem
  }
}

impl<T: ?Sized> Deref for NoisyDropper<T> {
  type Target = T;

  fn deref(&self) -> &Self::Target {
    &self.elem
  }
}

impl<T: ?Sized> DerefMut for NoisyDropper<T> {
  fn deref_mut(&mut self) -> &mut Self::Target {
    &mut self.elem
  }
}

#[derive(Debug)]
pub(crate) struct DropNotifier {
  dropped: AtomicBool,
}

impl DropNotifier {
  pub(crate) fn new() -> Self {
    Self { dropped: AtomicBool::new(false) }
  }

  pub(crate) fn was_dropped(&self) -> bool {
    self.dropped.load(Ordering::Relaxed)
  }
}

pub(crate) fn run_deferred() {
  for _ in 0..65536 {
    let guard = crossbeam_epoch::pin();

    unsafe { guard.defer_destroy(Owned::new(0).into_shared(&guard)) };

    guard.flush();
  }
}