risingwave_common/memory/
alloc.rs1use std::alloc::{AllocError, Allocator, Global, Layout};
16use std::ptr::NonNull;
17
18use allocator_api2::alloc::{AllocError as AllocErrorApi2, Allocator as AllocatorApi2};
19
20use crate::memory::MemoryContext;
21
22pub type MonitoredGlobalAlloc = MonitoredAlloc<Global>;
23
24pub struct MonitoredAlloc<A: Allocator> {
25 ctx: MemoryContext,
26 alloc: A,
27}
28
29impl<A: Allocator> MonitoredAlloc<A> {
30 pub fn new(ctx: MemoryContext, alloc: A) -> Self {
31 Self { ctx, alloc }
32 }
33}
34
35impl MonitoredGlobalAlloc {
36 pub fn with_memory_context(ctx: MemoryContext) -> Self {
37 Self { ctx, alloc: Global }
38 }
39
40 pub fn for_test() -> Self {
41 Self::with_memory_context(MemoryContext::none())
42 }
43}
44
45unsafe impl<A: Allocator> Allocator for MonitoredAlloc<A> {
46 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
47 let ret = self.alloc.allocate(layout)?;
48 self.ctx.add_unchecked(layout.size() as i64);
52 Ok(ret)
53 }
54
55 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
56 unsafe {
57 self.alloc.deallocate(ptr, layout);
58 self.ctx.add_unchecked(-(layout.size() as i64));
59 }
60 }
61}
62
63unsafe impl<A: Allocator> AllocatorApi2 for MonitoredAlloc<A> {
64 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocErrorApi2> {
65 let ret = self.alloc.allocate(layout).map_err(|_| AllocErrorApi2)?;
66 self.ctx.add_unchecked(layout.size() as i64);
68 Ok(ret)
69 }
70
71 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
72 unsafe {
73 self.alloc.deallocate(ptr, layout);
74 self.ctx.add_unchecked(-(layout.size() as i64));
75 }
76 }
77}
78
79impl<A: Allocator + Clone> Clone for MonitoredAlloc<A> {
80 fn clone(&self) -> Self {
81 Self {
82 ctx: self.ctx.clone(),
83 alloc: self.alloc.clone(),
84 }
85 }
86}