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}