Open3D (C++ API)  0.16.0
MemoryAllocation.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// The MIT License (MIT)
5//
6// Copyright (c) 2018-2021 www.open3d.org
7//
8// Permission is hereby granted, free of charge, to any person obtaining a copy
9// of this software and associated documentation files (the "Software"), to deal
10// in the Software without restriction, including without limitation the rights
11// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12// copies of the Software, and to permit persons to whom the Software is
13// furnished to do so, subject to the following conditions:
14//
15// The above copyright notice and this permission notice shall be included in
16// all copies or substantial portions of the Software.
17//
18// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24// IN THE SOFTWARE.
25// ----------------------------------------------------------------------------
26
27#pragma once
28
29#include <iostream>
30#include <memory>
31#include <stdexcept>
32#include <utility>
33#include <vector>
34
35namespace open3d {
36namespace core {
37namespace nns {
38
41public:
49 MemoryAllocation(void* ptr, size_t size, size_t alignment = 1)
50 : _ptr(ptr),
51 _size(size),
52 _alignment(alignment),
53 _max_size_ptr((char*)ptr) {
54 // align start and end of memory segment
55 void* aligned_ptr = std::align(_alignment, 1, ptr, size);
56 size_t size_after_align =
57 (((char*)ptr + size) - (char*)aligned_ptr) / _alignment;
58 size_after_align *= _alignment;
59 _free_segments.push_back(
60 std::pair<void*, size_t>(aligned_ptr, size_after_align));
61 }
62
66 template <class T>
67 std::pair<T*, size_t> Alloc(size_t size) {
68 std::pair<void*, size_t> tmp = Alloc(size * sizeof(T));
69 return std::pair<T*, size_t>((T*)tmp.first, tmp.first ? size : 0);
70 }
71
74 std::pair<void*, size_t> Alloc(size_t size) {
75 // round up to alignment
76 if (size % _alignment) size += _alignment - size % _alignment;
77
78 for (size_t i = 0; i < _free_segments.size(); ++i) {
79 void* ptr = std::align(_alignment, size, _free_segments[i].first,
80 _free_segments[i].second);
81 if (ptr) {
82 char* end_ptr = (char*)ptr + size;
83 if (end_ptr > _max_size_ptr) _max_size_ptr = end_ptr;
84
85 _free_segments[i].first = end_ptr;
86 _free_segments[i].second -= size;
87 return std::pair<void*, size_t>(ptr, size);
88 }
89 }
90 return std::pair<void*, size_t>(nullptr, 0);
91 }
92
94 std::pair<void*, size_t> AllocLargestSegment() {
95 size_t size = 0;
96 for (const auto& s : _free_segments)
97 if (s.second > size) size = s.second;
98
99 return Alloc(size);
100 }
101
103 template <class T>
104 void Free(const std::pair<T*, size_t>& segment) {
105 size_t size = sizeof(T) * segment.second;
106 if (size % _alignment) size += _alignment - size % _alignment;
107
108 Free(std::pair<void*, size_t>(segment.first, size));
109 }
110
112 void Free(const std::pair<void*, size_t>& segment) {
113 if (DEBUG) {
114 if ((char*)segment.first < (char*)_ptr ||
115 (char*)segment.first + segment.second > (char*)_ptr + _size)
116 throw std::runtime_error("free(): segment is out of bounds");
117 }
118 {
119 size_t i;
120 for (i = 0; i < _free_segments.size(); ++i) {
121 if ((char*)segment.first < (char*)_free_segments[i].first)
122 break;
123 }
124 _free_segments.insert(_free_segments.begin() + i, segment);
125 }
126
127 // merge adjacent segments
128 auto seg = _free_segments[0];
129 char* end_ptr = (char*)seg.first + seg.second;
130 size_t count = 0;
131 for (size_t i = 1; i < _free_segments.size(); ++i) {
132 const auto& seg_i = _free_segments[i];
133
134 if (end_ptr == (char*)seg_i.first) {
135 // merge with adjacent following segment
136 seg.second += seg_i.second;
137 end_ptr = (char*)seg.first + seg.second;
138 } else {
139 _free_segments[count] = seg;
140 seg = _free_segments[i];
141 end_ptr = (char*)seg.first + seg.second;
142 ++count;
143 }
144 }
145 _free_segments[count] = seg;
146 ++count;
147 _free_segments.resize(count);
148
149 if (DEBUG) {
150 // check if there are overlapping segments
151 for (size_t i = 1; i < _free_segments.size(); ++i) {
152 char* prev_end_ptr = (char*)_free_segments[i - 1].first +
153 _free_segments[i - 1].second;
154 if (prev_end_ptr > (char*)_free_segments[i].first) {
155 throw std::runtime_error(
156 "free(): Overlapping free segments found after "
157 "call to free");
158 }
159 }
160 }
161 }
162
164 size_t MaxUsed() const { return _max_size_ptr - (char*)_ptr; }
165
167 size_t Alignment() const { return _alignment; }
168
170 const std::vector<std::pair<void*, size_t>>& FreeSegments() const {
171 return _free_segments;
172 }
173
175 template <class T>
176 static void PrintSegment(const std::pair<T*, size_t>& s) {
177 std::cerr << "ptr " << (void*)s.first << "\t size " << s.second
178 << "\t end " << (void*)((char*)s.first + s.second) << "\n";
179 }
180
182 void PrintFreeSegments() const {
183 for (const auto& s : _free_segments) PrintSegment(s);
184 }
185
186private:
187 enum internal_config { DEBUG = 0 };
188
190 const void* _ptr;
191
193 const size_t _size;
194
196 const size_t _alignment;
197
199 char* _max_size_ptr;
200
203 std::vector<std::pair<void*, size_t>> _free_segments;
204};
205
206} // namespace nns
207} // namespace core
208} // namespace open3d
A class for managing memory segments within a memory allocation.
Definition: MemoryAllocation.h:40
void Free(const std::pair< T *, size_t > &segment)
Frees a previously returned segment.
Definition: MemoryAllocation.h:104
static void PrintSegment(const std::pair< T *, size_t > &s)
Prints the segment. Meant for debugging.
Definition: MemoryAllocation.h:176
size_t MaxUsed() const
Returns the peak memory usage in bytes.
Definition: MemoryAllocation.h:164
MemoryAllocation(void *ptr, size_t size, size_t alignment=1)
Definition: MemoryAllocation.h:49
void Free(const std::pair< void *, size_t > &segment)
Frees a previously returned segment.
Definition: MemoryAllocation.h:112
std::pair< void *, size_t > Alloc(size_t size)
Definition: MemoryAllocation.h:74
std::pair< T *, size_t > Alloc(size_t size)
Definition: MemoryAllocation.h:67
void PrintFreeSegments() const
Prints all free segments. Meant for debugging.
Definition: MemoryAllocation.h:182
const std::vector< std::pair< void *, size_t > > & FreeSegments() const
Returns the list of free segments.
Definition: MemoryAllocation.h:170
size_t Alignment() const
Returns the alignment in bytes.
Definition: MemoryAllocation.h:167
std::pair< void *, size_t > AllocLargestSegment()
Returns the largest free segment.
Definition: MemoryAllocation.h:94
int size
Definition: FilePCD.cpp:59
int count
Definition: FilePCD.cpp:61
Definition: PinholeCameraIntrinsic.cpp:35