LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
SummedValue.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_SummedValue_h
2 #define art_Framework_Principal_SummedValue_h
3 
4 // ======================================================================
5 //
6 // SummedValue: Class whose instances own two objects:
7 // - object of type specified as the template argument
8 // - RangeSet corresponding to the object
9 //
10 // The purpose of this auxiliary class is to provide users with a
11 // means of tying an object with its associated range. This can be
12 // important whenever a user needs to assemble (e.g.) product 3 from
13 // products 1 and 2. However, even though products 1 and 2 might have
14 // the same RangeSets overall, due to output-file switching, the
15 // RangeSets as recorded in each input file may be different. In such
16 // a case, product 3 should arguably only be placed on the Run or
17 // SubRun whenever the RangeSets from products 1 and 2 are the same.
18 //
19 // The main function of interest is SummedValue::update(Handle const& h),
20 // which updates the owned object (calling its appropriate aggregation
21 // function) and its corresponding RangeSet.
22 //
23 // The type 'T' need not correspond to the type of the data product.
24 // For example, the following are allowed uses of SummedValue:
25 //
26 // class MyModule : public EDProducer {
27 // SummedValue<POTSummary> pots_;
28 // SummedValue<unsigned> count_;
29 // public:
30 // ...
31 // void produce(Run& r) {
32 // auto const& h = r.getValidHandle<POTSummary>(...);
33 // pots_.update(h);
34 // count_.update(h, h->proton_count()); // Ties 'count_' with RangeSet
35 // from 'h'
36 // }
37 // };
38 //
39 // N.B. It is the responsibility of the user to call 'clear' whenever
40 // the owned object has been fully updated for the Run or SubRun
41 // of interest.
42 // ======================================================================
43 
47 #include "cetlib_except/demangle.h"
48 
49 #include <memory>
50 
51 namespace art {
52 
53  template <typename T>
54  class SummedValue {
55  public:
56  static_assert(
58  "\n\n"
59  "art error: SummedValue<T>'s only support types that can be aggregated.\n"
60  " Please contact artists@fnal.gov.\n");
61 
62  template <typename H>
64 
65  template <typename H>
67  T const& t);
68 
69  void clear();
70 
71  // Default-constructed object is invalid. As soon as it is
72  // updated, it becomes valid. No update can invalidate it.
73  bool isValid() const;
74 
75  T const& value() const;
76  RangeSet const& rangeOfValidity() const;
77 
78  private:
79  template <typename H>
80  void
81  update_impl(H const& h, T const& t)
82  {
83  // Precondition: handle must be valid
84  assert(h.isValid());
85 
86  auto const& newRS = h.provenance()->rangeOfValidity();
87  if (!rangeOfValidity_.is_valid() && newRS.is_valid()) {
88  rangeOfValidity_ = newRS;
89  value_ = t;
90  } else if (art::disjoint_ranges(rangeOfValidity_, newRS)) {
92  rangeOfValidity_.merge(h.provenance()->rangeOfValidity());
93  } else if (art::same_ranges(rangeOfValidity_, newRS)) {
94  // The ranges are the same, so the behavior is a NOP.
95  // However, we will probably never get here because of the
96  // seenIDs set, which prevents from duplicate aggregation.
97  // If the stakeholders decide that products with the same
98  // ranges should be checked for equality, then the seenIDs
99  // set needs to go away, and an extra condition will be
100  // added here.
101  } else if (art::overlapping_ranges(rangeOfValidity_, newRS)) {
103  "SummedValue<T>::update"}
104  << "\nThe following ranges corresponding to the type:\n"
105  << " '" << cet::demangle_symbol(typeid(T).name()) << "'"
106  << "\ncannot be aggregated\n"
107  << rangeOfValidity_ << " and\n"
108  << newRS << "\nPlease contact artists@fnal.gov.\n";
109  }
110  // NOP when both RangeSets are invalid
111  }
112 
113  T value_{};
115  };
116 
117  //===============================================
118  // Implementation
119 
120  template <typename T>
121  template <typename H>
124  {
125  std::string const& errMsg{"Attempt to update " +
126  cet::demangle_symbol(typeid(*this).name()) +
127  " from an invalid handle."};
128  detail::throw_if_invalid(errMsg, h);
129  update_impl(h, *h);
130  }
131 
132  template <typename T>
133  template <typename H>
135  SummedValue<T>::update(H const& h, T const& t)
136  {
137  std::string const& errMsg{"Attempt to update " +
138  cet::demangle_symbol(typeid(*this).name()) +
139  " from an invalid handle.\n"};
140  detail::throw_if_invalid(errMsg, h);
141  update_impl(h, t);
142  }
143 
144  template <typename T>
145  inline void
147  {
149  std::swap(*this, tmp);
150  }
151 
152  template <typename T>
153  inline bool
155  {
156  return rangeOfValidity_.is_valid();
157  }
158 
159  template <typename T>
160  inline T const&
162  {
163  return value_;
164  }
165 
166  template <typename T>
167  RangeSet const&
169  {
170  return rangeOfValidity_;
171  }
172 
173  template <class T, class U>
174  bool
176  {
178  }
179 
180  template <class T, class U>
181  bool
183  {
185  }
186 
187  template <class T, class U>
188  bool
190  {
192  }
193 }
194 
195 #endif /* art_Framework_Principal_SummedValue_h */
196 
197 // Local variables:
198 // mode: c++
199 // End:
RangeSet rangeOfValidity_
Definition: SummedValue.h:114
void throw_if_invalid(std::string const &)
Definition: Handle.h:63
Float_t tmp
Definition: plot.C:37
std::enable_if_t< detail::is_handle< H >::value > update(H const &h)
Definition: SummedValue.h:123
RangeSet & merge(RangeSet const &other)
Definition: RangeSet.cc:134
std::enable_if_t< detail::are_handles< T, U >::value, bool > disjoint_ranges(T const &a, U const &b)
RangeSet const & rangeOfValidity() const
Definition: SummedValue.h:168
void update_impl(H const &h, T const &t)
Definition: SummedValue.h:81
bool is_valid() const
Definition: RangeSet.cc:230
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string value(boost::any const &)
bool isValid() const
Definition: SummedValue.h:154
std::enable_if_t< detail::are_handles< T, U >::value, bool > overlapping_ranges(T const &a, U const &b)
T const & value() const
Definition: SummedValue.h:161
static RangeSet invalid()
Definition: RangeSet.cc:46
std::enable_if_t< detail::are_handles< T, U >::value, bool > same_ranges(T const &a, U const &b)
HLT enums.
static void aggregate(T &, T const &)
Definition: aggregate.h:57