honeycomb_core/attributes/
collections.rs

1//! Attribute storage structures
2//!
3//! This module contains all code used to describe custom collections used to store attributes
4//! (see [`AttributeBind`], [`AttributeUpdate`]).
5
6use num_traits::ToPrimitive;
7#[cfg(feature = "par-internals")]
8use rayon::prelude::*;
9
10use crate::attributes::{
11    AttributeBind, AttributeError, AttributeStorage, AttributeUpdate, UnknownAttributeStorage,
12};
13use crate::cmap::DartIdType;
14use crate::stm::{StmClosureResult, TVar, Transaction, TransactionClosureResult, abort};
15
16/// Custom storage structure
17///
18/// **This structure is not meant to be used directly** but with the [`AttributeBind`] trait.
19///
20/// The structure is used to store user-defined attributes using a vector of `Option<T>` items.
21/// This implementation should favor access logic over locality of reference.
22///
23/// # Generics
24///
25/// - `T: AttributeBind + AttributeUpdate` -- Type of the stored attributes.
26///
27#[derive(Debug)]
28pub struct AttrSparseVec<T: AttributeBind + AttributeUpdate> {
29    /// Inner storage.
30    data: Vec<TVar<Option<T>>>,
31}
32
33unsafe impl<A: AttributeBind + AttributeUpdate> Send for AttrSparseVec<A> {}
34unsafe impl<A: AttributeBind + AttributeUpdate> Sync for AttrSparseVec<A> {}
35
36impl<A: AttributeBind + AttributeUpdate> UnknownAttributeStorage for AttrSparseVec<A> {
37    #[cfg(not(feature = "par-internals"))]
38    fn new(length: usize) -> Self
39    where
40        Self: Sized,
41    {
42        Self {
43            data: (0..length).map(|_| TVar::new(None)).collect(),
44        }
45    }
46
47    #[cfg(feature = "par-internals")]
48    fn new(length: usize) -> Self
49    where
50        Self: Sized,
51    {
52        Self {
53            data: (0..length)
54                .into_par_iter()
55                .map(|_| TVar::new(None))
56                .collect(),
57        }
58    }
59
60    #[cfg(not(feature = "par-internals"))]
61    fn extend(&mut self, length: usize) {
62        self.data.extend((0..length).map(|_| TVar::new(None)));
63    }
64
65    #[cfg(feature = "par-internals")]
66    fn extend(&mut self, length: usize) {
67        self.data
68            .par_extend((0..length).into_par_iter().map(|_| TVar::new(None)));
69    }
70
71    fn clear_slot(&self, t: &mut Transaction, id: DartIdType) -> StmClosureResult<()> {
72        self.remove(t, A::IdentifierType::from(id))?;
73        Ok(())
74    }
75
76    fn n_attributes(&self) -> usize {
77        self.data
78            .iter()
79            .filter(|v| v.read_atomic().is_some())
80            .count()
81    }
82
83    fn merge(
84        &self,
85        t: &mut Transaction,
86        out: DartIdType,
87        lhs_inp: DartIdType,
88        rhs_inp: DartIdType,
89    ) -> TransactionClosureResult<(), AttributeError> {
90        let new_v = match (
91            self.data[lhs_inp as usize].read(t)?,
92            self.data[rhs_inp as usize].read(t)?,
93        ) {
94            (Some(v1), Some(v2)) => AttributeUpdate::merge(v1, v2),
95            (Some(v), None) | (None, Some(v)) => AttributeUpdate::merge_incomplete(v),
96            (None, None) => AttributeUpdate::merge_from_none(),
97        };
98        match new_v {
99            Ok(v) => {
100                self.data[rhs_inp as usize].write(t, None)?;
101                self.data[lhs_inp as usize].write(t, None)?;
102                self.data[out as usize].write(t, Some(v))?;
103                Ok(())
104            }
105            Err(e) => abort(e),
106        }
107    }
108
109    fn split(
110        &self,
111        t: &mut Transaction,
112        lhs_out: DartIdType,
113        rhs_out: DartIdType,
114        inp: DartIdType,
115    ) -> TransactionClosureResult<(), AttributeError> {
116        let res = if let Some(val) = self.data[inp as usize].read(t)? {
117            AttributeUpdate::split(val)
118        } else {
119            AttributeUpdate::split_from_none()
120        };
121        match res {
122            Ok((lhs_val, rhs_val)) => {
123                self.data[inp as usize].write(t, None)?;
124                self.data[lhs_out as usize].write(t, Some(lhs_val))?;
125                self.data[rhs_out as usize].write(t, Some(rhs_val))?;
126                Ok(())
127            }
128            Err(e) => abort(e),
129        }
130    }
131}
132
133impl<A: AttributeBind + AttributeUpdate> AttributeStorage<A> for AttrSparseVec<A> {
134    fn write(
135        &self,
136        t: &mut Transaction,
137        id: <A as AttributeBind>::IdentifierType,
138        val: A,
139    ) -> StmClosureResult<Option<A>> {
140        self.data[id.to_usize().unwrap()].replace(t, Some(val))
141    }
142
143    fn read(
144        &self,
145        t: &mut Transaction,
146        id: <A as AttributeBind>::IdentifierType,
147    ) -> StmClosureResult<Option<A>> {
148        self.data[id.to_usize().unwrap()].read(t)
149    }
150
151    fn remove(
152        &self,
153        t: &mut Transaction,
154        id: <A as AttributeBind>::IdentifierType,
155    ) -> StmClosureResult<Option<A>> {
156        self.data[id.to_usize().unwrap()].replace(t, None)
157    }
158}