1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 #ifndef OPENCV_UTILS_BUFFER_AREA_HPP
5 #define OPENCV_UTILS_BUFFER_AREA_HPP
6 
7 #include <opencv2/core/base.hpp>
8 #include <opencv2/core/private.hpp>
9 #include <opencv2/core/utility.hpp>
10 #include <vector>
11 
12 namespace cv { namespace utils {
13 
14 //! @addtogroup core_utils
15 //! @{
16 
17 /** @brief Manages memory block shared by muliple buffers.
18 
19 This class allows to allocate one large memory block and split it into several smaller
20 non-overlapping buffers. In safe mode each buffer allocation will be performed independently,
21 this mode allows dynamic memory access instrumentation using valgrind or memory sanitizer.
22 
23 Safe mode can be explicitly switched ON in constructor. It will also be enabled when compiling with
24 memory sanitizer support or in runtime with the environment variable `OPENCV_BUFFER_AREA_ALWAYS_SAFE`.
25 
26 Example of usage:
27 @code
28 int * buf1 = 0;
29 double * buf2 = 0;
30 cv::util::BufferArea area;
31 area.allocate(buf1, 200); // buf1 = new int[200];
32 area.allocate(buf2, 1000, 64); // buf2 = new double[1000]; - aligned by 64
33 area.commit();
34 @endcode
35 
36 @note This class is considered private and should be used only in OpenCV itself. API can be changed.
37 */
38 class CV_EXPORTS BufferArea
39 {
40 public:
41     /** @brief Class constructor.
42 
43     @param safe Enable _safe_ operation mode, each allocation will be performed independently.
44     */
45     BufferArea(bool safe = false);
46 
47     /** @brief Class destructor
48 
49     All allocated memory well be freed. Each bound pointer will be reset to NULL.
50     */
51     ~BufferArea();
52 
53     /** @brief Bind a pointer to local area.
54 
55     BufferArea will store reference to the pointer and allocation parameters effectively owning the
56     pointer and allocated memory. This operation has the same parameters and does the same job
57     as the operator `new`, except allocation can be performed later during the BufferArea::commit call.
58 
59     @param ptr Reference to a pointer of type T. Must be NULL
60     @param count Count of objects to be allocated, it has the same meaning as in the operator `new`.
61     @param alignment Alignment of allocated memory. same meaning as in the operator `new` (C++17).
62                      Must be divisible by sizeof(T). Must be power of two.
63 
64     @note In safe mode allocation will be performed immediatly.
65     */
66     template <typename T>
allocate(T * & ptr,size_t count,ushort alignment=sizeof (T))67     void allocate(T*&ptr, size_t count, ushort alignment = sizeof(T))
68     {
69         CV_Assert(ptr == NULL);
70         CV_Assert(count > 0);
71         CV_Assert(alignment > 0);
72         CV_Assert(alignment % sizeof(T) == 0);
73         CV_Assert((alignment & (alignment - 1)) == 0);
74         allocate_((void**)(&ptr), static_cast<ushort>(sizeof(T)), count, alignment);
75 #ifndef OPENCV_ENABLE_MEMORY_SANITIZER
76         if (safe)
77 #endif
78             CV_Assert(ptr != NULL);
79     }
80 
81     /** @brief Fill one of buffers with zeroes
82 
83     @param ptr pointer to memory block previously added using BufferArea::allocate
84 
85     BufferArea::commit must be called before using this method
86     */
87     template <typename T>
zeroFill(T * & ptr)88     void zeroFill(T*&ptr)
89     {
90         CV_Assert(ptr);
91         zeroFill_((void**)&ptr);
92     }
93 
94     /** @brief Fill all buffers with zeroes
95 
96     BufferArea::commit must be called before using this method
97     */
98     void zeroFill();
99 
100     /** @brief Allocate memory and initialize all bound pointers
101 
102     Each pointer bound to the area with the BufferArea::allocate will be initialized and will be set
103     to point to a memory block with requested size and alignment.
104 
105     @note Does nothing in safe mode as all allocations will be performed by BufferArea::allocate
106     */
107     void commit();
108 
109     /** @brief Release all memory and unbind all pointers
110 
111     All memory will be freed and all pointers will be reset to NULL and untied from the area allowing
112     to call `allocate` and `commit` again.
113     */
114     void release();
115 
116 private:
117     BufferArea(const BufferArea &); // = delete
118     BufferArea &operator=(const BufferArea &); // = delete
119     void allocate_(void **ptr, ushort type_size, size_t count, ushort alignment);
120     void zeroFill_(void **ptr);
121 
122 private:
123     class Block;
124     std::vector<Block> blocks;
125 #ifndef OPENCV_ENABLE_MEMORY_SANITIZER
126     void * oneBuf;
127     size_t totalSize;
128     const bool safe;
129 #endif
130 };
131 
132 //! @}
133 
134 }} // cv::utils::
135 
136 #endif
137