VTK  9.7.20260717
vtkBuffer.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2// SPDX-License-Identifier: BSD-3-Clause
18
19#ifndef vtkBuffer_h
20#define vtkBuffer_h
21
22#include "vtkAbstractBuffer.h"
23#include "vtkObjectFactory.h" // New() implementation
24#include "vtkTypeTraits.h" // For vtkTypeTraits
25
26#include <algorithm> // for std::min and std::copy
27#include <type_traits> // for std::is_trivially_copyable
28
29VTK_ABI_NAMESPACE_BEGIN
30template <class ScalarTypeT>
32{
33public:
35 typedef ScalarTypeT ScalarType;
36
39
43 ScalarType* GetBuffer() { return this->Pointer; }
44 const ScalarType* GetBuffer() const { return this->Pointer; }
45
52
56 void SetMallocFunction(vtkMallocingFunction mallocFunction = malloc);
57
61 void SetReallocFunction(vtkReallocingFunction reallocFunction = realloc);
62
69 void SetFreeFunction(bool noFreeFunction, vtkFreeingFunction deleteFunction);
70
76 void SetFreeFunction(bool noFreeFunction) { this->SetFreeFunction(noFreeFunction, free); }
77
81 vtkIdType GetSize() const { return this->Size; }
82
84
87 void* GetVoidBuffer() override { return this->Pointer; }
88 vtkIdType GetNumberOfElements() const override { return this->Size; }
89 int GetDataType() const override { return vtkTypeTraits<ScalarType>::VTKTypeID(); }
90 int GetDataTypeSize() const override { return sizeof(ScalarType); }
92
96 bool Allocate(vtkIdType size);
97
102 bool Reallocate(vtkIdType newsize);
103
104protected:
113
114 ~vtkBuffer() override { this->SetBuffer(nullptr, 0); }
115
116 ScalarType* Pointer;
121
122private:
123 vtkBuffer(const vtkBuffer&) = delete;
124 void operator=(const vtkBuffer&) = delete;
125};
126
127template <class ScalarT>
132
133template <class ScalarT>
135{
136 auto mkhold = vtkMemkindRAII(true);
138}
139
140//------------------------------------------------------------------------------
141template <typename ScalarT>
143{
144 if (this->Pointer != array)
145 {
146 if (this->DeleteFunction)
147 {
148 if (this->DeleteFunction != free)
149 {
150 this->DeleteFunction(this->Pointer);
151 }
152 else if constexpr (std::is_trivially_destructible_v<ScalarT>)
153 {
154 free(this->Pointer);
155 }
156 else
157 {
158 vtkErrorMacro("SetBuffer is not supported for non-trivially destructible types with free.");
159 return;
160 }
161 }
162 this->Pointer = array;
163 }
164 this->Size = sz;
165}
166//------------------------------------------------------------------------------
167template <typename ScalarT>
169{
170 this->MallocFunction = mallocFunction;
171}
172//------------------------------------------------------------------------------
173template <typename ScalarT>
175{
176 this->ReallocFunction = reallocFunction;
177}
178
179//------------------------------------------------------------------------------
180template <typename ScalarT>
181void vtkBuffer<ScalarT>::SetFreeFunction(bool noFreeFunction, vtkFreeingFunction deleteFunction)
182{
183 if (noFreeFunction)
184 {
185 this->DeleteFunction = nullptr;
186 }
187 else
188 {
189 this->DeleteFunction = deleteFunction;
190 }
191}
192
193//------------------------------------------------------------------------------
194template <typename ScalarT>
196{
197 // release old memory.
198 this->SetBuffer(nullptr, 0);
199 if (size > 0)
200 {
201 ScalarType* newArray = nullptr;
202 if (this->MallocFunction && this->MallocFunction != malloc)
203 {
204 newArray = static_cast<ScalarType*>(this->MallocFunction(size * sizeof(ScalarType)));
205 }
206 else if constexpr (std::is_trivially_constructible_v<ScalarType>)
207 {
208 newArray = static_cast<ScalarType*>(malloc(size * sizeof(ScalarType)));
209 }
210 else
211 {
212 vtkErrorMacro("Allocate is not supported for non-trivially constructible types with malloc.");
213 return false;
214 }
215 if (newArray)
216 {
217 this->SetBuffer(newArray, size);
218 if (!this->MallocFunction)
219 {
220 this->DeleteFunction = free;
221 }
222 return true;
223 }
224 return false;
225 }
226 return true; // size == 0
227}
228
229//------------------------------------------------------------------------------
230template <typename ScalarT>
232{
233 if (!this->Pointer || newsize == 0)
234 {
235 return this->Allocate(newsize);
236 }
237 if (this->DeleteFunction != free)
238 {
239 ScalarType* newArray = nullptr;
240 if (this->MallocFunction && this->MallocFunction != malloc)
241 {
242 newArray = static_cast<ScalarType*>(this->MallocFunction(newsize * sizeof(ScalarType)));
243 }
244 else if constexpr (std::is_trivially_constructible_v<ScalarType>)
245 {
246 newArray = static_cast<ScalarType*>(malloc(newsize * sizeof(ScalarType)));
247 }
248 else
249 {
250 vtkErrorMacro(
251 "Reallocate is not supported for non-trivially constructible types with malloc.");
252 return false;
253 }
254 if (!newArray)
255 {
256 return false;
257 }
258 // Wrap std::min in parentheses to prevent expansion of the min() macro defined by
259 // <windows.h> when NOMINMAX is not set.
260 std::copy(this->Pointer, this->Pointer + (std::min)(this->Size, newsize), newArray);
261 // now save the new array and release the old one too.
262 this->SetBuffer(newArray, newsize);
263 // The second check is needed because the array passed in may have been
264 // allocated outside the memory management of `vtkBuffer` and therefore
265 // have been registered with a `DeleteFunction` such as `delete` or
266 // `delete[]`. Since the memory is now allocated with `malloc` here,
267 // we must also reset `DeleteFunction` to something which matches.
268 if (!this->MallocFunction || this->MallocFunction == malloc)
269 {
270 this->DeleteFunction = free;
271 }
272 }
273 else
274 {
275 // Try to reallocate with minimal memory usage and possibly avoid copying.
276 ScalarType* newArray = nullptr;
277 if (this->ReallocFunction && this->ReallocFunction != realloc)
278 {
279 newArray = static_cast<ScalarType*>(
280 this->ReallocFunction(this->Pointer, newsize * sizeof(ScalarType)));
281 }
282 else if constexpr (std::is_trivially_copyable_v<ScalarType>)
283 {
284 newArray = static_cast<ScalarType*>(realloc(this->Pointer, newsize * sizeof(ScalarType)));
285 }
286 else
287 {
288 vtkErrorMacro("Reallocate is not supported for non-trivially copyable types with realloc.");
289 return false;
290 }
291 if (!newArray)
292 {
293 return false;
294 }
295 this->Pointer = newArray;
296 this->Size = newsize;
297 }
298 return true;
299}
300
301VTK_ABI_NAMESPACE_END
302#endif
303// VTK-HeaderTest-Exclude: vtkBuffer.h
vtkAbstractBuffer()=default
bool Reallocate(vtkIdType newsize)
Allocate a new buffer that holds newsize elements.
Definition vtkBuffer.h:231
ScalarType * Pointer
Definition vtkBuffer.h:116
ScalarType * GetBuffer()
Access the buffer as a scalar pointer.
Definition vtkBuffer.h:43
vtkFreeingFunction DeleteFunction
Definition vtkBuffer.h:120
vtkMallocingFunction MallocFunction
Definition vtkBuffer.h:118
const ScalarType * GetBuffer() const
Definition vtkBuffer.h:44
void * GetVoidBuffer() override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition vtkBuffer.h:87
vtkIdType Size
Definition vtkBuffer.h:117
vtkTemplateTypeMacro(vtkBuffer< ScalarTypeT >, vtkAbstractBuffer)
void SetReallocFunction(vtkReallocingFunction reallocFunction=realloc)
Set the realloc function to be used when allocating space inside this object.
Definition vtkBuffer.h:174
ScalarTypeT ScalarType
Definition vtkBuffer.h:35
static vtkBuffer< ScalarTypeT > * ExtendedNew()
Definition vtkBuffer.h:134
void SetMallocFunction(vtkMallocingFunction mallocFunction=malloc)
Set the malloc function to be used when allocating space inside this object.
Definition vtkBuffer.h:168
vtkIdType GetSize() const
Return the number of elements the current buffer can hold.
Definition vtkBuffer.h:81
int GetDataType() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition vtkBuffer.h:89
~vtkBuffer() override
Definition vtkBuffer.h:114
int GetDataTypeSize() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition vtkBuffer.h:90
vtkReallocingFunction ReallocFunction
Definition vtkBuffer.h:119
bool Allocate(vtkIdType size)
Allocate a new buffer that holds size elements.
Definition vtkBuffer.h:195
static vtkBuffer< ScalarTypeT > * New()
Definition vtkBuffer.h:128
vtkIdType GetNumberOfElements() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition vtkBuffer.h:88
void SetFreeFunction(bool noFreeFunction)
Set whether the buffer should be freed when this object is deleted or resized.
Definition vtkBuffer.h:76
void SetFreeFunction(bool noFreeFunction, vtkFreeingFunction deleteFunction)
Set the free function to be used when releasing this object.
Definition vtkBuffer.h:181
void SetBuffer(ScalarType *array, vtkIdType size)
Set the memory buffer that this vtkBuffer object will manage.
Definition vtkBuffer.h:142
A class to help modify and restore the global UsingMemkind state, like SetUsingMemkind(newValue),...
static vtkFreeingFunction GetCurrentFreeFunction()
static vtkMallocingFunction GetCurrentMallocFunction()
static vtkReallocingFunction GetCurrentReallocFunction()
Template defining traits of native types used by VTK.
void *(* vtkMallocingFunction)(size_t)
void *(* vtkReallocingFunction)(void *, size_t)
void(* vtkFreeingFunction)(void *)
#define VTK_STANDARD_NEW_BODY(thisClass)
int vtkIdType
Definition vtkType.h:363
#define VTK_ZEROCOPY