Skip to content

Commit

Permalink
feat(orig-type-id-map): implement feature and supplement IdWrapper
Browse files Browse the repository at this point in the history
…with associated types
  • Loading branch information
andrewsonin committed Dec 12, 2023
1 parent 002b43b commit 2b7d473
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 19 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "blazemap"
version = "0.0.3"
version = "0.0.4"
authors = ["Andrew Sonin <sonin.cel@yandex.ru>"]
categories = ["data-structures"]
description = """
Expand All @@ -16,6 +16,7 @@ edition = "2021"
[dependencies]
once_cell = "1"
parking_lot = "0.12"
read-write-api = "0.17"
serde = { version = "1", optional = true, features = ["derive"] }

[dev-dependencies]
Expand Down
5 changes: 4 additions & 1 deletion src/collections/blazemap.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;

use read_write_api::ReadApi;
#[cfg(feature = "serde")]
use serde::{
de::{MapAccess, Visitor},
Expand All @@ -17,6 +18,7 @@ pub use crate::collections::blazemap::{
};
use crate::collections::blazemap::entry::VacantEntryInner;
use crate::id_wrapper::IdWrapper;
use crate::orig_type_id_map::OrigTypeIdMap;

mod entry;
mod iter;
Expand Down Expand Up @@ -322,7 +324,8 @@ impl<K, V> Default for BlazeMap<K, V>

macro_rules! blaze_map_orig_key_blocking_iter {
($self:ident, $iter:ident, $guard:ident) => {
let $guard = K::static_info().read();
let $guard = K::static_info();
let $guard = $guard.read();
let $iter = $self.inner.iter()
.enumerate()
.filter_map(|(idx, value)| Some((idx, value.as_ref()?)))
Expand Down
9 changes: 7 additions & 2 deletions src/collections/blazemap/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::marker::PhantomData;
use std::mem::needs_drop;
use std::panic::{RefUnwindSafe, UnwindSafe};

use read_write_api::ReadApi;

use crate::collections::blazemap::BlazeMap;
use crate::orig_type_id_map::OrigTypeIdMap;
use crate::prelude::IdWrapper;

/// An iterator over the entries of a [`BlazeMap`].
Expand Down Expand Up @@ -550,7 +553,8 @@ impl<'a, K, V> Debug for Iter<'a, K, V>
{
#[inline]
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
let static_info = K::static_info().read();
let static_info = K::static_info();
let static_info = static_info.read();
let iter = self.map(
|(key, value)| {
let key = unsafe { static_info.get_key_unchecked(key.get_index()) };
Expand Down Expand Up @@ -612,7 +616,8 @@ impl<'a, K, V> Debug for Keys<'a, K, V>
{
#[inline]
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
let static_info = K::static_info().read();
let static_info = K::static_info();
let static_info = static_info.read();
let iter = self.map(
|key| unsafe { static_info.get_key_unchecked(key.get_index()) }
);
Expand Down
17 changes: 12 additions & 5 deletions src/id_wrapper.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::hash::Hash;

use parking_lot::{RwLock, RwLockUpgradableReadGuard};
use read_write_api::{RwApi, UpgradableReadApi, UpgradableReadGuard};

use crate::utils::StaticInfo;
use crate::orig_type_id_map::OrigTypeIdMap;

/// Provides interface for `blazemap` key-wrapper types
/// defined by the [`register_blazemap_id`](crate::register_blazemap_id) macro.
Expand All @@ -11,15 +11,22 @@ pub trait IdWrapper: Copy
/// Original key type.
type OrigType: 'static + Clone + Eq + Hash;

#[doc(hidden)]
type OrigTypeIdMap: 'static + OrigTypeIdMap<Self::OrigType>;

#[doc(hidden)]
type OrigTypeIdMapApi: RwApi<Target=&'static mut Self::OrigTypeIdMap>;

/// Creates a new instance of [`Self`] based on the [`Self::OrigType`] instance.
#[inline]
fn new(key: Self::OrigType) -> Self {
unsafe {
let guard = Self::static_info().upgradable_read();
let mut static_info = Self::static_info();
let guard = static_info.upgradable_read();
if let Some(index) = guard.get_index(&key) {
Self::from_index_unchecked(index)
} else {
let mut guard = RwLockUpgradableReadGuard::upgrade(guard);
let mut guard = guard.upgrade();
let index = guard.insert_new_key_unchecked(key);
Self::from_index_unchecked(index)
}
Expand All @@ -33,5 +40,5 @@ pub trait IdWrapper: Copy
unsafe fn from_index_unchecked(index: usize) -> Self;

#[doc(hidden)]
fn static_info() -> &'static RwLock<StaticInfo<Self::OrigType>>;
fn static_info() -> Self::OrigTypeIdMapApi;
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub mod utils;
/// Collection types.
pub mod collections;
mod macros;
#[doc(hidden)]
mod orig_type_id_map;

/// Crate prelude.
pub mod prelude {
Expand Down
26 changes: 21 additions & 5 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,8 @@ macro_rules! blazemap_inner {
impl $crate::prelude::IdWrapper for $new_type
{
type OrigType = $orig_type;
type OrigTypeIdMap = $crate::utils::StaticInfo<$orig_type>;
type OrigTypeIdMapApi = &'static $crate::external::parking_lot::RwLock<&'static mut $crate::utils::StaticInfo<$orig_type>>;

#[inline]
fn get_index(self) -> usize {
Expand All @@ -125,13 +127,15 @@ macro_rules! blazemap_inner {
}

#[inline]
fn static_info() -> &'static $crate::external::parking_lot::RwLock<$crate::utils::StaticInfo<$orig_type>>
fn static_info() -> &'static $crate::external::parking_lot::RwLock<&'static mut $crate::utils::StaticInfo<$orig_type>>
{
use $crate::external::once_cell::sync::Lazy;
use $crate::external::parking_lot::RwLock;
use $crate::utils::StaticInfo;
static MAP: Lazy<RwLock<StaticInfo<$orig_type>>> = Lazy::new(
|| RwLock::new(StaticInfo::new())

static mut STATIC_INFO: StaticInfo<$orig_type> = StaticInfo::new();
static MAP: Lazy<RwLock<&'static mut StaticInfo<$orig_type>>> = Lazy::new(
|| RwLock::new(unsafe { &mut STATIC_INFO })
);
&MAP
}
Expand All @@ -155,7 +159,10 @@ macro_rules! blazemap_derive_key_inner {
impl PartialOrd for $new_type
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> {
fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering>
{
use $crate::orig_type_id_map::OrigTypeIdMap;

let Self(lhs) = self;
let Self(rhs) = other;
let guard = <Self as $crate::prelude::IdWrapper>::static_info().read();
Expand All @@ -181,7 +188,10 @@ macro_rules! blazemap_derive_key_inner {
impl Ord for $new_type
{
#[inline]
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering {
fn cmp(&self, other: &Self) -> ::std::cmp::Ordering
{
use $crate::orig_type_id_map::OrigTypeIdMap;

let Self(lhs) = self;
let Self(rhs) = other;
let guard = <Self as $crate::prelude::IdWrapper>::static_info().read();
Expand All @@ -201,6 +211,8 @@ macro_rules! blazemap_derive_key_inner {
#[inline]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
{
use $crate::orig_type_id_map::OrigTypeIdMap;

let Self(index) = self;
let mut f = f.debug_struct(::std::stringify!($new_type));
let guard = <Self as $crate::prelude::IdWrapper>::static_info().read();
Expand All @@ -219,6 +231,8 @@ macro_rules! blazemap_derive_key_inner {
#[inline]
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result
{
use $crate::orig_type_id_map::OrigTypeIdMap;

let Self(index) = self;
let guard = <Self as $crate::prelude::IdWrapper>::static_info().read();
let original_key = unsafe { guard.get_key_unchecked(index.into_inner()) };
Expand Down Expand Up @@ -248,6 +262,8 @@ macro_rules! blazemap_derive_key_inner {
where
S: $crate::external::serde::Serializer
{
use $crate::orig_type_id_map::OrigTypeIdMap;

let Self(index) = self;
unsafe {
<Self as $crate::prelude::IdWrapper>::static_info()
Expand Down
11 changes: 11 additions & 0 deletions src/orig_type_id_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#[doc(hidden)]
pub trait OrigTypeIdMap<K>
{
fn num_elems(&self) -> usize;

fn get_index(&self, key: &K) -> Option<usize>;

unsafe fn get_key_unchecked(&self, index: usize) -> &K;

unsafe fn insert_new_key_unchecked(&mut self, key: K) -> usize;
}
8 changes: 3 additions & 5 deletions src/utils/static_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::hash::Hash;

use once_cell::sync::Lazy;

use crate::orig_type_id_map::OrigTypeIdMap;

/// Global, statically initialized structure that contains correspondence mapping
/// between blazemap index wrappers and original keys.
#[doc(hidden)]
Expand All @@ -24,31 +26,27 @@ impl<K> StaticInfo<K>
}
}

impl<K> StaticInfo<K>
impl<K> OrigTypeIdMap<K> for StaticInfo<K>
where
K: Clone + Eq + Hash
{
#[inline(always)]
pub(in crate)
fn num_elems(&self) -> usize {
self.index_to_orig.len()
}

#[inline]
pub(in crate)
fn get_index(&self, key: &K) -> Option<usize> {
self.orig_to_index.get(key).copied()
}

#[inline]
pub
unsafe
fn get_key_unchecked(&self, index: usize) -> &K {
self.index_to_orig.get_unchecked(index)
}

#[inline]
pub(in crate)
unsafe
fn insert_new_key_unchecked(&mut self, key: K) -> usize
{
Expand Down

0 comments on commit 2b7d473

Please sign in to comment.