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        assert_ne!(lhs_inp, rhs_inp);
97        let new_v = match (
98            self.data[lhs_inp as usize].exchange(t, None)?,
99            self.data[rhs_inp as usize].exchange(t, None)?,
100        ) {
101            (Some(v1), Some(v2)) => AttributeUpdate::merge(v1, v2),
102            (Some(v), None) | (None, Some(v)) => AttributeUpdate::merge_incomplete(v),
103            (None, None) => AttributeUpdate::merge_from_none(),
104        };
105        match new_v {
106            Ok(v) => {
107                self.data[out as usize].write(t, Some(v))?;
108                Ok(())
109            }
110            Err(e) => abort(e),
111        }
112    }
113
114    fn split(
115        &self,
116        t: &mut Transaction,
117        lhs_out: DartIdType,
118        rhs_out: DartIdType,
119        inp: DartIdType,
120    ) -> TransactionClosureResult<(), AttributeError> {
121        assert_ne!(lhs_out, rhs_out);
122        let res = if let Some(val) = self.data[inp as usize].exchange(t, None)? {
123            AttributeUpdate::split(val)
124        } else {
125            AttributeUpdate::split_from_none()
126        };
127        match res {
128            Ok((lhs_val, rhs_val)) => {
129                self.data[lhs_out as usize].write(t, Some(lhs_val))?;
130                self.data[rhs_out as usize].write(t, Some(rhs_val))?;
131                Ok(())
132            }
133            Err(e) => abort(e),
134        }
135    }
136}
137
138impl<A: AttributeBind + AttributeUpdate> AttributeStorage<A> for AttrSparseVec<A> {
139    fn write(
140        &self,
141        t: &mut Transaction,
142        id: <A as AttributeBind>::IdentifierType,
143        val: A,
144    ) -> StmClosureResult<Option<A>> {
145        self.data[id.to_usize().unwrap()].exchange(t, Some(val))
146    }
147
148    fn read(
149        &self,
150        t: &mut Transaction,
151        id: <A as AttributeBind>::IdentifierType,
152    ) -> StmClosureResult<Option<A>> {
153        self.data[id.to_usize().unwrap()].read(t)
154    }
155
156    fn remove(
157        &self,
158        t: &mut Transaction,
159        id: <A as AttributeBind>::IdentifierType,
160    ) -> StmClosureResult<Option<A>> {
161        self.data[id.to_usize().unwrap()].exchange(t, None)
162    }
163}