VTK  9.7.1
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
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 
29 VTK_ABI_NAMESPACE_BEGIN
30 template <class ScalarTypeT>
32 {
33 public:
35  typedef ScalarTypeT ScalarType;
36 
37  static vtkBuffer<ScalarTypeT>* New();
39 
43  ScalarType* GetBuffer() { return this->Pointer; }
44  const ScalarType* GetBuffer() const { return this->Pointer; }
45 
51  void SetBuffer(VTK_ZEROCOPY ScalarType* array, vtkIdType size);
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 
104 protected:
106  : Pointer(nullptr)
107  , Size(0)
108  {
112  }
113 
114  ~vtkBuffer() override { this->SetBuffer(nullptr, 0); }
115 
116  ScalarType* Pointer;
121 
122 private:
123  vtkBuffer(const vtkBuffer&) = delete;
124  void operator=(const vtkBuffer&) = delete;
125 };
126 
127 template <class ScalarT>
129 {
131 }
132 
133 template <class ScalarT>
135 {
136  auto mkhold = vtkMemkindRAII(true);
137  return vtkBuffer<ScalarT>::New();
138 }
139 
140 //------------------------------------------------------------------------------
141 template <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 //------------------------------------------------------------------------------
167 template <typename ScalarT>
169 {
170  this->MallocFunction = mallocFunction;
171 }
172 //------------------------------------------------------------------------------
173 template <typename ScalarT>
175 {
176  this->ReallocFunction = reallocFunction;
177 }
178 
179 //------------------------------------------------------------------------------
180 template <typename ScalarT>
181 void 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 //------------------------------------------------------------------------------
194 template <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 //------------------------------------------------------------------------------
230 template <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 
301 VTK_ABI_NAMESPACE_END
302 #endif
303 // VTK-HeaderTest-Exclude: vtkBuffer.h
static vtkBuffer< ScalarTypeT > * New()
Definition: vtkBuffer.h:128
static vtkBuffer< ScalarTypeT > * ExtendedNew()
Definition: vtkBuffer.h:134
void SetReallocFunction(vtkReallocingFunction reallocFunction=realloc)
Set the realloc function to be used when allocating space inside this object.
Definition: vtkBuffer.h:174
vtkFreeingFunction DeleteFunction
Definition: vtkBuffer.h:120
void SetFreeFunction(bool noFreeFunction, vtkFreeingFunction deleteFunction)
Set the free function to be used when releasing this object.
Definition: vtkBuffer.h:181
void * GetVoidBuffer() override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition: vtkBuffer.h:87
void(* vtkFreeingFunction)(void *)
Definition: vtkObjectBase.h:66
vtkIdType GetSize() const
Return the number of elements the current buffer can hold.
Definition: vtkBuffer.h:81
int vtkIdType
Definition: vtkType.h:363
A class to help modify and restore the global UsingMemkind state, like SetUsingMemkind(newValue), but safer.
void SetMallocFunction(vtkMallocingFunction mallocFunction=malloc)
Set the malloc function to be used when allocating space inside this object.
Definition: vtkBuffer.h:168
vtkTemplateTypeMacro(vtkBuffer< ScalarTypeT >, vtkAbstractBuffer)
static vtkReallocingFunction GetCurrentReallocFunction()
vtkIdType GetNumberOfElements() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition: vtkBuffer.h:88
vtkMallocingFunction MallocFunction
Definition: vtkBuffer.h:118
internal storage class used by vtkSOADataArrayTemplate, vtkAOSDataArrayTemplate, and others...
Definition: vtkBuffer.h:31
ScalarType * GetBuffer()
Access the buffer as a scalar pointer.
Definition: vtkBuffer.h:43
ScalarType * Pointer
Definition: vtkBuffer.h:116
void SetBuffer(ScalarType *array, vtkIdType size)
Set the memory buffer that this vtkBuffer object will manage.
Definition: vtkBuffer.h:142
ScalarTypeT ScalarType
Definition: vtkBuffer.h:35
void *(* vtkMallocingFunction)(size_t)
Definition: vtkObjectBase.h:64
#define VTK_STANDARD_NEW_BODY(thisClass)
bool Reallocate(vtkIdType newsize)
Allocate a new buffer that holds newsize elements.
Definition: vtkBuffer.h:231
bool Allocate(vtkIdType size)
Allocate a new buffer that holds size elements.
Definition: vtkBuffer.h:195
int GetDataTypeSize() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition: vtkBuffer.h:90
static vtkFreeingFunction GetCurrentFreeFunction()
#define VTK_ZEROCOPY
Abstract base class for vtkBuffer providing buffer protocol support.
const ScalarType * GetBuffer() const
Definition: vtkBuffer.h:44
~vtkBuffer() override
Definition: vtkBuffer.h:114
void SetFreeFunction(bool noFreeFunction)
Set whether the buffer should be freed when this object is deleted or resized.
Definition: vtkBuffer.h:76
void *(* vtkReallocingFunction)(void *, size_t)
Definition: vtkObjectBase.h:65
int GetDataType() const override
vtkAbstractBuffer interface implementation for Python buffer protocol support.
Definition: vtkBuffer.h:89
vtkReallocingFunction ReallocFunction
Definition: vtkBuffer.h:119
static vtkMallocingFunction GetCurrentMallocFunction()
Template defining traits of native types used by VTK.
Definition: vtkTypeTraits.h:25
vtkIdType Size
Definition: vtkBuffer.h:117