Skip to main content

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
33impl<A: AttributeBind + AttributeUpdate> AttrSparseVec<A> {
34    pub(crate) fn set_atomic(&self, id: usize, val: A) {
35        self.data[id].write_atomic(Some(val));
36    }
37}
38
39unsafe impl<A: AttributeBind + AttributeUpdate> Send for AttrSparseVec<A> {}
40unsafe impl<A: AttributeBind + AttributeUpdate> Sync for AttrSparseVec<A> {}
41
42impl<A: AttributeBind + AttributeUpdate> UnknownAttributeStorage for AttrSparseVec<A> {
43    #[cfg(not(feature = "par-internals"))]
44    fn new(length: usize) -> Self
45    where
46        Self: Sized,
47    {
48        Self {
49            data: (0..length).map(|_| TVar::new(None)).collect(),
50        }
51    }
52
53    #[cfg(feature = "par-internals")]
54    fn new(length: usize) -> Self
55    where
56        Self: Sized,
57    {
58        Self {
59            data: (0..length)
60                .into_par_iter()
61                .map(|_| TVar::new(None))
62                .collect(),
63        }
64    }
65
66    #[cfg(not(feature = "par-internals"))]
67    fn extend(&mut self, length: usize) {
68        self.data.extend((0..length).map(|_| TVar::new(None)));
69    }
70
71    #[cfg(feature = "par-internals")]
72    fn extend(&mut self, length: usize) {
73        self.data
74            .par_extend((0..length).into_par_iter().map(|_| TVar::new(None)));
75    }
76
77    fn clear_slot(&self, t: &mut Transaction, id: DartIdType) -> StmClosureResult<()> {
78        self.remove(t, A::IdentifierType::from(id))?;
79        Ok(())
80    }
81
82    fn n_attributes(&self) -> usize {
83        self.data
84            .iter()
85            .filter(|v| v.read_atomic().is_some())
86            .count()
87    }
88
89    fn merge(
90        &self,
91        t: &mut Transaction,
92        out: DartIdType,
93        lhs_inp: DartIdType,
94        rhs_inp: DartIdType,
95    ) -> TransactionClosureResult<(), AttributeError> {
96        let new_v = match (
97            self.data[lhs_inp as usize].read(t)?,
98            self.data[rhs_inp as usize].read(t)?,
99        ) {
100            (Some(v1), Some(v2)) => AttributeUpdate::merge(v1, v2),
101            (Some(v), None) | (None, Some(v)) => AttributeUpdate::merge_incomplete(v),
102            (None, None) => AttributeUpdate::merge_from_none(),
103        };
104        match new_v {
105            Ok(v) => {
106                self.data[rhs_inp as usize].write(t, None)?;
107                self.data[lhs_inp as usize].write(t, None)?;
108                self.data[out as usize].write(t, Some(v))?;
109                Ok(())
110            }
111            Err(e) => abort(e),
112        }
113    }
114
115    fn split(
116        &self,
117        t: &mut Transaction,
118        lhs_out: DartIdType,
119        rhs_out: DartIdType,
120        inp: DartIdType,
121    ) -> TransactionClosureResult<(), AttributeError> {
122        let res = if let Some(val) = self.data[inp as usize].read(t)? {
123            AttributeUpdate::split(val)
124        } else {
125            AttributeUpdate::split_from_none()
126        };
127        match res {
128            Ok((lhs_val, rhs_val)) => {
129                self.data[inp as usize].write(t, None)?;
130                self.data[lhs_out as usize].write(t, Some(lhs_val))?;
131                self.data[rhs_out as usize].write(t, Some(rhs_val))?;
132                Ok(())
133            }
134            Err(e) => abort(e),
135        }
136    }
137}
138
139impl<A: AttributeBind + AttributeUpdate> AttributeStorage<A> for AttrSparseVec<A> {
140    fn write(
141        &self,
142        t: &mut Transaction,
143        id: <A as AttributeBind>::IdentifierType,
144        val: A,
145    ) -> StmClosureResult<Option<A>> {
146        self.data[id.to_usize().unwrap()].replace(t, Some(val))
147    }
148
149    fn read(
150        &self,
151        t: &mut Transaction,
152        id: <A as AttributeBind>::IdentifierType,
153    ) -> StmClosureResult<Option<A>> {
154        self.data[id.to_usize().unwrap()].read(t)
155    }
156
157    fn remove(
158        &self,
159        t: &mut Transaction,
160        id: <A as AttributeBind>::IdentifierType,
161    ) -> StmClosureResult<Option<A>> {
162        self.data[id.to_usize().unwrap()].replace(t, None)
163    }
164}