SIRF  3.4.0
DataHandle.h
Go to the documentation of this file.
1 /*
2 SyneRBI Synergistic Image Reconstruction Framework (SIRF)
3 Copyright 2015 - 2020 Rutherford Appleton Laboratory STFC
4 Copyright 2018 - 2019 University College London
5 This is software developed for the Collaborative Computational
6 Project in Synergistic Reconstruction for Biomedical Imaging (formerly CCP PETMR)
7 (http://www.ccpsynerbi.ac.uk/).
8 
9 Licensed under the Apache License, Version 2.0 (the "License");
10 you may not use this file except in compliance with the License.
11 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18 
19 */
20 
30 #ifndef DATA_HANDLE_TYPES
31 #define DATA_HANDLE_TYPES
32 
33 #include <stdlib.h>
34 #include <memory>
35 #include <string>
36 #include <vector>
37 
38 #include "sirf/iUtilities/LocalisedException.h"
39 
40 #define NEW(T, X) T* X = new T
41 #define CAST_PTR(T, X, Y) T* X = (T*)Y
42 //#define THROW(msg) throw LocalisedException(msg, __FILE__, __LINE__)
43 #define CATCH \
44  catch (LocalisedException& se) {\
45  ExecutionStatus status(se);\
46  DataHandle* handle = new DataHandle;\
47  handle->set(0, &status);\
48  return (void*)handle;\
49  }\
50  catch (std::string msg) {\
51  ExecutionStatus status(msg.c_str(), __FILE__, __LINE__);\
52  DataHandle* handle = new DataHandle;\
53  handle->set(0, &status);\
54  return (void*)handle;\
55  }\
56  catch (const std::exception &error) {\
57  ExecutionStatus status(error.what(), __FILE__, __LINE__);\
58  DataHandle* handle = new DataHandle;\
59  handle->set(0, &status);\
60  return (void*)handle;\
61  }\
62  catch (...) {\
63  ExecutionStatus status("unhandled", __FILE__, __LINE__);\
64  DataHandle* handle = new DataHandle;\
65  handle->set(0, &status);\
66  return (void*)handle;\
67  }\
68 
69 typedef std::vector<void const *> DataHandleVector;
71 
80 public:
81  ExecutionStatus() : _line(0) {}
82  ExecutionStatus(const std::string& error, const std::string& file, int line) {
83  set(error, file, line);
84  }
86  set(s.error(), s.file(), s.line());
87  }
89  set(ex.what(), ex.file(), ex.line());
90  }
91  ~ExecutionStatus() {}
92  const std::string& error() const { return _error; }
93  const std::string& file() const { return _file; }
94  int line() const { return _line; }
95 private:
96  std::string _error;
97  std::string _file;
98  int _line;
99  void set(const std::string& error, const std::string& file, int line) {
100  _error = error;
101  _file = file;
102  _line = line;
103  }
104 };
105 
115 class DataHandle {
116 public:
117  DataHandle() : _data(0), _status(0), _owns_data(0) {}
118  virtual ~DataHandle() {
119  if (_data && _owns_data)
120  free(_data);
121  delete _status;
122  }
123  static void* error_handle(const std::string& error, const std::string& file, int line)
124  {
125  DataHandle* handle = new DataHandle;
126  ExecutionStatus status(error, file, line);
127  handle->set(0, &status);
128  return handle;
129  }
130  void set(void* data, const ExecutionStatus* status = 0, int grab = 0) {
131  if (status) {
132  delete _status;
133  _status = new ExecutionStatus(*status);
134  }
135  if (_data && _owns_data)
136  free(_data);
137  _data = data;
138  _owns_data = grab != 0;
139  }
140  void set_status(const std::string& error, const std::string& file, int line)
141  {
142  if (_status)
143  delete _status;
144  _status = new ExecutionStatus(error, file, line);
145  }
146  void* data() const { return _data; }
147  const ExecutionStatus* status() const { return _status; }
148 protected:
149  bool _owns_data; // can free _data
150  void* _data; // data address
151  ExecutionStatus* _status; // execution status
152 };
153 
154 #if defined(USE_BOOST)
155 #include <boost/shared_ptr.hpp>
156 #endif
157 
158 template<class Base>
159 class ObjectHandle : public DataHandle {
160 public:
161  ObjectHandle(const ObjectHandle& obj) {
162 #if defined(USE_BOOST)
163  if (obj.uses_boost_sptr()) {
164  NEW(boost::shared_ptr<Base>, ptr_sptr);
165  *ptr_sptr = *(boost::shared_ptr<Base>*)obj.data();
166  _data = (void*)ptr_sptr;
167  }
168  else
169 #endif
170  {
171  NEW(std::shared_ptr<Base>, ptr_sptr);
172  *ptr_sptr = *(std::shared_ptr<Base>*)obj.data();
173  _data = (void*)ptr_sptr;
174  }
175  if (obj._status)
176  _status = new ExecutionStatus(*obj._status);
177  else
178  _status = 0;
179  }
180  ObjectHandle(const std::shared_ptr<Base>& sptr,
181  const ExecutionStatus* status = 0) : _boost_sptr(false) {
182  NEW(std::shared_ptr<Base>, ptr_sptr);
183  *ptr_sptr = sptr;
184  _data = (void*)ptr_sptr;
185  if (status)
186  _status = new ExecutionStatus(*status);
187  else
188  _status = 0;
189  }
190 #if defined(USE_BOOST)
191  ObjectHandle(const boost::shared_ptr<Base>& sptr,
192  const ExecutionStatus* status = 0) : _boost_sptr(true) {
193  NEW(boost::shared_ptr<Base>, ptr_sptr);
194  *ptr_sptr = sptr;
195  _data = (void*)ptr_sptr;
196  if (status)
197  _status = new ExecutionStatus(*status);
198  else
199  _status = 0;
200  }
201 #endif
202  virtual ~ObjectHandle() {
203  delete _status;
204  _status = 0;
205 #if defined(USE_BOOST)
206  if (_boost_sptr) {
207  CAST_PTR(boost::shared_ptr<Base>, ptr_sptr, _data);
208  delete ptr_sptr;
209  }
210  else
211 #endif
212  {
213  CAST_PTR(std::shared_ptr<Base>, ptr_sptr, _data);
214  delete ptr_sptr;
215  }
216  }
217  bool uses_boost_sptr() const
218  {
219  return _boost_sptr;
220  }
221 protected:
222  bool _boost_sptr;
223 };
224 
225 template<class Object>
226 static void*
227 newObjectHandle(std::shared_ptr<Object> sptr)
228 {
229  return (void*)new ObjectHandle<Object>(sptr);
230 }
231 
232 #if defined(USE_BOOST)
233 template<class Object>
234 static void*
235 newObjectHandle(boost::shared_ptr<Object> sptr)
236 {
237  return (void*)new ObjectHandle<Object>(sptr);
238 }
239 #endif
240 
241 template<class Object>
242 Object&
243 objectFromHandle(const void* h) {
245  void* ptr = handle->data();
246  if (ptr == 0)
247  THROW("zero data pointer cannot be dereferenced");
248 #if defined(USE_BOOST)
249  if (handle->uses_boost_sptr()) {
250  CAST_PTR(boost::shared_ptr<Object>, ptr_sptr, ptr);
251  Object* ptr_obj = ptr_sptr->get();
252  if (ptr_obj == 0)
253  THROW("zero object pointer cannot be dereferenced");
254  return *ptr_obj;
255  }
256  else
257 #endif
258  {
259  CAST_PTR(std::shared_ptr<Object>, ptr_sptr, ptr);
260  Object* ptr_obj = ptr_sptr->get();
261  if (ptr_obj == 0)
262  THROW("zero object pointer cannot be dereferenced");
263  return *ptr_obj;
264  }
265 }
266 
267 template<class Object>
268 void
269 getObjectSptrFromHandle(const void* h, std::shared_ptr<Object>& sptr) {
271 #if defined(USE_BOOST)
272  if (handle->uses_boost_sptr())
273  THROW("cannot cast boost::shared_ptr to std::shared_ptr");
274 #endif
275  void* ptr = handle->data();
276  if (ptr == 0)
277  THROW("zero data pointer cannot be dereferenced");
278  CAST_PTR(std::shared_ptr<Object>, ptr_sptr, ptr);
279  sptr = *ptr_sptr;
280 }
281 
282 #if defined(USE_BOOST)
283 template<class Object>
284 void
285 getObjectSptrFromHandle(const void* h, boost::shared_ptr<Object>& sptr) {
287  if (!handle->uses_boost_sptr())
288  THROW("cannot cast std::shared_ptr to boost::shared_ptr");
289  void* ptr = handle->data();
290  if (ptr == 0)
291  THROW("zero data pointer cannot be dereferenced");
292  CAST_PTR(boost::shared_ptr<Object>, ptr_sptr, ptr);
293  sptr = *ptr_sptr;
294 }
295 #endif
296 
297 #define GRAB 1
298 
307 template <typename T>
308 void
310 {
311  T* ptr = (T*)malloc(sizeof(T));
312  *ptr = x;
313  h->set((void*)ptr, 0, GRAB);
314 }
315 
322 template <typename T>
323 void*
325 {
326  DataHandle* h = new DataHandle;
327  setDataHandle<T>(h, x);
328  return (void*)h;
329 }
330 
337 template <typename T>
338 T
339 dataFromHandle(const void* ptr)
340 {
341  DataHandle* ptr_h = (DataHandle*)ptr;
342  void* ptr_d = ptr_h->data();
343  if (!ptr_d)
344  return 0;
345  else
346  return *((T*)ptr_d);
347 }
348 
349 // yet another kludge to stop matlab on linux from crashing
350 
351 inline char* charDataFromDataHandle(const DataHandle* ptr_h)
352 {
353  void* ptr_d = ptr_h->data();
354  if (!ptr_d)
355  return 0;
356  else
357  return (char*)ptr_d;
358 }
359 
360 inline void* charDataHandleFromCharData(const char* s)
361 {
362  DataHandle* h = new DataHandle;
363  size_t len = strlen(s);
364  char* d = (char*)malloc(len + 1);
365 #ifdef _MSC_VER
366  strcpy_s(d, len + 1, s);
367 #else
368  strcpy(d, s);
369 #endif
370  h->set((void*)d, 0, GRAB);
371  return (void*)h;
372 }
373 
374 #endif
Definition: LocalisedException.h:32
std::vector< void const * > DataHandleVector
Typedef of vector of void pointers for a vector of handles.
Definition: DataHandle.h:70
Basic wrapper for C++ objects.
Definition: DataHandle.h:115
void setDataHandle(DataHandle *h, T x)
DataHandle wrapper.
Definition: DataHandle.h:309
T dataFromHandle(const void *ptr)
Data extractor.
Definition: DataHandle.h:339
Execution status type.
Definition: DataHandle.h:79
Definition: DataHandle.h:159
void * dataHandle(T x)
Data wrapper constructor.
Definition: DataHandle.h:324