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 shared_string;
19mod sort;
20mod string;
21mod work;
22pub use map::{HashWork, OwnedMap, RetainError};
23pub use shared_string::SharedString;
24pub use sort::SortError;
25pub use string::OwnedString;
26pub use work::{Execution, Work};
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum MemoryError {
31 LimitExceeded,
33 OutOfMemory,
35 CapacityOverflow,
37 WorkExceeded,
39}
40
41impl fmt::Display for MemoryError {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.write_str(match self {
44 Self::LimitExceeded => "memory budget spent",
45 Self::OutOfMemory => "allocator could not supply storage",
46 Self::CapacityOverflow => "storage capacity overflow",
47 Self::WorkExceeded => "work budget spent",
48 })
49 }
50}
51
52#[cfg(feature = "std")]
53impl std::error::Error for MemoryError {}
54
55#[derive(Debug)]
60pub struct MemoryAccount {
61 limit: usize,
62 used: AtomicUsize,
63 work_limit: usize,
64 work: AtomicUsize,
65}
66
67impl MemoryAccount {
68 #[must_use]
70 pub const fn new(limit: usize, work_limit: usize) -> Self {
71 Self {
72 limit,
73 used: AtomicUsize::new(0),
74 work_limit,
75 work: AtomicUsize::new(0),
76 }
77 }
78
79 fn reserve(&self, bytes: usize) -> core::result::Result<Reservation<'_>, MemoryError> {
80 let mut used = self.used.load(Ordering::Relaxed);
81 loop {
82 debug_assert!(used <= self.limit);
83 if bytes > self.limit - used {
84 return Err(MemoryError::LimitExceeded);
85 }
86 match self.used.compare_exchange_weak(
87 used,
88 used + bytes,
89 Ordering::Relaxed,
90 Ordering::Relaxed,
91 ) {
92 Ok(_) => {
93 return Ok(Reservation {
94 account: self,
95 bytes,
96 });
97 }
98 Err(current) => used = current,
99 }
100 }
101 }
102
103 fn release(&self, bytes: usize) {
104 let previous = self.used.fetch_sub(bytes, Ordering::Relaxed);
105 debug_assert!(previous >= bytes);
106 }
107}
108
109struct Reservation<'a> {
110 account: &'a MemoryAccount,
111 bytes: usize,
112}
113
114impl Reservation<'_> {
115 fn commit(mut self) {
116 self.bytes = 0;
117 }
118}
119
120impl Drop for Reservation<'_> {
121 fn drop(&mut self) {
122 self.account.release(self.bytes);
123 }
124}
125
126#[derive(Debug, Clone)]
130pub struct Memory {
131 account: Arc<MemoryAccount>,
132}
133
134impl Memory {
135 #[must_use]
137 pub fn new(account: Arc<MemoryAccount>) -> Self {
138 Self { account }
139 }
140
141 #[must_use]
143 pub fn limit(&self) -> usize {
144 self.account.limit
145 }
146
147 #[must_use]
149 pub fn used(&self) -> usize {
150 self.account.used.load(Ordering::Relaxed)
151 }
152
153 #[must_use]
155 pub fn same_account(&self, other: &Self) -> bool {
156 Arc::ptr_eq(&self.account, &other.account)
157 }
158
159 #[must_use]
161 pub fn work_used(&self) -> usize {
162 self.account.work.load(Ordering::Relaxed)
163 }
164
165 #[must_use]
169 pub fn work_remaining(&self) -> usize {
170 let spent = self.account.work.load(Ordering::Relaxed);
171 debug_assert!(spent <= self.account.work_limit);
172 self.account.work_limit - spent
173 }
174
175 pub fn charge_work(&self, amount: u64) -> core::result::Result<(), MemoryError> {
180 let amount = usize::try_from(amount).map_err(|_| MemoryError::WorkExceeded)?;
181 let mut spent = self.account.work.load(Ordering::Relaxed);
182 loop {
183 debug_assert!(spent <= self.account.work_limit);
184 if amount > self.account.work_limit - spent {
185 return Err(MemoryError::WorkExceeded);
186 }
187 match self.account.work.compare_exchange_weak(
188 spent,
189 spent + amount,
190 Ordering::Relaxed,
191 Ordering::Relaxed,
192 ) {
193 Ok(_) => return Ok(()),
194 Err(current) => spent = current,
195 }
196 }
197 }
198
199 pub fn reserve(&self, bytes: usize) -> core::result::Result<MemoryReservation, MemoryError> {
205 let reservation = self.account.reserve(bytes)?;
206 reservation.commit();
207 Ok(MemoryReservation {
208 memory: self.clone(),
209 bytes,
210 })
211 }
212
213 #[must_use]
215 pub fn vector<T>(&self) -> OwnedVec<T> {
216 Work::vector(self)
217 }
218
219 #[must_use]
221 pub fn map<K: HashWork, V>(&self) -> OwnedMap<K, V> {
222 OwnedMap::new(self.clone())
223 }
224
225 #[must_use]
227 pub fn string(&self) -> OwnedString {
228 OwnedString::new(self)
229 }
230}
231
232#[derive(Debug)]
237#[must_use = "retain the reservation until its allocation has been deallocated"]
238pub struct MemoryReservation {
239 memory: Memory,
240 bytes: usize,
241}
242
243impl Drop for MemoryReservation {
244 fn drop(&mut self) {
245 self.memory.account.release(self.bytes);
246 }
247}
248
249pub struct OwnedVec<T, W: Work = Memory> {
257 values: Vec<T, allocator::AccountAllocator<W>>,
258}
259
260impl<T> OwnedVec<T> {
261 pub fn with_execution<W: Work>(self, execution: &W) -> Result<OwnedVec<T, W>, Self> {
270 if !self.memory().same_account(execution.memory()) {
271 return Err(self);
272 }
273 Ok(OwnedVec {
274 values: allocator::scope(self.values, execution),
275 })
276 }
277}
278
279impl<T, W: Work> OwnedVec<T, W> {
280 #[must_use]
308 pub fn into_owned(self) -> OwnedVec<T> {
309 OwnedVec {
310 values: allocator::retain(self.values),
311 }
312 }
313}
314
315impl<T: fmt::Debug, W: Work> fmt::Debug for OwnedVec<T, W> {
316 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317 self.values.fmt(f)
318 }
319}
320
321impl<T: PartialEq, W: Work> PartialEq for OwnedVec<T, W> {
322 fn eq(&self, other: &Self) -> bool {
323 **self == **other
324 }
325}
326
327impl<T: Eq, W: Work> Eq for OwnedVec<T, W> {}
328
329impl<T: PartialEq, W: Work, const N: usize> PartialEq<[T; N]> for OwnedVec<T, W> {
330 fn eq(&self, other: &[T; N]) -> bool {
331 &**self == other
332 }
333}
334
335impl<T, W: Work> OwnedVec<T, W> {
336 #[must_use]
338 pub fn memory(&self) -> &Memory {
339 self.values.allocator().memory()
340 }
341 #[must_use]
343 pub fn capacity(&self) -> usize {
344 self.values.capacity()
345 }
346
347 pub fn try_reserve_exact(
349 &mut self,
350 additional: usize,
351 ) -> core::result::Result<(), MemoryError> {
352 self.values.allocator().clear_failure();
353 self.values
354 .try_reserve_exact(additional)
355 .map_err(|error| match error.kind() {
356 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
357 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
358 })
359 }
360
361 pub fn try_reserve(&mut self, additional: usize) -> core::result::Result<(), MemoryError> {
363 self.values.allocator().clear_failure();
364 self.values
365 .try_reserve(additional)
366 .map_err(|error| match error.kind() {
367 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
368 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
369 })
370 }
371
372 pub fn try_push(&mut self, value: T) -> core::result::Result<(), MemoryError> {
374 self.values.allocator().work().charge_work(1)?;
375 if self.values.len() == self.values.capacity() {
376 self.try_reserve(1)?;
377 }
378 self.values.push(value);
380 Ok(())
381 }
382
383 pub fn pop(&mut self) -> Option<T> {
385 self.values.pop()
386 }
387
388 pub fn clear(&mut self) {
390 self.values.clear();
391 }
392
393 pub fn try_sort_unstable_by<E>(
399 &mut self,
400 compare: impl FnMut(&T, &T) -> core::result::Result<core::cmp::Ordering, E>,
401 ) -> core::result::Result<(), SortError<E>> {
402 let work = self.values.allocator().work().clone();
403 sort::sort(&mut self.values, &work, compare)
404 }
405}
406
407impl<T: Copy, W: Work> OwnedVec<T, W> {
408 pub fn try_extend_from_slice(&mut self, values: &[T]) -> core::result::Result<(), MemoryError> {
410 let work = values.len().max(core::mem::size_of_val(values));
411 self.values.allocator().work().charge_work(work as u64)?;
412 if self.values.capacity() == 0 {
413 self.try_reserve_exact(values.len())?;
414 } else {
415 self.try_reserve(values.len())?;
416 }
417 self.values.extend_from_slice(values);
418 Ok(())
419 }
420 pub fn try_copy(&self) -> core::result::Result<Self, MemoryError> {
422 let mut copy = self.values.allocator().work().vector();
423 let work = self.values.len().max(core::mem::size_of_val(&**self));
424 self.values.allocator().work().charge_work(work as u64)?;
425 copy.try_reserve_exact(self.values.len())?;
426 copy.values.extend_from_slice(&self.values);
428 Ok(copy)
429 }
430}
431
432impl<T, W: Work> Deref for OwnedVec<T, W> {
433 type Target = [T];
434 fn deref(&self) -> &[T] {
435 &self.values
436 }
437}
438
439impl<T, W: Work> DerefMut for OwnedVec<T, W> {
440 fn deref_mut(&mut self) -> &mut [T] {
441 &mut self.values
442 }
443}
444
445impl<'a, T, W: Work> IntoIterator for &'a OwnedVec<T, W> {
446 type Item = &'a T;
447 type IntoIter = core::slice::Iter<'a, T>;
448 fn into_iter(self) -> Self::IntoIter {
449 self.iter()
450 }
451}
452
453impl<'a, T, W: Work> IntoIterator for &'a mut OwnedVec<T, W> {
454 type Item = &'a mut T;
455 type IntoIter = core::slice::IterMut<'a, T>;
456 fn into_iter(self) -> Self::IntoIter {
457 self.iter_mut()
458 }
459}
460
461pub struct OwnedIter<T, W: Work = Memory> {
463 values: allocator_api2::vec::IntoIter<T, allocator::AccountAllocator<W>>,
464}
465
466impl<T, W: Work> Iterator for OwnedIter<T, W> {
467 type Item = T;
468 fn next(&mut self) -> Option<T> {
469 self.values.next()
470 }
471 fn size_hint(&self) -> (usize, Option<usize>) {
472 self.values.size_hint()
473 }
474}
475
476impl<T, W: Work> DoubleEndedIterator for OwnedIter<T, W> {
477 fn next_back(&mut self) -> Option<T> {
478 self.values.next_back()
479 }
480}
481
482impl<T, W: Work> ExactSizeIterator for OwnedIter<T, W> {}
483impl<T, W: Work> core::iter::FusedIterator for OwnedIter<T, W> {}
484
485impl<T, W: Work> IntoIterator for OwnedVec<T, W> {
486 type Item = T;
487 type IntoIter = OwnedIter<T, W>;
488 fn into_iter(self) -> Self::IntoIter {
489 OwnedIter {
490 values: self.values.into_iter(),
491 }
492 }
493}
494
495#[cfg(test)]
496mod tests;