1use alloc::sync::Arc;
9use core::fmt;
10use core::ops::{Deref, DerefMut};
11use core::sync::atomic::{AtomicUsize, Ordering};
12
13use allocator_api2::collections::TryReserveErrorKind;
14use allocator_api2::vec::Vec;
15
16mod allocator;
17mod map;
18mod sort;
19mod string;
20pub use map::{HashWork, OwnedMap};
21pub use sort::SortError;
22pub use string::OwnedString;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum MemoryError {
27 LimitExceeded,
29 OutOfMemory,
31 CapacityOverflow,
33 WorkExceeded,
35}
36
37impl fmt::Display for MemoryError {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.write_str(match self {
40 Self::LimitExceeded => "memory budget spent",
41 Self::OutOfMemory => "allocator could not supply storage",
42 Self::CapacityOverflow => "storage capacity overflow",
43 Self::WorkExceeded => "work budget spent",
44 })
45 }
46}
47
48#[cfg(feature = "std")]
49impl std::error::Error for MemoryError {}
50
51#[derive(Debug)]
56pub struct MemoryAccount {
57 limit: usize,
58 used: AtomicUsize,
59 work_limit: usize,
60 work: AtomicUsize,
61}
62
63impl MemoryAccount {
64 #[must_use]
66 pub const fn new(limit: usize, work_limit: usize) -> Self {
67 Self {
68 limit,
69 used: AtomicUsize::new(0),
70 work_limit,
71 work: AtomicUsize::new(0),
72 }
73 }
74
75 fn reserve(&self, bytes: usize) -> core::result::Result<Reservation<'_>, MemoryError> {
76 let mut used = self.used.load(Ordering::Relaxed);
77 loop {
78 debug_assert!(used <= self.limit);
79 if bytes > self.limit - used {
80 return Err(MemoryError::LimitExceeded);
81 }
82 match self.used.compare_exchange_weak(
83 used,
84 used + bytes,
85 Ordering::Relaxed,
86 Ordering::Relaxed,
87 ) {
88 Ok(_) => {
89 return Ok(Reservation {
90 account: self,
91 bytes,
92 });
93 }
94 Err(current) => used = current,
95 }
96 }
97 }
98
99 fn release(&self, bytes: usize) {
100 let previous = self.used.fetch_sub(bytes, Ordering::Relaxed);
101 debug_assert!(previous >= bytes);
102 }
103}
104
105struct Reservation<'a> {
106 account: &'a MemoryAccount,
107 bytes: usize,
108}
109
110impl Reservation<'_> {
111 fn commit(mut self) {
112 self.bytes = 0;
113 }
114}
115
116impl Drop for Reservation<'_> {
117 fn drop(&mut self) {
118 self.account.release(self.bytes);
119 }
120}
121
122#[derive(Debug, Clone)]
126pub struct Memory {
127 account: Arc<MemoryAccount>,
128}
129
130impl Memory {
131 #[must_use]
133 pub fn new(account: Arc<MemoryAccount>) -> Self {
134 Self { account }
135 }
136
137 #[must_use]
139 pub fn limit(&self) -> usize {
140 self.account.limit
141 }
142
143 #[must_use]
145 pub fn used(&self) -> usize {
146 self.account.used.load(Ordering::Relaxed)
147 }
148
149 #[must_use]
151 pub fn same_account(&self, other: &Self) -> bool {
152 Arc::ptr_eq(&self.account, &other.account)
153 }
154
155 #[must_use]
157 pub fn work_used(&self) -> usize {
158 self.account.work.load(Ordering::Relaxed)
159 }
160
161 pub fn charge_work(&self, amount: u64) -> core::result::Result<(), MemoryError> {
166 let amount = usize::try_from(amount).map_err(|_| MemoryError::WorkExceeded)?;
167 let mut spent = self.account.work.load(Ordering::Relaxed);
168 loop {
169 debug_assert!(spent <= self.account.work_limit);
170 if amount > self.account.work_limit - spent {
171 return Err(MemoryError::WorkExceeded);
172 }
173 match self.account.work.compare_exchange_weak(
174 spent,
175 spent + amount,
176 Ordering::Relaxed,
177 Ordering::Relaxed,
178 ) {
179 Ok(_) => return Ok(()),
180 Err(current) => spent = current,
181 }
182 }
183 }
184
185 pub fn reserve(&self, bytes: usize) -> core::result::Result<MemoryReservation, MemoryError> {
191 let reservation = self.account.reserve(bytes)?;
192 reservation.commit();
193 Ok(MemoryReservation {
194 memory: self.clone(),
195 bytes,
196 })
197 }
198
199 #[must_use]
201 pub fn vector<T>(&self) -> OwnedVec<T> {
202 OwnedVec {
203 values: Vec::new_in(allocator::AccountAllocator::new(self.clone())),
204 }
205 }
206
207 #[must_use]
209 pub fn map<K: HashWork, V>(&self) -> OwnedMap<K, V> {
210 OwnedMap::new(self.clone())
211 }
212
213 #[must_use]
215 pub fn string(&self) -> OwnedString {
216 OwnedString::new(self)
217 }
218}
219
220#[derive(Debug)]
225#[must_use = "retain the reservation until its allocation has been deallocated"]
226pub struct MemoryReservation {
227 memory: Memory,
228 bytes: usize,
229}
230
231impl Drop for MemoryReservation {
232 fn drop(&mut self) {
233 self.memory.account.release(self.bytes);
234 }
235}
236
237pub struct OwnedVec<T> {
243 values: Vec<T, allocator::AccountAllocator>,
244}
245
246impl<T: fmt::Debug> fmt::Debug for OwnedVec<T> {
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 self.values.fmt(f)
249 }
250}
251
252impl<T: PartialEq> PartialEq for OwnedVec<T> {
253 fn eq(&self, other: &Self) -> bool {
254 **self == **other
255 }
256}
257
258impl<T: Eq> Eq for OwnedVec<T> {}
259
260impl<T: PartialEq, const N: usize> PartialEq<[T; N]> for OwnedVec<T> {
261 fn eq(&self, other: &[T; N]) -> bool {
262 &**self == other
263 }
264}
265
266impl<T> OwnedVec<T> {
267 #[must_use]
269 pub fn memory(&self) -> &Memory {
270 self.values.allocator().memory()
271 }
272 #[must_use]
274 pub fn capacity(&self) -> usize {
275 self.values.capacity()
276 }
277
278 pub fn try_reserve_exact(
280 &mut self,
281 additional: usize,
282 ) -> core::result::Result<(), MemoryError> {
283 self.values.allocator().clear_failure();
284 self.values
285 .try_reserve_exact(additional)
286 .map_err(|error| match error.kind() {
287 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
288 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
289 })
290 }
291
292 pub fn try_reserve(&mut self, additional: usize) -> core::result::Result<(), MemoryError> {
294 self.values.allocator().clear_failure();
295 self.values
296 .try_reserve(additional)
297 .map_err(|error| match error.kind() {
298 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
299 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
300 })
301 }
302
303 pub fn try_push(&mut self, value: T) -> core::result::Result<(), MemoryError> {
305 self.values.allocator().memory().charge_work(1)?;
306 if self.values.len() == self.values.capacity() {
307 self.try_reserve(1)?;
308 }
309 self.values.push(value);
311 Ok(())
312 }
313
314 pub fn pop(&mut self) -> Option<T> {
316 self.values.pop()
317 }
318
319 pub fn clear(&mut self) {
321 self.values.clear();
322 }
323
324 pub fn try_sort_unstable_by<E>(
330 &mut self,
331 compare: impl FnMut(&T, &T) -> core::result::Result<core::cmp::Ordering, E>,
332 ) -> core::result::Result<(), SortError<E>> {
333 let memory = self.memory().clone();
334 sort::sort(&mut self.values, &memory, compare)
335 }
336}
337
338impl<T: Copy> OwnedVec<T> {
339 pub fn try_extend_from_slice(&mut self, values: &[T]) -> core::result::Result<(), MemoryError> {
341 let work = values.len().max(core::mem::size_of_val(values));
342 self.memory().charge_work(work as u64)?;
343 if self.values.capacity() == 0 {
344 self.try_reserve_exact(values.len())?;
345 } else {
346 self.try_reserve(values.len())?;
347 }
348 self.values.extend_from_slice(values);
349 Ok(())
350 }
351 pub fn try_copy(&self) -> core::result::Result<Self, MemoryError> {
353 let mut copy = self.values.allocator().memory().vector();
354 let work = self.values.len().max(core::mem::size_of_val(&**self));
355 self.values.allocator().memory().charge_work(work as u64)?;
356 copy.try_reserve_exact(self.values.len())?;
357 copy.values.extend_from_slice(&self.values);
359 Ok(copy)
360 }
361}
362
363impl<T> Deref for OwnedVec<T> {
364 type Target = [T];
365 fn deref(&self) -> &[T] {
366 &self.values
367 }
368}
369
370impl<T> DerefMut for OwnedVec<T> {
371 fn deref_mut(&mut self) -> &mut [T] {
372 &mut self.values
373 }
374}
375
376impl<'a, T> IntoIterator for &'a OwnedVec<T> {
377 type Item = &'a T;
378 type IntoIter = core::slice::Iter<'a, T>;
379 fn into_iter(self) -> Self::IntoIter {
380 self.iter()
381 }
382}
383
384impl<'a, T> IntoIterator for &'a mut OwnedVec<T> {
385 type Item = &'a mut T;
386 type IntoIter = core::slice::IterMut<'a, T>;
387 fn into_iter(self) -> Self::IntoIter {
388 self.iter_mut()
389 }
390}
391
392pub struct OwnedIter<T> {
394 values: allocator_api2::vec::IntoIter<T, allocator::AccountAllocator>,
395}
396
397impl<T> Iterator for OwnedIter<T> {
398 type Item = T;
399 fn next(&mut self) -> Option<T> {
400 self.values.next()
401 }
402 fn size_hint(&self) -> (usize, Option<usize>) {
403 self.values.size_hint()
404 }
405}
406
407impl<T> DoubleEndedIterator for OwnedIter<T> {
408 fn next_back(&mut self) -> Option<T> {
409 self.values.next_back()
410 }
411}
412
413impl<T> ExactSizeIterator for OwnedIter<T> {}
414impl<T> core::iter::FusedIterator for OwnedIter<T> {}
415
416impl<T> IntoIterator for OwnedVec<T> {
417 type Item = T;
418 type IntoIter = OwnedIter<T>;
419 fn into_iter(self) -> Self::IntoIter {
420 OwnedIter {
421 values: self.values.into_iter(),
422 }
423 }
424}
425
426#[cfg(test)]
427mod tests;