VTK  9.6.20260307
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 std::copy(this->Pointer, this->Pointer + std::min(this->Size, newsize), newArray);
259 // now save the new array and release the old one too.
260 this->SetBuffer(newArray, newsize);
261 // The second check is needed because the array passed in may have been
262 // allocated outside the memory management of `vtkBuffer` and therefore
263 // have been registered with a `DeleteFunction` such as `delete` or
264 // `delete[]`. Since the memory is now allocated with `malloc` here,
265 // we must also reset `DeleteFunction` to something which matches.
266 if (!this->MallocFunction || this->MallocFunction == malloc)
267 {
268 this->DeleteFunction = free;
269 }
270 }
271 else
272 {
273 // Try to reallocate with minimal memory usage and possibly avoid copying.
274 ScalarType* newArray = nullptr;
275 if (this->ReallocFunction && this->ReallocFunction != realloc)
276 {
277 newArray = static_cast<ScalarType*>(
278 this->ReallocFunction(this->Pointer, newsize * sizeof(ScalarType)));
279 }
280 else if constexpr (std::is_trivially_copyable_v<ScalarType>)
281 {
282 newArray = static_cast<ScalarType*>(realloc(this->Pointer, newsize * sizeof(ScalarType)));
283 }
284 else
285 {
286 vtkErrorMacro("Reallocate is not supported for non-trivially copyable types with realloc.");
287 return false;
288 }
289 if (!newArray)
290 {
291 return false;
292 }
293 this->Pointer = newArray;
294 this->Size = newsize;
295 }
296 return true;
297}
298
299VTK_ABI_NAMESPACE_END
300#endif
301// 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