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 text;
22mod work;
23pub use map::{HashWork, MapExecution, OwnedMap, RetainError};
24pub use shared_string::SharedString;
25pub use sort::SortError;
26pub use string::OwnedString;
27pub use text::{OwnedText, TextError, TextErrorKind};
28pub use work::{Execution, Work};
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum MemoryError {
33 LimitExceeded,
35 OutOfMemory,
37 CapacityOverflow,
39 WorkExceeded,
41}
42
43impl fmt::Display for MemoryError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.write_str(match self {
46 Self::LimitExceeded => "memory budget spent",
47 Self::OutOfMemory => "allocator could not supply storage",
48 Self::CapacityOverflow => "storage capacity overflow",
49 Self::WorkExceeded => "work budget spent",
50 })
51 }
52}
53
54impl core::error::Error for MemoryError {}
55
56#[derive(Debug)]
61pub struct MemoryAccount {
62 limit: usize,
63 used: AtomicUsize,
64 work_limit: usize,
65 work: AtomicUsize,
66}
67
68impl MemoryAccount {
69 #[must_use]
71 pub const fn new(limit: usize, work_limit: usize) -> Self {
72 Self {
73 limit,
74 used: AtomicUsize::new(0),
75 work_limit,
76 work: AtomicUsize::new(0),
77 }
78 }
79
80 fn reserve(&self, bytes: usize) -> core::result::Result<Reservation<'_>, MemoryError> {
81 let mut used = self.used.load(Ordering::Relaxed);
82 loop {
83 debug_assert!(used <= self.limit);
84 if bytes > self.limit - used {
85 return Err(MemoryError::LimitExceeded);
86 }
87 match self.used.compare_exchange_weak(
88 used,
89 used + bytes,
90 Ordering::Relaxed,
91 Ordering::Relaxed,
92 ) {
93 Ok(_) => {
94 return Ok(Reservation {
95 account: self,
96 bytes,
97 });
98 }
99 Err(current) => used = current,
100 }
101 }
102 }
103
104 fn release(&self, bytes: usize) {
105 let previous = self.used.fetch_sub(bytes, Ordering::Relaxed);
106 debug_assert!(previous >= bytes);
107 }
108}
109
110struct Reservation<'a> {
111 account: &'a MemoryAccount,
112 bytes: usize,
113}
114
115impl Reservation<'_> {
116 fn commit(mut self) {
117 self.bytes = 0;
118 }
119}
120
121impl Drop for Reservation<'_> {
122 fn drop(&mut self) {
123 self.account.release(self.bytes);
124 }
125}
126
127#[derive(Debug, Clone)]
131pub struct Memory {
132 account: Arc<MemoryAccount>,
133}
134
135impl Memory {
136 #[must_use]
138 pub fn new(account: Arc<MemoryAccount>) -> Self {
139 Self { account }
140 }
141
142 #[must_use]
144 pub fn limit(&self) -> usize {
145 self.account.limit
146 }
147
148 #[must_use]
150 pub fn used(&self) -> usize {
151 self.account.used.load(Ordering::Relaxed)
152 }
153
154 #[must_use]
156 pub fn same_account(&self, other: &Self) -> bool {
157 Arc::ptr_eq(&self.account, &other.account)
158 }
159
160 #[must_use]
162 pub fn work_used(&self) -> usize {
163 self.account.work.load(Ordering::Relaxed)
164 }
165
166 #[must_use]
170 pub fn work_remaining(&self) -> usize {
171 let spent = self.account.work.load(Ordering::Relaxed);
172 debug_assert!(spent <= self.account.work_limit);
173 self.account.work_limit - spent
174 }
175
176 pub fn charge_work(&self, amount: u64) -> core::result::Result<(), MemoryError> {
181 let amount = usize::try_from(amount).map_err(|_| MemoryError::WorkExceeded)?;
182 let mut spent = self.account.work.load(Ordering::Relaxed);
183 loop {
184 debug_assert!(spent <= self.account.work_limit);
185 if amount > self.account.work_limit - spent {
186 return Err(MemoryError::WorkExceeded);
187 }
188 match self.account.work.compare_exchange_weak(
189 spent,
190 spent + amount,
191 Ordering::Relaxed,
192 Ordering::Relaxed,
193 ) {
194 Ok(_) => return Ok(()),
195 Err(current) => spent = current,
196 }
197 }
198 }
199
200 pub fn reserve(&self, bytes: usize) -> core::result::Result<MemoryReservation, MemoryError> {
206 let reservation = self.account.reserve(bytes)?;
207 reservation.commit();
208 Ok(MemoryReservation {
209 memory: self.clone(),
210 bytes,
211 })
212 }
213
214 #[must_use]
216 pub fn vector<T>(&self) -> OwnedVec<T> {
217 Work::vector(self)
218 }
219
220 #[must_use]
222 pub fn map<K: HashWork, V>(&self) -> OwnedMap<K, V> {
223 OwnedMap::new(self.clone())
224 }
225
226 #[must_use]
228 pub fn string(&self) -> OwnedString {
229 OwnedString::new(self)
230 }
231}
232
233#[derive(Debug)]
238#[must_use = "retain the reservation until its allocation has been deallocated"]
239pub struct MemoryReservation {
240 memory: Memory,
241 bytes: usize,
242}
243
244impl Drop for MemoryReservation {
245 fn drop(&mut self) {
246 self.memory.account.release(self.bytes);
247 }
248}
249
250pub struct OwnedVec<T, W: Work = Memory> {
258 values: Vec<T, allocator::AccountAllocator<W>>,
259}
260
261#[must_use]
264pub enum VecExecution<T, Old: Work, New: Work> {
265 Changed {
267 values: OwnedVec<T, New>,
269 previous: Old,
271 },
272 Foreign {
274 values: OwnedVec<T, Old>,
276 requested: New,
278 },
279}
280
281impl<T> OwnedVec<T> {
282 pub fn with_execution<W: Work>(self, execution: &W) -> Result<OwnedVec<T, W>, Self> {
291 if !self.memory().same_account(execution.memory()) {
292 return Err(self);
293 }
294 Ok(OwnedVec {
295 values: allocator::scope(self.values, execution),
296 })
297 }
298}
299
300impl<T, W: Work> OwnedVec<T, W> {
301 pub(crate) fn work(&self) -> &W {
302 self.values.allocator().work()
303 }
304
305 pub fn rebind<New: Work>(self, execution: New) -> VecExecution<T, W, New> {
309 if !self.memory().same_account(execution.memory()) {
310 return VecExecution::Foreign {
311 values: self,
312 requested: execution,
313 };
314 }
315 let (values, previous) = allocator::rebind(self.values, &execution);
316 VecExecution::Changed {
317 values: OwnedVec { values },
318 previous,
319 }
320 }
321 #[must_use]
349 pub fn into_owned(self) -> OwnedVec<T> {
350 OwnedVec {
351 values: allocator::retain(self.values),
352 }
353 }
354}
355
356impl<T: fmt::Debug, W: Work> fmt::Debug for OwnedVec<T, W> {
357 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358 self.values.fmt(f)
359 }
360}
361
362impl<T: PartialEq, W: Work> PartialEq for OwnedVec<T, W> {
363 fn eq(&self, other: &Self) -> bool {
364 **self == **other
365 }
366}
367
368impl<T: Eq, W: Work> Eq for OwnedVec<T, W> {}
369
370impl<T: PartialEq, W: Work, const N: usize> PartialEq<[T; N]> for OwnedVec<T, W> {
371 fn eq(&self, other: &[T; N]) -> bool {
372 &**self == other
373 }
374}
375
376impl<T, W: Work> OwnedVec<T, W> {
377 #[must_use]
379 pub fn memory(&self) -> &Memory {
380 self.values.allocator().memory()
381 }
382 #[must_use]
384 pub fn capacity(&self) -> usize {
385 self.values.capacity()
386 }
387
388 pub fn try_reserve_exact(
390 &mut self,
391 additional: usize,
392 ) -> core::result::Result<(), MemoryError> {
393 self.values.allocator().clear_failure();
394 self.values
395 .try_reserve_exact(additional)
396 .map_err(|error| match error.kind() {
397 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
398 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
399 })
400 }
401
402 pub fn try_reserve(&mut self, additional: usize) -> core::result::Result<(), MemoryError> {
404 self.values.allocator().clear_failure();
405 self.values
406 .try_reserve(additional)
407 .map_err(|error| match error.kind() {
408 TryReserveErrorKind::CapacityOverflow => MemoryError::CapacityOverflow,
409 TryReserveErrorKind::AllocError { .. } => self.values.allocator().failure(),
410 })
411 }
412
413 pub fn try_push(&mut self, value: T) -> core::result::Result<(), MemoryError> {
415 self.values.allocator().work().charge_work(1)?;
416 if self.values.len() == self.values.capacity() {
417 self.try_reserve(1)?;
418 }
419 self.values.push(value);
421 Ok(())
422 }
423
424 pub fn pop(&mut self) -> Option<T> {
426 self.values.pop()
427 }
428
429 pub fn clear(&mut self) {
431 self.values.clear();
432 }
433
434 pub fn try_drain_all(
448 &mut self,
449 ) -> Result<
450 impl DoubleEndedIterator<Item = T> + ExactSizeIterator + core::iter::FusedIterator + '_,
451 MemoryError,
452 > {
453 let work = self.values.len().max(core::mem::size_of_val(&**self));
454 self.values.allocator().work().charge_work(work as u64)?;
455 Ok(self.values.drain(..))
456 }
457
458 pub fn try_sort_unstable_by<E>(
464 &mut self,
465 compare: impl FnMut(&T, &T) -> core::result::Result<core::cmp::Ordering, E>,
466 ) -> core::result::Result<(), SortError<E>> {
467 let work = self.values.allocator().work().clone();
468 sort::sort(&mut self.values, &work, compare)
469 }
470}
471
472impl<T: Copy, W: Work> OwnedVec<T, W> {
473 pub fn try_extend_from_slice(&mut self, values: &[T]) -> core::result::Result<(), MemoryError> {
475 let work = values.len().max(core::mem::size_of_val(values));
476 self.values.allocator().work().charge_work(work as u64)?;
477 if self.values.capacity() == 0 {
478 self.try_reserve_exact(values.len())?;
479 } else {
480 self.try_reserve(values.len())?;
481 }
482 self.values.extend_from_slice(values);
483 Ok(())
484 }
485 pub fn try_copy(&self) -> core::result::Result<Self, MemoryError> {
487 let mut copy = self.values.allocator().work().vector();
488 let work = self.values.len().max(core::mem::size_of_val(&**self));
489 self.values.allocator().work().charge_work(work as u64)?;
490 copy.try_reserve_exact(self.values.len())?;
491 copy.values.extend_from_slice(&self.values);
493 Ok(copy)
494 }
495}
496
497impl<T, W: Work> Deref for OwnedVec<T, W> {
498 type Target = [T];
499 fn deref(&self) -> &[T] {
500 &self.values
501 }
502}
503
504impl<T, W: Work> DerefMut for OwnedVec<T, W> {
505 fn deref_mut(&mut self) -> &mut [T] {
506 &mut self.values
507 }
508}
509
510impl<'a, T, W: Work> IntoIterator for &'a OwnedVec<T, W> {
511 type Item = &'a T;
512 type IntoIter = core::slice::Iter<'a, T>;
513 fn into_iter(self) -> Self::IntoIter {
514 self.iter()
515 }
516}
517
518impl<'a, T, W: Work> IntoIterator for &'a mut OwnedVec<T, W> {
519 type Item = &'a mut T;
520 type IntoIter = core::slice::IterMut<'a, T>;
521 fn into_iter(self) -> Self::IntoIter {
522 self.iter_mut()
523 }
524}
525
526pub struct OwnedIter<T, W: Work = Memory> {
528 values: allocator_api2::vec::IntoIter<T, allocator::AccountAllocator<W>>,
529}
530
531impl<T, W: Work> Iterator for OwnedIter<T, W> {
532 type Item = T;
533 fn next(&mut self) -> Option<T> {
534 self.values.next()
535 }
536 fn size_hint(&self) -> (usize, Option<usize>) {
537 self.values.size_hint()
538 }
539}
540
541impl<T, W: Work> DoubleEndedIterator for OwnedIter<T, W> {
542 fn next_back(&mut self) -> Option<T> {
543 self.values.next_back()
544 }
545}
546
547impl<T, W: Work> ExactSizeIterator for OwnedIter<T, W> {}
548impl<T, W: Work> core::iter::FusedIterator for OwnedIter<T, W> {}
549
550impl<T, W: Work> IntoIterator for OwnedVec<T, W> {
551 type Item = T;
552 type IntoIter = OwnedIter<T, W>;
553 fn into_iter(self) -> Self::IntoIter {
554 OwnedIter {
555 values: self.values.into_iter(),
556 }
557 }
558}
559
560#[cfg(test)]
561mod tests;