Mantid
Loading...
Searching...
No Matches
UniqueID.h
Go to the documentation of this file.
1#pragma once
2
3#include "MantidNexus/DllConfig.h"
5#include <atomic>
6
7// Forward declarations for needed HDF5 functions
8// NOTE declare extern "C" to prevent conflict with actual declaration
9// NOTE use MYH5DLL, set to match HDF5's H5_DLL, to allow Windows build
10#if defined(_MSC_VER) // on Windows builds
11#define MYH5DLL __declspec(dllimport)
12#else
13#define MYH5DLL // gcc and clang do not need a DLL specifier
14#endif
15extern "C" {
19}
20
21namespace Mantid::Nexus {
22
24constexpr hid_t INVALID_HID{-1};
25
30template <herr_t (*const D)(hid_t)> class Hdf5ID {
31protected:
33
34 void close();
35
36public:
37 // constructors
38 Hdf5ID() noexcept : m_id(INVALID_HID) {}
39 Hdf5ID(hid_t const id) noexcept : m_id(id) {}
40
41 // comparators
42 bool operator==(hid_t const id) const { return m_id == id; }
43 bool operator!=(hid_t const id) const { return m_id != id; }
44 bool operator<=(hid_t const id) const { return m_id <= id; }
45 bool operator<(hid_t const id) const { return m_id < id; }
46
49 hid_t get() const { return m_id; }
50 operator hid_t() const { return m_id; }
53 bool isValid() const {
54 // fail early condition
55 if (m_id <= 0) {
56 return false;
57 } else {
58 return H5Iis_valid(m_id) > 0;
59 }
60 }
61};
62
64template <herr_t (*const closer)(hid_t)> inline void Hdf5ID<closer>::close() {
65 if (this->isValid()) {
66 closer(this->m_id);
67 this->m_id = INVALID_HID;
68 }
69}
70
72template <> inline void Hdf5ID<&H5Fclose>::close() {
73 if (this->isValid()) {
74 H5Fclose(this->m_id);
75 this->m_id = INVALID_HID;
76 // call garbage collection to close any and all open objects on this file
78 }
79}
80
81// ******************************************************************
82// UNIQUE ID
83// ******************************************************************
84
92template <herr_t (*const D)(hid_t)> class UniqueID : public Hdf5ID<D> {
93private:
94 // prohibit copying a unique ID
95 UniqueID(UniqueID<D> const &) = delete;
96 UniqueID &operator=(UniqueID<D> const &) = delete;
97
98public:
99 // constructors / destructor
100 UniqueID() : Hdf5ID<D>() {}
101 UniqueID(hid_t const id) : Hdf5ID<D>(id) {}
102 UniqueID(UniqueID<D> &&uid) noexcept : Hdf5ID<D>(uid.m_id) { uid.m_id = INVALID_HID; }
103 ~UniqueID() { this->close(); }
104
105 // assignment
108
109 void reset() { reset(INVALID_HID); };
110 void reset(hid_t const);
111 void reset(UniqueID<D> const &) = delete;
114};
115
118template <herr_t (*const D)(hid_t)> inline hid_t UniqueID<D>::release() {
119 hid_t tmp = this->m_id;
120 this->m_id = INVALID_HID;
121 return tmp;
122}
123
126template <herr_t (*const D)(hid_t)> inline void UniqueID<D>::reset(hid_t const id) {
127 if (this->m_id != id) {
128 this->close();
129 this->m_id = id;
130 }
131}
132
135template <herr_t (*const D)(hid_t)> inline void UniqueID<D>::reset(UniqueID<D> &&uid) {
136 if (this != &uid) {
137 reset(uid.m_id);
138 uid.m_id = INVALID_HID;
139 }
140}
141
144template <herr_t (*const D)(hid_t)> inline UniqueID<D> &UniqueID<D>::operator=(hid_t const id) {
145 reset(id);
146 return *this;
147}
148
151template <herr_t (*const D)(hid_t)> inline UniqueID<D> &UniqueID<D>::operator=(UniqueID<D> &&uid) {
152 reset(std::move(uid));
153 return *this;
154}
155
156// ******************************************************************
157// SHARED ID
158// ******************************************************************
159
167template <herr_t (*const D)(hid_t)> class SharedID : public Hdf5ID<D> {
168private:
169 std::atomic<std::size_t> *m_leash_counts;
172
173public:
174 // constructors / destructor
175 SharedID() : Hdf5ID<D>(), m_leash_counts(nullptr) {}
176 SharedID(hid_t id) : Hdf5ID<D>(id), m_leash_counts(this->isValid() ? new std::atomic<std::size_t>(1) : nullptr) {}
181 uid.m_id = INVALID_HID;
182 uid.m_leash_counts = nullptr;
183 }
185
189
191 bool operator==(SharedID<D> const &uid) const {
192 if (m_leash_counts == uid.m_leash_counts) {
193 return this->m_id == uid.m_id;
194 } else {
195 return false;
196 }
197 }
198
200 std::size_t use_count() const { return (m_leash_counts ? (*m_leash_counts).load() : 0); }
201
202 void reset() { reset(INVALID_HID); };
203 void reset(hid_t const);
204 void reset(SharedID<D> const &);
205 void reset(SharedID<D> &&);
206};
207
210template <herr_t (*const D)(hid_t)> inline void SharedID<D>::reset(hid_t const id) {
211 if (this->m_id != id) {
212 decrement_leash_counts();
213 this->m_id = id;
214 m_leash_counts = nullptr;
215 increment_leash_counts();
216 }
217}
218
221template <herr_t (*const D)(hid_t)> inline void SharedID<D>::reset(SharedID<D> const &uid) {
222 if (&uid != this && uid.m_id != this->m_id) {
223 decrement_leash_counts();
224 this->m_id = uid.m_id;
225 m_leash_counts = uid.m_leash_counts;
226 increment_leash_counts();
227 }
228}
229
232template <herr_t (*const D)(hid_t)> inline void SharedID<D>::reset(SharedID<D> &&uid) {
233 if (&uid != this && uid.m_id != this->m_id) {
234 decrement_leash_counts();
235 this->m_id = uid.m_id;
236 m_leash_counts = uid.m_leash_counts;
237 // unset the moved id
238 uid.m_id = INVALID_HID;
239 uid.m_leash_counts = nullptr;
240 // no increment -- number of leashes is same
241 }
242}
243
244template <herr_t (*const D)(hid_t)> inline void SharedID<D>::increment_leash_counts() {
245 if (this->isValid()) {
246 if (!m_leash_counts) {
247 m_leash_counts = new std::atomic<std::size_t>(1);
248 } else {
249 (*m_leash_counts)++;
250 }
251 }
252}
253
254template <herr_t (*const D)(hid_t)> inline void SharedID<D>::decrement_leash_counts() {
255 if (m_leash_counts) {
256 // atomic-safe access the counts
257 std::size_t prev_counts = (*m_leash_counts).fetch_sub(1);
258 if (prev_counts == 1) {
259 this->close();
260 delete m_leash_counts;
261 m_leash_counts = nullptr;
262 } else if (prev_counts == 0) {
263 m_leash_counts->store(0);
264 delete m_leash_counts;
265 m_leash_counts = nullptr;
266 }
267 }
268}
269
270template <herr_t (*const D)(hid_t)> inline SharedID<D> &SharedID<D>::operator=(hid_t id) {
271 reset(id);
272 return *this;
273}
274
275template <herr_t (*const D)(hid_t)> inline SharedID<D> &SharedID<D>::operator=(SharedID<D> const &uid) {
276 reset(uid);
277 return *this;
278}
279
280template <herr_t (*const D)(hid_t)> inline SharedID<D> &SharedID<D>::operator=(SharedID<D> &&uid) {
281 reset(std::move(uid));
282 return *this;
283}
284
285} // namespace Mantid::Nexus
gsl_vector * tmp
int64_t hid_t
This class defines data types which are used as part of the Nexus API.
int herr_t
MYH5DLL herr_t H5Fclose(hid_t)
MYH5DLL herr_t H5Iis_valid(hid_t)
MYH5DLL herr_t H5garbage_collect()
#define MYH5DLL
Definition UniqueID.h:13
A very simple wrapper that holds an HDF5 object through its hid_t.
Definition UniqueID.h:30
bool operator<=(hid_t const id) const
Definition UniqueID.h:44
bool isValid() const
Return whether the UniqueId corresponds to a valid HDF5 object.
Definition UniqueID.h:53
hid_t get() const
Return the managed HDF5 handle.
Definition UniqueID.h:49
Hdf5ID(hid_t const id) noexcept
Definition UniqueID.h:39
bool operator==(hid_t const id) const
Definition UniqueID.h:42
Hdf5ID() noexcept
Definition UniqueID.h:38
bool operator!=(hid_t const id) const
Definition UniqueID.h:43
bool operator<(hid_t const id) const
Definition UniqueID.h:45
void close()
Close the held object ID.
Definition UniqueID.h:64
A wrapper class for managing HDF5 object handles (hid_t) that can be shared.
Definition UniqueID.h:167
SharedID< D > & operator=(hid_t const)
Definition UniqueID.h:270
SharedID(SharedID< D > const &uid)
Definition UniqueID.h:177
bool operator==(SharedID< D > const &uid) const
ensure two SharedIDs are tracking the same object
Definition UniqueID.h:191
std::atomic< std::size_t > * m_leash_counts
Definition UniqueID.h:169
std::size_t use_count() const
Returns the number of SharedID objects holding the same ID.
Definition UniqueID.h:200
SharedID(SharedID< D > &&uid)
Definition UniqueID.h:180
A wrapper class for managing HDF5 object handles (hid_t).
Definition UniqueID.h:92
void reset(UniqueID< D > &&)
Close the existing ID and replace with the new ID; or, set to invalid.
Definition UniqueID.h:135
hid_t release()
Release hold on the managed ID; it will not be closed by this UniqueID.
Definition UniqueID.h:118
UniqueID(UniqueID< D > const &)=delete
void reset(UniqueID< D > const &)=delete
UniqueID(UniqueID< D > &&uid) noexcept
Definition UniqueID.h:102
void reset(hid_t const)
Close the existing ID and replace with the new ID; or, set to invalid.
Definition UniqueID.h:126
UniqueID< D > & operator=(hid_t const)
Assign a HDF5 object ID to be managed.
Definition UniqueID.h:144
UniqueID< D > & operator=(UniqueID< D > &&)
Pass the HDF5 object ID from an existing UniqueID to another UniqueID.
Definition UniqueID.h:151
UniqueID(hid_t const id)
Definition UniqueID.h:101
UniqueID & operator=(UniqueID< D > const &)=delete
Header for a base Nexus::Exception.
constexpr hid_t INVALID_HID
an ID that HDF5 will always consider invalid
Definition UniqueID.h:24
STL namespace.