openPMD-api
Memory.hpp
1 /* Copyright 2017-2021 Fabian Koller
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include "openPMD/Dataset.hpp"
24 #include "openPMD/Datatype.hpp"
25 #include "openPMD/auxiliary/UniquePtr.hpp"
26 
27 #include <complex>
28 #include <functional>
29 #include <iostream>
30 #include <memory>
31 #include <type_traits>
32 #include <utility>
33 #include <variant>
34 
35 namespace openPMD
36 {
37 namespace auxiliary
38 {
39  inline std::unique_ptr<void, std::function<void(void *)>>
40  allocatePtr(Datatype dtype, uint64_t numPoints)
41  {
42  void *data = nullptr;
43  std::function<void(void *)> del = [](void *) {};
44  switch (dtype)
45  {
46  using DT = Datatype;
47  case DT::VEC_STRING:
48  data = new char *[numPoints];
49  del = [](void *p) { delete[] static_cast<char **>(p); };
50  break;
51  case DT::VEC_LONG_DOUBLE:
52  case DT::LONG_DOUBLE:
53  data = new long double[numPoints];
54  del = [](void *p) { delete[] static_cast<long double *>(p); };
55  break;
56  case DT::ARR_DBL_7:
57  case DT::VEC_DOUBLE:
58  case DT::DOUBLE:
59  data = new double[numPoints];
60  del = [](void *p) { delete[] static_cast<double *>(p); };
61  break;
62  case DT::VEC_FLOAT:
63  case DT::FLOAT:
64  data = new float[numPoints];
65  del = [](void *p) { delete[] static_cast<float *>(p); };
66  break;
67  case DT::VEC_CLONG_DOUBLE:
68  case DT::CLONG_DOUBLE:
69  data = new std::complex<long double>[numPoints];
70  del = [](void *p) {
71  delete[] static_cast<std::complex<long double> *>(p);
72  };
73  break;
74  case DT::VEC_CDOUBLE:
75  case DT::CDOUBLE:
76  data = new std::complex<double>[numPoints];
77  del = [](void *p) {
78  delete[] static_cast<std::complex<double> *>(p);
79  };
80  break;
81  case DT::VEC_CFLOAT:
82  case DT::CFLOAT:
83  data = new std::complex<float>[numPoints];
84  del = [](void *p) {
85  delete[] static_cast<std::complex<float> *>(p);
86  };
87  break;
88  case DT::VEC_SHORT:
89  case DT::SHORT:
90  data = new short[numPoints];
91  del = [](void *p) { delete[] static_cast<short *>(p); };
92  break;
93  case DT::VEC_INT:
94  case DT::INT:
95  data = new int[numPoints];
96  del = [](void *p) { delete[] static_cast<int *>(p); };
97  break;
98  case DT::VEC_LONG:
99  case DT::LONG:
100  data = new long[numPoints];
101  del = [](void *p) { delete[] static_cast<long *>(p); };
102  break;
103  case DT::VEC_LONGLONG:
104  case DT::LONGLONG:
105  data = new long long[numPoints];
106  del = [](void *p) { delete[] static_cast<long long *>(p); };
107  break;
108  case DT::VEC_USHORT:
109  case DT::USHORT:
110  data = new unsigned short[numPoints];
111  del = [](void *p) { delete[] static_cast<unsigned short *>(p); };
112  break;
113  case DT::VEC_UINT:
114  case DT::UINT:
115  data = new unsigned int[numPoints];
116  del = [](void *p) { delete[] static_cast<unsigned int *>(p); };
117  break;
118  case DT::VEC_ULONG:
119  case DT::ULONG:
120  data = new unsigned long[numPoints];
121  del = [](void *p) { delete[] static_cast<unsigned long *>(p); };
122  break;
123  case DT::VEC_ULONGLONG:
124  case DT::ULONGLONG:
125  data = new unsigned long long[numPoints];
126  del = [](void *p) {
127  delete[] static_cast<unsigned long long *>(p);
128  };
129  break;
130  case DT::VEC_CHAR:
131  case DT::CHAR:
132  data = new char[numPoints];
133  del = [](void *p) { delete[] static_cast<char *>(p); };
134  break;
135  case DT::VEC_UCHAR:
136  case DT::UCHAR:
137  data = new unsigned char[numPoints];
138  del = [](void *p) { delete[] static_cast<unsigned char *>(p); };
139  break;
140  case DT::VEC_SCHAR:
141  case DT::SCHAR:
142  data = new signed char[numPoints];
143  del = [](void *p) { delete[] static_cast<signed char *>(p); };
144  break;
145  case DT::BOOL:
146  data = new bool[numPoints];
147  del = [](void *p) { delete[] static_cast<bool *>(p); };
148  break;
149  case DT::STRING:
150  /* user assigns c_str pointer */
151  break;
152  case DT::UNDEFINED:
153  default:
154  throw std::runtime_error(
155  "Unknown Attribute datatype (Pointer allocation)");
156  }
157 
158  return std::unique_ptr<void, std::function<void(void *)>>(data, del);
159  }
160 
161  inline std::unique_ptr<void, std::function<void(void *)>>
162  allocatePtr(Datatype dtype, Extent const &e)
163  {
164  uint64_t numPoints = 1u;
165  for (auto const &dimensionSize : e)
166  numPoints *= dimensionSize;
167  return allocatePtr(dtype, numPoints);
168  }
169 
170  /*
171  * A buffer for the WRITE_DATASET task that can either be a std::shared_ptr
172  * or a std::unique_ptr.
173  */
174  struct WriteBuffer
175  {
176  using EligibleTypes = std::
177  variant<std::shared_ptr<void const>, UniquePtrWithLambda<void>>;
178  EligibleTypes m_buffer;
179 
180  WriteBuffer() : m_buffer(UniquePtrWithLambda<void>())
181  {}
182 
183  template <typename... Args>
184  explicit WriteBuffer(Args &&...args)
185  : m_buffer(std::forward<Args>(args)...)
186  {}
187 
188  WriteBuffer(WriteBuffer &&) = default;
189  WriteBuffer(WriteBuffer const &) = delete;
190  WriteBuffer &operator=(WriteBuffer &&) = default;
191  WriteBuffer &operator=(WriteBuffer const &) = delete;
192 
193  WriteBuffer const &operator=(std::shared_ptr<void const> ptr)
194  {
195  m_buffer = std::move(ptr);
196  return *this;
197  }
198 
199  WriteBuffer const &operator=(UniquePtrWithLambda<void const> ptr)
200  {
201  m_buffer = std::move(ptr);
202  return *this;
203  }
204 
205  inline void const *get() const
206  {
207  return std::visit(
208  [](auto const &arg) {
209  // unique_ptr and shared_ptr both have the get() member, so
210  // we're being sneaky and don't distinguish the types here
211  return static_cast<void const *>(arg.get());
212  },
213  m_buffer);
214  }
215  };
216 } // namespace auxiliary
217 } // namespace openPMD
Public definitions of openPMD-api.
Definition: Date.cpp:29
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:51
Definition: Memory.hpp:175