Skip to content

Commit

Permalink
Hide hasher implementation behind newtype (#2263)
Browse files Browse the repository at this point in the history
  • Loading branch information
kangalio authored Nov 6, 2022
1 parent 4cf89c4 commit a01ee32
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 20 deletions.
23 changes: 11 additions & 12 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ use std::time::Duration;
use dashmap::mapref::entry::Entry;
use dashmap::mapref::one::Ref;
use dashmap::DashMap;
use fxhash::FxBuildHasher;
#[cfg(feature = "temp_cache")]
use moka::dash::Cache as DashCache;
use parking_lot::RwLock;
Expand All @@ -56,16 +55,16 @@ mod event;
mod settings;
mod wrappers;

use wrappers::{MaybeMap, ReadOnlyMapRef};
use wrappers::{BuildHasher, MaybeMap, ReadOnlyMapRef};

type MessageCache = DashMap<ChannelId, HashMap<MessageId, Message>, FxBuildHasher>;
type MessageCache = DashMap<ChannelId, HashMap<MessageId, Message>, BuildHasher>;

struct NotSend;

enum CacheRefInner<'a, K, V> {
#[cfg(feature = "temp_cache")]
Arc(Arc<V>),
DashRef(Ref<'a, K, V, FxBuildHasher>),
DashRef(Ref<'a, K, V, BuildHasher>),
ReadGuard(parking_lot::RwLockReadGuard<'a, V>),
}

Expand All @@ -87,7 +86,7 @@ impl<'a, K, V> CacheRef<'a, K, V> {
Self::new(CacheRefInner::Arc(inner))
}

fn from_ref(inner: Ref<'a, K, V, FxBuildHasher>) -> Self {
fn from_ref(inner: Ref<'a, K, V, BuildHasher>) -> Self {
Self::new(CacheRefInner::DashRef(inner))
}

Expand Down Expand Up @@ -188,12 +187,12 @@ pub struct Cache {
///
/// The TTL for each value is configured in CacheSettings.
#[cfg(feature = "temp_cache")]
pub(crate) temp_channels: DashCache<ChannelId, GuildChannel, FxBuildHasher>,
pub(crate) temp_channels: DashCache<ChannelId, GuildChannel, BuildHasher>,
/// Cache of users who have been fetched from `to_user`.
///
/// The TTL for each value is configured in CacheSettings.
#[cfg(feature = "temp_cache")]
pub(crate) temp_users: DashCache<UserId, Arc<User>, FxBuildHasher>,
pub(crate) temp_users: DashCache<UserId, Arc<User>, BuildHasher>,

// Channels cache:
// ---
Expand Down Expand Up @@ -249,7 +248,7 @@ pub struct Cache {
/// This is simply a vecdeque so we can keep track of the order of messages
/// inserted into the cache. When a maximum number of messages are in a
/// channel's cache, we can pop the front and remove that ID from the cache.
pub(crate) message_queue: DashMap<ChannelId, VecDeque<MessageId>, FxBuildHasher>,
pub(crate) message_queue: DashMap<ChannelId, VecDeque<MessageId>, BuildHasher>,

// Miscellanous fixed-size data
// ---
Expand Down Expand Up @@ -290,12 +289,12 @@ impl Cache {
#[instrument]
pub fn new_with_settings(settings: Settings) -> Self {
#[cfg(feature = "temp_cache")]
fn temp_cache<K, V>(ttl: Duration) -> DashCache<K, V, FxBuildHasher>
fn temp_cache<K, V>(ttl: Duration) -> DashCache<K, V, BuildHasher>
where
K: Hash + Eq + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
{
DashCache::builder().time_to_live(ttl).build_with_hasher(FxBuildHasher::default())
DashCache::builder().time_to_live(ttl).build_with_hasher(BuildHasher::default())
}

Self {
Expand Down Expand Up @@ -707,14 +706,14 @@ impl Cache {
pub fn guild_channels(
&self,
guild_id: impl Into<GuildId>,
) -> Option<DashMap<ChannelId, GuildChannel, FxBuildHasher>> {
) -> Option<DashMap<ChannelId, GuildChannel, BuildHasher>> {
self._guild_channels(guild_id.into())
}

fn _guild_channels(
&self,
guild_id: GuildId,
) -> Option<DashMap<ChannelId, GuildChannel, FxBuildHasher>> {
) -> Option<DashMap<ChannelId, GuildChannel, BuildHasher>> {
self.guilds.get(&guild_id).map(|g| g.channels.clone().into_iter().collect())
}

Expand Down
35 changes: 27 additions & 8 deletions src/cache/wrappers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@ use std::hash::Hash;
use dashmap::mapref::multiple::RefMulti;
use dashmap::mapref::one::{Ref, RefMut};
use dashmap::DashMap;
use fxhash::FxBuildHasher;

#[derive(Debug)]
/// A wrapper around Option<DashMap<K, V>> to ease disabling specific cache fields.
pub(crate) struct MaybeMap<K: Eq + Hash, V>(pub(super) Option<DashMap<K, V, FxBuildHasher>>);
pub(crate) struct MaybeMap<K: Eq + Hash, V>(pub(super) Option<DashMap<K, V, BuildHasher>>);
impl<K: Eq + Hash, V> MaybeMap<K, V> {
pub fn iter(&self) -> impl Iterator<Item = RefMulti<'_, K, V, FxBuildHasher>> {
pub fn iter(&self) -> impl Iterator<Item = RefMulti<'_, K, V, BuildHasher>> {
Option::iter(&self.0).flat_map(DashMap::iter)
}

pub fn get(&self, k: &K) -> Option<Ref<'_, K, V, FxBuildHasher>> {
pub fn get(&self, k: &K) -> Option<Ref<'_, K, V, BuildHasher>> {
self.0.as_ref()?.get(k)
}

pub fn get_mut(&self, k: &K) -> Option<RefMut<'_, K, V, FxBuildHasher>> {
pub fn get_mut(&self, k: &K) -> Option<RefMut<'_, K, V, BuildHasher>> {
self.0.as_ref()?.get_mut(k)
}

Expand All @@ -43,17 +42,37 @@ impl<K: Eq + Hash, V> MaybeMap<K, V> {
#[derive(Clone, Copy, Debug)]
/// A wrapper around a reference to a MaybeMap, allowing for public inspection of the underlying map
/// without allowing mutation of internal cache fields, which could cause issues.
pub struct ReadOnlyMapRef<'a, K: Eq + Hash, V>(Option<&'a DashMap<K, V, FxBuildHasher>>);
pub struct ReadOnlyMapRef<'a, K: Eq + Hash, V>(Option<&'a DashMap<K, V, BuildHasher>>);
impl<'a, K: Eq + Hash, V> ReadOnlyMapRef<'a, K, V> {
pub fn iter(&self) -> impl Iterator<Item = RefMulti<'_, K, V, FxBuildHasher>> {
pub fn iter(&self) -> impl Iterator<Item = RefMulti<'_, K, V, BuildHasher>> {
self.0.into_iter().flat_map(DashMap::iter)
}

pub fn get(&self, k: &K) -> Option<Ref<'_, K, V, FxBuildHasher>> {
pub fn get(&self, k: &K) -> Option<Ref<'_, K, V, BuildHasher>> {
self.0?.get(k)
}

pub fn len(&self) -> usize {
self.0.map_or(0, DashMap::len)
}
}

pub struct Hasher(fxhash::FxHasher);
impl std::hash::Hasher for Hasher {
fn finish(&self) -> u64 {
self.0.finish()
}

fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes);
}
}
#[derive(Clone, Default)]
pub struct BuildHasher(fxhash::FxBuildHasher);
impl std::hash::BuildHasher for BuildHasher {
type Hasher = Hasher;

fn build_hasher(&self) -> Self::Hasher {
Hasher(self.0.build_hasher())
}
}

0 comments on commit a01ee32

Please sign in to comment.