File: TestArrayFreeFunctions.cxx

package info (click to toggle)
vtk9 9.5.2%2Bdfsg3-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 205,984 kB
  • sloc: cpp: 2,336,570; ansic: 327,116; python: 111,200; yacc: 4,104; java: 3,977; sh: 3,032; xml: 2,771; perl: 2,189; lex: 1,787; makefile: 181; javascript: 165; objc: 153; tcl: 59
file content (209 lines) | stat: -rw-r--r-- 6,276 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkAbstractArray.h"

// Helpers:
#include "vtkAOSDataArrayTemplate.h"
#include "vtkBitArray.h"
#include "vtkFloatArray.h"
#include "vtkNew.h"
#include "vtkSOADataArrayTemplate.h"
#ifdef VTK_USE_SCALED_SOA_ARRAYS
#include "vtkScaledSOADataArrayTemplate.h"
#endif
#include "vtkStringArray.h"

#include <cstdint>
#include <cstdio>

// Forward declare the test function:
namespace
{

//------------------------------------------------------------------------------
struct UseFree
{
  static const int value = vtkAbstractArray::VTK_DATA_ARRAY_FREE;
};

struct UseDelete
{
  static const int value = vtkAbstractArray::VTK_DATA_ARRAY_DELETE;
};

struct UseAlignedFree
{
  static const int value = vtkAbstractArray::VTK_DATA_ARRAY_ALIGNED_FREE;
};

struct UseLambda
{
  static const int value = vtkAbstractArray::VTK_DATA_ARRAY_USER_DEFINED;
};

int timesLambdaFreeCalled = 0;

//------------------------------------------------------------------------------
#define testAssert(expr, errorMessage)                                                             \
  do                                                                                               \
  {                                                                                                \
    if (!(expr))                                                                                   \
    {                                                                                              \
      ++errors;                                                                                    \
      vtkGenericWarningMacro(<< "Assertion failed: " #expr << "\n" << errorMessage);               \
    }                                                                                              \
  } while (false)

//------------------------------------------------------------------------------
void* make_allocation(UseFree, std::size_t size, int)
{
  return malloc(size);
}

void* make_allocation(UseDelete, std::size_t size, int type)
{
  // Std::string is weird. When UseDelete is passed it binds to a custom
  // free function that casts the memory to std::string*. So to not violate
  // this behavior we need to allocate as a string
  if (type == VTK_STRING)
  {
    return new std::string[size];
  }
  else
  {
    return new uint8_t[size];
  }
}

void* make_allocation(UseAlignedFree, std::size_t size, int)
{
#if defined(_WIN32)
  return _aligned_malloc(size, 16);
#else
  return malloc(size);
#endif
}

void* make_allocation(UseLambda, std::size_t size, int)
{
  return new uint8_t[size];
}

//------------------------------------------------------------------------------
template <typename FreeType>
void assign_user_free(FreeType, vtkAbstractArray*)
{
}

void assign_user_free(UseLambda, vtkAbstractArray* array)
{
  array->SetArrayFreeFunction(
    [](void* ptr)
    {
      delete[] reinterpret_cast<uint8_t*>(ptr);
      timesLambdaFreeCalled++;
    });
}

//------------------------------------------------------------------------------
template <typename FreeType>
int assign_void_array(
  FreeType, vtkAbstractArray* array, void* ptr, std::size_t size, bool vtkShouldFree)
{
  int errors = 0;
  if (vtkSOADataArrayTemplate<double>* is_soa =
        vtkArrayDownCast<vtkSOADataArrayTemplate<double>>(array))
  {
    is_soa->SetNumberOfComponents(1);
    is_soa->SetArray(0, reinterpret_cast<double*>(ptr), static_cast<vtkIdType>(size), false,
      !vtkShouldFree, FreeType::value);
  }
#ifdef VTK_USE_SCALED_SOA_ARRAYS
  else if (vtkScaledSOADataArrayTemplate<double>* is_scale_soa =
             vtkArrayDownCast<vtkScaledSOADataArrayTemplate<double>>(array))
  {
    is_scale_soa->SetNumberOfComponents(1);
    is_scale_soa->SetArray(0, reinterpret_cast<double*>(ptr), static_cast<vtkIdType>(size), false,
      !vtkShouldFree, FreeType::value);
  }
#endif
  else
  {
    const int save = vtkShouldFree ? 0 : 1;
    array->SetVoidArray(ptr, static_cast<vtkIdType>(size), save, FreeType::value);
    testAssert(array->GetVoidPointer(0) == ptr, "assignment failed");
  }
  return errors;
}

//------------------------------------------------------------------------------
template <typename FreeType>
int ExerciseDelete(FreeType f)
{
  int errors = 0;

  std::cout << "Starting tests for free type: " << f.value << std::endl;

  std::vector<vtkAbstractArray*> arrays;
  arrays.push_back(vtkStringArray::New());
  arrays.push_back(vtkBitArray::New());
  arrays.push_back(vtkFloatArray::New());
  arrays.push_back(vtkAOSDataArrayTemplate<double>::New());
  arrays.push_back(vtkSOADataArrayTemplate<double>::New());
#ifdef VTK_USE_SCALED_SOA_ARRAYS
  arrays.push_back(vtkScaledSOADataArrayTemplate<double>::New());
#endif
  const std::size_t size = 5000;
  for (auto it = arrays.begin(); it != arrays.end(); ++it)
  {

    vtkAbstractArray* array = *it;

    // test setting the array's memory and having it not free the memory
    void* ptr = make_allocation(f, size, array->GetDataType());
    errors += assign_void_array(f, array, ptr, size, false);

    // ask array to free memory, ptr should still be valid
    array->Initialize();

    // This time ask the array to free the memory
    errors += assign_void_array(f, array, ptr, size, true);

    // if we are a lambda we need to set the real free function
    assign_user_free(f, array);

    // free the memory for real this time
    array->Initialize();
  }

  for (auto it = arrays.begin(); it != arrays.end(); ++it)
  {
    vtkAbstractArray* array = *it;
    array->Delete();
  }

  return errors;
}

} // end anon namespace

//-------------Test Entry Point-------------------------------------------------
int TestArrayFreeFunctions(int, char*[])
{
  int errors = 0;

  errors += ExerciseDelete(UseFree{});
  errors += ExerciseDelete(UseDelete{});
  errors += ExerciseDelete(UseAlignedFree{});
  errors += ExerciseDelete(UseLambda{});
  if (timesLambdaFreeCalled != 5)
  {
    std::cerr << "Test failed! Lambda free not called " << std::endl;
  }
  if (errors > 0)
  {
    std::cerr << "Test failed! Error count: " << errors << std::endl;
  }

  return errors == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}