opencv_core/
memory.rs

1//! Memory management utilities for OpenCV
2
3use crate::{Error, Result};
4use std::alloc::{GlobalAlloc, Layout, System};
5use std::sync::atomic::{AtomicUsize, Ordering};
6
7/// Global memory statistics
8static ALLOCATED_BYTES: AtomicUsize = AtomicUsize::new(0);
9static ALLOCATION_COUNT: AtomicUsize = AtomicUsize::new(0);
10
11/// OpenCV memory allocator
12pub 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
35/// Initialize memory allocators
36pub fn init_allocators() -> Result<()> {
37    // Reset statistics
38    ALLOCATED_BYTES.store(0, Ordering::Relaxed);
39    ALLOCATION_COUNT.store(0, Ordering::Relaxed);
40    Ok(())
41}
42
43/// Get current memory usage
44pub fn get_memory_usage() -> (usize, usize) {
45    (
46        ALLOCATED_BYTES.load(Ordering::Relaxed),
47        ALLOCATION_COUNT.load(Ordering::Relaxed),
48    )
49}
50
51/// Memory pool for efficient allocation
52pub struct MemoryPool {
53    block_size: usize,
54    blocks: Vec<Vec<u8>>,
55    free_list: Vec<*mut u8>,
56}
57
58impl MemoryPool {
59    /// Create a new memory pool
60    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        // Pre-allocate initial blocks
68        for _ in 0..initial_blocks {
69            pool.allocate_block();
70        }
71        
72        pool
73    }
74    
75    /// Allocate a new block
76    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    /// Get a memory block from the pool
84    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    /// Return a memory block to the pool
92    pub fn put(&mut self, ptr: *mut u8) {
93        self.free_list.push(ptr);
94    }
95}
96
97/// Aligned memory allocation
98pub 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
112/// Free aligned memory
113pub 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}