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