1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::{internal, Base, RawMem};
use std::mem::size_of;
use std::{
alloc::{self, Layout, LayoutError},
io,
ptr::{self, NonNull},
};
pub struct GlobalMem<T>(Base<T>);
impl<T: Default> GlobalMem<T> {
pub fn new() -> Self {
Self(Base::new(NonNull::slice_from_raw_parts(
NonNull::dangling(),
0,
)))
}
fn layout_impl(capacity: usize) -> io::Result<Layout> {
Layout::array::<T>(capacity).map_err(io::Error::other)
}
unsafe fn on_reserved_impl(&mut self, new_capacity: usize) -> io::Result<&mut [T]> {
let old_capacity = self.0.allocated();
let ptr = if self.0.ptr.as_non_null_ptr() == NonNull::dangling() {
let layout = Self::layout_impl(new_capacity)?;
let ptr = alloc::alloc_zeroed(layout);
NonNull::slice_from_raw_parts(NonNull::new_unchecked(ptr), layout.size())
} else {
let new_capacity = new_capacity * size_of::<T>();
let ptr = internal::align_from(self.0.ptr);
let layout = Self::layout_impl(old_capacity)?;
let new = alloc::realloc(ptr.as_mut_ptr(), layout, new_capacity);
NonNull::slice_from_raw_parts(NonNull::new_unchecked(new), new_capacity)
};
self.0.ptr = internal::guaranteed_align_to(ptr);
for i in old_capacity..new_capacity {
self.0.ptr.as_mut_ptr().add(i).write(T::default());
}
Ok(self.0.ptr.as_mut())
}
}
impl<T: Default> Default for GlobalMem<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Default> RawMem<T> for GlobalMem<T> {
fn alloc(&mut self, capacity: usize) -> io::Result<&mut [T]> {
unsafe { self.on_reserved_impl(capacity) }
}
fn allocated(&self) -> usize {
self.0.allocated()
}
fn occupy(&mut self, capacity: usize) -> io::Result<()> {
self.0.occupy(capacity)
}
fn occupied(&self) -> usize {
self.0.occupied
}
}
impl<T> Drop for GlobalMem<T> {
fn drop(&mut self) {
unsafe {
let slice = self.0.ptr.as_mut();
for item in slice {
ptr::drop_in_place(item);
}
}
let _: Result<_, LayoutError> = try {
let ptr = self.0.ptr;
let layout = Layout::array::<T>(ptr.len())?;
unsafe {
let ptr = ptr.as_non_null_ptr().cast();
alloc::dealloc(ptr.as_ptr(), layout);
}
};
}
}