card_est_array/traits/
estimator_array.rs

1/*
2 * SPDX-FileCopyrightText: 2024 Matteo Dell'Acqua
3 * SPDX-FileCopyrightText: 2025 Sebastiano Vigna
4 *
5 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6 */
7
8use super::estimator::{EstimationLogic, Estimator, EstimatorMut};
9
10/// An array of immutable estimators sharing a [`EstimationLogic`].
11///
12/// Arrays of estimators are useful because they share the same logic, saving
13/// space with respect to a estimators. Moreover, by hiding the
14/// implementation, it is possible to create estimator arrays for estimators
15/// whose [backends are slices](crate::impls::SliceEstimatorArray).
16pub trait EstimatorArray<L: EstimationLogic + ?Sized> {
17    /// The type of immutable estimator returned by
18    /// [`get_estimator`](EstimatorArray::get_estimator).
19    type Estimator<'a>: Estimator<L>
20    where
21        Self: 'a;
22
23    /// Returns the logic used by the estimators in the array.
24    fn logic(&self) -> &L;
25
26    /// Returns the estimator at the specified index as an immutable estimator.
27    ///
28    /// Note that this method will usually require some allocation, as it needs
29    /// to create a new instance of [`EstimatorArray::Estimator`].
30    fn get_estimator(&self, index: usize) -> Self::Estimator<'_>;
31
32    /// Returns an immutable reference to the backend of the estimator at the
33    /// specified index.
34    ///
35    /// This method will usually require no allocation.
36    fn get_backend(&self, index: usize) -> &L::Backend;
37
38    /// Returns the number of estimators in the array.
39    fn len(&self) -> usize;
40
41    /// Returns `true` if the array contains no estimators.
42    #[inline(always)]
43    fn is_empty(&self) -> bool {
44        self.len() == 0
45    }
46}
47
48/// An array of mutable estimators sharing a [`EstimationLogic`].
49pub trait EstimatorArrayMut<L: EstimationLogic + ?Sized>: EstimatorArray<L> {
50    /// The type of mutable estimator returned by
51    /// [`get_estimator_mut`](EstimatorArrayMut::get_estimator_mut).
52    type EstimatorMut<'a>: EstimatorMut<L>
53    where
54        Self: 'a;
55
56    /// Returns the estimator at the specified index as a mutable estimator.
57    ///
58    /// Note that this method will usually require some allocation, as it needs
59    /// to create a new instance of [`EstimatorArrayMut::EstimatorMut`].
60    fn get_estimator_mut(&mut self, index: usize) -> Self::EstimatorMut<'_>;
61
62    /// Returns a mutable reference to the backend of the estimator at the
63    /// specified index.
64    ///
65    /// This method will usually require no allocation.
66    fn get_backend_mut(&mut self, index: usize) -> &mut L::Backend;
67
68    /// Resets all estimators in the array.
69    fn clear(&mut self);
70}
71
72/// A trait for estimator arrays that can be viewed as a [`SyncEstimatorArray`].
73pub trait AsSyncArray<L: EstimationLogic + ?Sized> {
74    type SyncEstimatorArray<'a>: SyncEstimatorArray<L>
75    where
76        Self: 'a;
77
78    /// Converts a mutable reference to this type into a shared reference
79    /// to a [`SyncEstimatorArray`].
80    fn as_sync_array(&mut self) -> Self::SyncEstimatorArray<'_>;
81}
82
83/// An array of mutable estimators sharing a [`EstimationLogic`] that can be shared
84/// between threads.
85///
86/// This trait has the same purpose of [`EstimatorArrayMut`], but can be shared
87/// between threads as it implements interior mutability. It follows a logic
88/// similar to a slice of
89/// [`SyncCell`](https://crates.io/crates/sync_cell_slice/): it is possible to
90/// get or set the backend of an estimator, but not to obtain a reference to a
91/// backend.
92///
93/// # Safety
94///
95/// The methods of this trait are unsafe because multiple thread can
96/// concurrently access the same estimator array. The caller must ensure that
97/// there are no data races.
98pub trait SyncEstimatorArray<L: EstimationLogic + ?Sized>: Sync {
99    /// Returns the logic used by the estimators in the array.
100    fn logic(&self) -> &L;
101
102    /// Sets the backend of the estimator at `index` to the given backend, using a
103    /// shared reference to the estimator array.
104    ///
105    /// # Safety
106    ///
107    /// The caller must ensure that the backend is correct for the logic of the
108    /// estimator array, and that there are no data races.
109    unsafe fn set(&self, index: usize, content: &L::Backend);
110
111    /// Copies the backend of the estimator at `index` to the given backend, using a
112    /// shared reference to the estimator array.
113    ///
114    /// # Safety
115    ///
116    /// The caller must ensure that the backend is correct for the logic of the
117    /// estimator array, and that there are no data races.
118    unsafe fn get(&self, index: usize, content: &mut L::Backend);
119
120    /// Clears all estimators in the array.
121    ///
122    /// # Safety
123    ///
124    /// The caller must ensure that there are no data races.
125    unsafe fn clear(&self);
126
127    /// Returns the number of estimators in the array.
128    fn len(&self) -> usize;
129
130    /// Returns `true` if the array contains no estimators.
131    #[inline(always)]
132    fn is_empty(&self) -> bool {
133        self.len() == 0
134    }
135}