Handle.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_Handle_h
2 #define art_Framework_Principal_Handle_h
3 
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 // ======================================================================
30 
37 #include "cetlib_except/demangle.h"
38 #include "cetlib_except/exception.h"
39 
40 #include <memory>
41 #include <typeinfo>
42 
43 namespace art {
44  // defined herein:
45  template <typename T>
46  class Handle;
47  template <typename T>
48  class ValidHandle;
49  template <class T>
50  void swap(Handle<T>& a, Handle<T>& b);
51  template <class T>
53  template <class T>
55 
56  // forward declarations:
57  class EDProduct;
58  template <typename T>
59  class Wrapper;
60 
61  namespace detail {
62  inline void
64  {}
65 
66  template <typename H, typename... T>
67  void
68  throw_if_invalid(std::string const& msg, H const& h, T const&... t)
69  {
70  if (!h.isValid())
71  throw Exception{art::errors::NullPointerError} << msg << '\n';
72  throw_if_invalid(msg, t...);
73  }
74  }
75 
76  template <class T>
78  range_of_validity(T const& h);
79 
80  template <class T, class U>
82  T const& a,
83  U const& b);
84 
85  template <class T, class U>
87  T const& a,
88  U const& b);
89 
90  template <class T, class U>
92  T const& a,
93  U const& b);
94 }
95 
96 // ======================================================================
97 
98 template <typename T>
99 class art::Handle {
100 public:
101  using element_type = T;
102  class HandleTag {};
103 
104  // c'tors:
105  explicit constexpr Handle() =
106  default; // Default-constructed handles are invalid.
107  explicit Handle(GroupQueryResult const&);
108 
109  // pointer behaviors:
110  T const& operator*() const;
111  T const* operator->() const; // alias for product()
112  T const* product() const;
113 
114  // inspectors:
115  bool isValid() const;
116  bool failedToGet()
117  const; // was Handle used in a 'get' call whose data could not be found?
118  Provenance const* provenance() const;
119  ProductID id() const;
120  std::shared_ptr<art::Exception const> whyFailed() const;
121 
122  // mutators:
123  void swap(Handle<T>& other);
124  void clear();
125 
126 private:
127  T const* prod_{nullptr};
128  Provenance prov_{};
129  std::shared_ptr<art::Exception const> whyFailed_{nullptr};
130 }; // Handle<>
131 
132 // ----------------------------------------------------------------------
133 // c'tors:
134 
135 template <class T>
137  : prod_{nullptr}, prov_{gqr.result()}, whyFailed_{gqr.whyFailed()}
138 {
139  if (gqr.succeeded()) {
140  auto const wrapperPtr = dynamic_cast<Wrapper<T> const*>(
141  gqr.result()->uniqueProduct(TypeID{typeid(Wrapper<T>)}));
142  if (wrapperPtr == nullptr) {
144  e << "Product retrieval via Handle<T> succeeded for product:\n"
146  << "but an attempt to interpret it as an object of type '"
147  << cet::demangle_symbol(typeid(T).name()) << "' failed.\n";
148  whyFailed_ = std::make_shared<art::Exception const>(std::move(e));
149  } else {
150  prod_ = wrapperPtr->product();
151  }
152  }
153 }
154 
155 // ----------------------------------------------------------------------
156 // pointer behaviors:
157 
158 template <class T>
159 inline T const& art::Handle<T>::operator*() const
160 {
161  return *product();
162 }
163 
164 template <class T>
165 T const*
167 {
168  if (failedToGet())
169  throw *whyFailed_;
170 
171  if (prod_ == nullptr)
173  << "Attempt to de-reference product that points to 'nullptr'";
174 
175  return prod_;
176 }
177 
178 template <class T>
179 inline T const* art::Handle<T>::operator->() const
180 {
181  return product();
182 }
183 
184 // ----------------------------------------------------------------------
185 // inspectors:
186 
187 template <class T>
188 bool
190 {
191  return prod_ && prov_.isValid();
192 }
193 
194 template <class T>
195 bool
197 {
198  return whyFailed_.get();
199 }
200 
201 template <class T>
202 inline art::Provenance const*
204 {
205  return &prov_;
206 }
207 
208 template <class T>
209 inline art::ProductID
211 {
212  // FIXME: returning prov_.productID() should be sufficient since
213  // ProductID{} is invalid anyway.
214  return prov_.isValid() ? prov_.productID() : ProductID{};
215 }
216 
217 template <class T>
218 inline std::shared_ptr<art::Exception const>
220 {
221  return whyFailed_;
222 }
223 
224 // ----------------------------------------------------------------------
225 // mutators:
226 
227 template <class T>
228 void
230 {
231  std::swap(*this, other);
232 }
233 
234 template <class T>
235 void
237 {
238  Handle<T> tmp;
239  swap(tmp);
240 }
241 
242 // ======================================================================
243 // Non-members:
244 
245 // Convert from handle-to-EDProduct to handle-to-T
246 template <class T>
247 void
249 {
250  Handle<T> h{orig};
251  result.swap(h);
252 }
253 
254 // ======================================================================
255 template <typename T>
256 class art::ValidHandle {
257 public:
258  typedef T element_type;
259  class HandleTag {};
260 
261  ValidHandle() = delete;
262  explicit ValidHandle(T const* prod, Provenance prov);
263 
264  ValidHandle(ValidHandle const&) = default;
265  ValidHandle& operator=(ValidHandle const&) & = default;
266 
267  // pointer behaviors
268  operator T const*() const; // conversion to T const*
269  T const& operator*() const;
270  T const* operator->() const; // alias for product()
271  T const* product() const;
272 
273  // inspectors
274  bool isValid() const; // always true
275  bool failedToGet() const; // always false
276  Provenance const* provenance() const;
277  ProductID id() const;
278  std::shared_ptr<art::Exception const> whyFailed() const; // always null
279 
280  // mutators
281  void swap(ValidHandle<T>& other);
282  // No clear() function, because a ValidHandle may not have an invalid
283  // state, and that is what clear() would obtain.
284 
285 private:
286  T const* prod_;
288 };
289 
290 template <class T>
292  : prod_{prod}, prov_{prov}
293 {
294  if (prod == nullptr)
296  << "Attempt to create ValidHandle with null pointer";
297 }
298 
299 template <class T>
300 inline art::ValidHandle<T>::operator T const*() const
301 {
302  return prod_;
303 }
304 
305 template <class T>
306 inline T const& art::ValidHandle<T>::operator*() const
307 {
308  return *prod_;
309 }
310 
311 template <class T>
312 inline T const* art::ValidHandle<T>::operator->() const
313 {
314  return prod_;
315 }
316 
317 template <class T>
318 inline T const*
320 {
321  return prod_;
322 }
323 
324 template <class T>
325 inline bool
327 {
328  return true;
329 }
330 
331 template <class T>
332 inline bool
334 {
335  return false;
336 }
337 
338 template <class T>
339 inline art::Provenance const*
341 {
342  return &prov_;
343 }
344 
345 template <class T>
346 inline art::ProductID
348 {
349  return prov_.productID();
350 }
351 
352 template <class T>
353 inline std::shared_ptr<art::Exception const>
355 {
356  return std::shared_ptr<art::Exception const>();
357 }
358 
359 template <class T>
360 inline void
362 {
363  std::swap(*this, other);
364 }
365 
366 // ======================================================================
367 // Non-members:
368 
369 template <class T>
371 art::range_of_validity(T const& h)
372 {
373  std::string const& errMsg =
374  "Attempt to retrieve range set from invalid handle.";
375  detail::throw_if_invalid(errMsg, h);
376  return h.provenance()->rangeOfValidity();
377 }
378 
379 template <class T, class U>
381 art::same_ranges(T const& a, U const& b)
382 {
383  std::string const& errMsg =
384  "Attempt to compare range sets where one or both handles are invalid.";
385  detail::throw_if_invalid(errMsg, a, b);
387 }
388 
389 template <class T, class U>
391 art::disjoint_ranges(T const& a, U const& b)
392 {
393  std::string const& errMsg =
394  "Attempt to compare range sets where one or both handles are invalid.";
395  detail::throw_if_invalid(errMsg, a, b);
397 }
398 
399 template <class T, class U>
401 art::overlapping_ranges(T const& a, U const& b)
402 {
403  std::string const& errMsg =
404  "Attempt to compare range sets where one or both handles are invalid.";
405  detail::throw_if_invalid(errMsg, a, b);
407 }
408 
409 #endif /* art_Framework_Principal_Handle_h */
410 
411 // Local Variables:
412 // mode: c++
413 // End:
::xsd::cxx::tree::id< char, ncname > id
Definition: Database.h:165
const XML_Char * name
Definition: expat.h:151
Provenance prov_
Definition: Handle.h:287
std::enable_if_t< detail::is_handle< T >::value, RangeSet const & > range_of_validity(T const &h)
T const * prod_
Definition: Handle.h:127
void throw_if_invalid(std::string const &)
Definition: Handle.h:63
std::shared_ptr< art::Exception const > whyFailed_
Definition: Handle.h:129
vector< vector< double > > clear
void swap(Handle< T > &other)
Definition: Handle.h:229
T const & operator*() const
Definition: Handle.h:306
Float_t tmp
Definition: plot.C:36
bool isValid() const
Definition: Provenance.h:120
T const * product() const
Definition: Handle.h:319
void swap(art::HLTGlobalStatus &lhs, art::HLTGlobalStatus &rhs)
ProductID const & productID() const
Definition: Provenance.h:113
ValidHandle()=delete
bool isValid() const
Definition: Handle.h:189
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:166
const XML_Char int const XML_Char * value
Definition: expat.h:331
ProductID id() const
Definition: Handle.h:347
void swap(Handle< T > &a, Handle< T > &b)
Provenance const * provenance() const
Definition: Handle.h:203
const double a
T const * operator->() const
Definition: Handle.h:312
void convert_handle(GroupQueryResult const &, Handle< T > &)
Definition: Handle.h:248
art::art::TriggerResults element_type
Definition: Handle.h:101
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:340
constexpr Handle()=default
T prod(const std::vector< T > &v)
Definition: prod.hpp:17
Provenance prov_
Definition: Handle.h:128
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
T const * operator->() const
Definition: Handle.h:179
T product(std::vector< T > dims)
T const & operator*() const
Definition: Handle.h:159
T const * prod_
Definition: Handle.h:286
void clear()
Definition: Handle.h:236
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:333
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:354
std::shared_ptr< art::Exception const > whyFailed() const
Definition: Handle.h:219
double T
Definition: Xdiff_gwt.C:5
BranchDescription const & productDescription() const
Definition: Provenance.h:46
Float_t e
Definition: plot.C:35
ProductID id() const
Definition: Handle.h:210
void swap(ValidHandle< T > &other)
Definition: Handle.h:361
bool failedToGet() const
Definition: Handle.h:196
bool isValid() const
Definition: Handle.h:326