1use crate::{Error, Result};
4use std::alloc::{GlobalAlloc, Layout, System};
5use std::sync::atomic::{AtomicUsize, Ordering};
6
7static ALLOCATED_BYTES: AtomicUsize = AtomicUsize::new(0);
9static ALLOCATION_COUNT: AtomicUsize = AtomicUsize::new(0);
10
11pub struct OpenCVAllocator;
13
14unsafe impl GlobalAlloc for OpenCVAllocator {
15 unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
16 unsafe {
17 let ptr = System.alloc(layout);
18 if !ptr.is_null() {
19 ALLOCATED_BYTES.fetch_add(layout.size(), Ordering::Relaxed);
20 ALLOCATION_COUNT.fetch_add(1, Ordering::Relaxed);
21 }
22 ptr
23 }
24 }
25
26 unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
27 unsafe {
28 System.dealloc(ptr, layout);
29 ALLOCATED_BYTES.fetch_sub(layout.size(), Ordering::Relaxed);
30 ALLOCATION_COUNT.fetch_sub(1, Ordering::Relaxed);
31 }
32 }
33}
34
35pub fn init_allocators() -> Result<()> {
37 ALLOCATED_BYTES.store(0, Ordering::Relaxed);
39 ALLOCATION_COUNT.store(0, Ordering::Relaxed);
40 Ok(())
41}
42
43pub fn get_memory_usage() -> (usize, usize) {
45 (
46 ALLOCATED_BYTES.load(Ordering::Relaxed),
47 ALLOCATION_COUNT.load(Ordering::Relaxed),
48 )
49}
50
51pub struct MemoryPool {
53 block_size: usize,
54 blocks: Vec<Vec<u8>>,
55 free_list: Vec<*mut u8>,
56}
57
58impl MemoryPool {
59 pub fn new(block_size: usize, initial_blocks: usize) -> Self {
61 let mut pool = MemoryPool {
62 block_size,
63 blocks: Vec::new(),
64 free_list: Vec::new(),
65 };
66
67 for _ in 0..initial_blocks {
69 pool.allocate_block();
70 }
71
72 pool
73 }
74
75 fn allocate_block(&mut self) {
77 let mut block = vec![0u8; self.block_size];
78 let ptr = block.as_mut_ptr();
79 self.blocks.push(block);
80 self.free_list.push(ptr);
81 }
82
83 pub fn get(&mut self) -> *mut u8 {
85 if self.free_list.is_empty() {
86 self.allocate_block();
87 }
88 self.free_list.pop().unwrap()
89 }
90
91 pub fn put(&mut self, ptr: *mut u8) {
93 self.free_list.push(ptr);
94 }
95}
96
97pub fn allocate_aligned(size: usize, alignment: usize) -> Result<*mut u8> {
99 let layout = Layout::from_size_align(size, alignment)
100 .map_err(|_| Error::Memory("Invalid layout".into()))?;
101
102 unsafe {
103 let ptr = std::alloc::alloc(layout);
104 if ptr.is_null() {
105 Err(Error::Memory("Allocation failed".into()))
106 } else {
107 Ok(ptr)
108 }
109 }
110}
111
112pub unsafe fn deallocate_aligned(ptr: *mut u8, size: usize, alignment: usize) {
114 if let Ok(layout) = Layout::from_size_align(size, alignment) {
115 unsafe {
116 std::alloc::dealloc(ptr, layout);
117 }
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_memory_stats() {
127 let (bytes, count) = get_memory_usage();
128 assert!(bytes >= 0);
129 assert!(count >= 0);
130 }
131
132 #[test]
133 fn test_memory_pool() {
134 let mut pool = MemoryPool::new(1024, 10);
135
136 let ptr1 = pool.get();
137 let ptr2 = pool.get();
138
139 assert_ne!(ptr1, ptr2);
140
141 pool.put(ptr1);
142 pool.put(ptr2);
143 }
144
145 #[test]
146 fn test_aligned_allocation() {
147 let size = 1024;
148 let alignment = 16;
149
150 let ptr = allocate_aligned(size, alignment).unwrap();
151 assert!(!ptr.is_null());
152 assert_eq!(ptr as usize % alignment, 0);
153
154 unsafe {
155 deallocate_aligned(ptr, size, alignment);
156 }
157 }
158}