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