Handle.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_Handle_h
2 #define art_Framework_Principal_Handle_h
3 // vim: set sw=2 expandtab :
4 
5 //==========================================================================
6 // Handle: Non-owning "smart pointer" for reference to EDProducts and
7 // their Provenances.
8 //
9 // ValidHandle: A Handle that can not be invalid, and thus does not check
10 // for validity upon dereferencing.
11 //
12 // If the pointed-to EDProduct or Provenance is destroyed, use of the
13 // Handle becomes undefined. There is no way to query the Handle to
14 // discover if this has happened.
15 //
16 // Handles can have:
17 // -- Product and Provenance pointers both null;
18 // -- Both pointers valid
19 //
20 // ValidHandles must have Product and Provenance pointers valid.
21 //
22 // To check validity, one can use the Handle::isValid() function.
23 // ValidHandles cannot be invalid, and so have no validity checks.
24 //
25 // If failedToGet() returns true then the requested data is not available
26 // If failedToGet() returns false but isValid() is also false then no
27 // attempt to get data has occurred
28 //==========================================================================
29 
36 #include "cetlib_except/demangle.h"
37 #include "cetlib_except/exception.h"
38 
39 #include <memory>
40 #include <typeinfo>
41 
42 namespace art {
43 
44  template <typename T>
45  class Handle;
46  template <typename T>
47  class ValidHandle;
48  template <class T>
49  void swap(Handle<T>& a, Handle<T>& b);
50  template <class T>
52  template <class T>
54 
55  class EDProduct;
56  template <typename T>
57  class Wrapper;
58 
59  namespace detail {
60  template <typename... T>
61  void
62  throw_if_invalid(std::string const& msg, T const&... t)
63  {
64  bool const all_valid = true && (... && t.isValid());
65  if (!all_valid) {
66  throw Exception{art::errors::NullPointerError} << msg << '\n';
67  }
68  }
69  } // namespace detail
70 
71  template <class T>
73  range_of_validity(T const& h);
74  template <class T, class U>
76  T const& a,
77  U const& b);
78  template <class T, class U>
80  T const& a,
81  U const& b);
82  template <class T, class U>
84  T const& a,
85  U const& b);
86 
87 } // namespace art
88 
89 template <typename T>
90 class art::Handle {
91 public:
92  using element_type = T;
93  class HandleTag {};
94 
95  ~Handle() = default;
96  explicit constexpr Handle() =
97  default; // Default-constructed handles are invalid.
98  explicit Handle(GroupQueryResult const&);
99  Handle(Handle const&) = default;
100  Handle(Handle&&) = default;
101  Handle& operator=(Handle const&) = default;
102  Handle& operator=(Handle&&) = default;
103 
104  // pointer behaviors:
105  T const& operator*() const;
106  T const* operator->() const; // alias for product()
107  T const* product() const;
108 
109  // inspectors:
110  bool isValid() const;
111  bool failedToGet()
112  const; // was Handle used in a 'get' call whose data could not be found?
113  Provenance const* provenance() const;
114  ProductID id() const;
115  std::shared_ptr<art::Exception const> whyFailed() const;
116 
117  // mutators:
118  void swap(Handle<T>& other);
119  void clear();
120 
121 private:
122  T const* prod_{nullptr};
123  Provenance prov_{};
124  std::shared_ptr<art::Exception const> whyFailed_{nullptr};
125 }; // Handle<>
126 
127 // ----------------------------------------------------------------------
128 // c'tors:
129 
130 template <class T>
132  : prod_{nullptr}, prov_{gqr.result()}, whyFailed_{gqr.whyFailed()}
133 {
134  if (gqr.succeeded()) {
135  auto const wrapperPtr = dynamic_cast<Wrapper<T> const*>(
136  gqr.result()->uniqueProduct(TypeID{typeid(Wrapper<T>)}));
137  if (wrapperPtr != nullptr) {
138  prod_ = wrapperPtr->product();
139  } else {
141  e << "Product retrieval via Handle<T> succeeded for product:\n"
143  << "but an attempt to interpret it as an object of type '"
144  << cet::demangle_symbol(typeid(T).name()) << "' failed.\n";
145  whyFailed_ = std::make_shared<art::Exception const>(std::move(e));
146  }
147  }
148 }
149 
150 // ----------------------------------------------------------------------
151 // pointer behaviors:
152 
153 template <class T>
154 inline T const& art::Handle<T>::operator*() const
155 {
156  return *product();
157 }
158 
159 template <class T>
160 T const*
162 {
163  if (failedToGet()) {
164  throw *whyFailed_;
165  }
166  if (prod_ == nullptr)
168  << "Attempt to de-reference product that points to 'nullptr'.\n";
169  return prod_;
170 }
171 
172 template <class T>
173 inline T const* art::Handle<T>::operator->() const
174 {
175  return product();
176 }
177 
178 // ----------------------------------------------------------------------
179 // inspectors:
180 
181 template <class T>
182 bool
184 {
185  return prod_ && prov_.isValid();
186 }
187 
188 template <class T>
189 bool
191 {
192  return whyFailed_.get();
193 }
194 
195 template <class T>
196 inline art::Provenance const*
198 {
199  return &prov_;
200 }
201 
202 template <class T>
203 inline art::ProductID
205 {
206  // FIXME: returning prov_.productID() should be sufficient since
207  // ProductID{} is invalid anyway.
208  return prov_.isValid() ? prov_.productID() : ProductID{};
209 }
210 
211 template <class T>
212 inline std::shared_ptr<art::Exception const>
214 {
215  return whyFailed_;
216 }
217 
218 // ----------------------------------------------------------------------
219 // mutators:
220 
221 template <class T>
222 void
224 {
225  std::swap(*this, other);
226 }
227 
228 template <class T>
229 void
231 {
232  Handle<T> tmp;
233  swap(tmp);
234 }
235 
236 // ======================================================================
237 // Non-members:
238 
239 // Convert from handle-to-EDProduct to handle-to-T
240 template <class T>
241 void
243 {
244  Handle<T> h{orig};
245  result.swap(h);
246 }
247 
248 // ======================================================================
249 template <typename T>
250 class art::ValidHandle {
251 public:
252  typedef T element_type;
253  class HandleTag {};
254 
255  ~ValidHandle() = default;
256  ValidHandle() = delete;
257  explicit ValidHandle(T const* prod, Provenance prov);
258  ValidHandle(ValidHandle const&) = default;
259  ValidHandle(ValidHandle&&) = default;
260  ValidHandle& operator=(ValidHandle const&) & = default;
261  ValidHandle& operator=(ValidHandle&&) & = default;
262 
263  // pointer behaviors
264  operator T const*() const; // conversion to T const*
265  T const& operator*() const;
266  T const* operator->() const; // alias for product()
267  T const* product() const;
268 
269  // inspectors
270  bool isValid() const; // always true
271  bool failedToGet() const; // always false
272  Provenance const* provenance() const;
273  ProductID id() const;
274  std::shared_ptr<art::Exception const> whyFailed() const; // always null
275 
276  // mutators
277  void swap(ValidHandle<T>& other);
278 
279  // No clear() function, because a ValidHandle does not have an invalid
280  // state, and that is what the result of clear() would have to be.
281 
282 private:
283  T const* prod_;
285 };
286 
287 template <class T>
289  : prod_{prod}, prov_{prov}
290 {
291  if (prod == nullptr) {
293  << "Attempt to create ValidHandle with null pointer";
294  }
295 }
296 
297 template <class T>
298 inline art::ValidHandle<T>::operator T const*() const
299 {
300  return prod_;
301 }
302 
303 template <class T>
304 inline T const& art::ValidHandle<T>::operator*() const
305 {
306  return *prod_;
307 }
308 
309 template <class T>
310 inline T const* art::ValidHandle<T>::operator->() const
311 {
312  return prod_;
313 }
314 
315 template <class T>
316 inline T const*
318 {
319  return prod_;
320 }
321 
322 template <class T>
323 inline bool
325 {
326  return true;
327 }
328 
329 template <class T>
330 inline bool
332 {
333  return false;
334 }
335 
336 template <class T>
337 inline art::Provenance const*
339 {
340  return &prov_;
341 }
342 
343 template <class T>
344 inline art::ProductID
346 {
347  return prov_.productID();
348 }
349 
350 template <class T>
351 inline std::shared_ptr<art::Exception const>
353 {
354  return std::shared_ptr<art::Exception const>();
355 }
356 
357 template <class T>
358 inline void
360 {
361  std::swap(*this, other);
362 }
363 
364 // ======================================================================
365 // Non-members:
366 
367 template <class T>
369 art::range_of_validity(T const& h)
370 {
371  std::string const& errMsg =
372  "Attempt to retrieve range set from invalid handle.";
373  detail::throw_if_invalid(errMsg, h);
374  return h.provenance()->rangeOfValidity();
375 }
376 
377 template <class T, class U>
379 art::same_ranges(T const& a, U const& b)
380 {
381  std::string const& errMsg =
382  "Attempt to compare range sets where one or both handles are invalid.";
383  detail::throw_if_invalid(errMsg, a, b);
385 }
386 
387 template <class T, class U>
389 art::disjoint_ranges(T const& a, U const& b)
390 {
391  std::string const& errMsg =
392  "Attempt to compare range sets where one or both handles are invalid.";
393  detail::throw_if_invalid(errMsg, a, b);
395 }
396 
397 template <class T, class U>
399 art::overlapping_ranges(T const& a, U const& b)
400 {
401  std::string const& errMsg =
402  "Attempt to compare range sets where one or both handles are invalid.";
403  detail::throw_if_invalid(errMsg, a, b);
405 }
406 
407 #endif /* art_Framework_Principal_Handle_h */
408 
409 // Local Variables:
410 // mode: c++
411 // End:
::xsd::cxx::tree::id< char, ncname > id
Definition: Database.h:165
Handle & operator=(Handle const &)=default
const XML_Char * name
Definition: expat.h:151
Provenance prov_
Definition: Handle.h:284
std::enable_if_t< detail::is_handle< T >::value, RangeSet const & > range_of_validity(T const &h)
T const * prod_
Definition: Handle.h:122
std::shared_ptr< art::Exception const > whyFailed_
Definition: Handle.h:124
vector< vector< double > > clear
void swap(Handle< T > &other)
Definition: Handle.h:223
T const & operator*() const
Definition: Handle.h:304
Float_t tmp
Definition: plot.C:36
bool isValid() const
T const * product() const
Definition: Handle.h:317
ValidHandle()=delete
bool isValid() const
Definition: Handle.h:183
float_mat operator*(const float_mat &a, const float_mat &b)
matrix multiplication.
static const char *const errMsg[]
Definition: Error.h:69
T const * product() const
Definition: Handle.h:161
const XML_Char int const XML_Char * value
Definition: expat.h:331
ProductID id() const
Definition: Handle.h:345
void swap(Handle< T > &a, Handle< T > &b)
Provenance const * provenance() const
Definition: Handle.h:197
const double a
T const * operator->() const
Definition: Handle.h:310
void convert_handle(GroupQueryResult const &, Handle< T > &)
Definition: Handle.h:242
art::art::TriggerResults element_type
Definition: Handle.h:92
std::enable_if_t< detail::are_handles< T, U >::value, bool > disjoint_ranges(T const &a, U const &b)
Provenance const * provenance() const
Definition: Handle.h:338
ProductID productID() const
constexpr Handle()=default
void throw_if_invalid(std::string const &msg, T const &...t)
Definition: Handle.h:62
Provenance prov_
Definition: Handle.h:123
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
T const * operator->() const
Definition: Handle.h:173
void swap(ValidHandle< T > &a, ValidHandle< T > &b)
T const & operator*() const
Definition: Handle.h:154
T const * prod_
Definition: Handle.h:283
void clear()
Definition: Handle.h:230
std::enable_if_t< detail::are_handles< T, U >::value, bool > overlapping_ranges(T const &a, U const &b)
std::enable_if_t< detail::are_handles< T, U >::value, bool > same_ranges(T const &a, U const &b)
const hit & b
Definition: hits.cxx:21
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
bool failedToGet() const
Definition: Handle.h:331
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:352
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:213
double T
Definition: Xdiff_gwt.C:5
BranchDescription const & productDescription() const
Float_t e
Definition: plot.C:35
ProductID id() const
Definition: Handle.h:204
void swap(ValidHandle< T > &other)
Definition: Handle.h:359
bool failedToGet() const
Definition: Handle.h:190
bool isValid() const
Definition: Handle.h:324
enum BeamMode string