CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
MultiAssociation.cc
Go to the documentation of this file.
1 #include <algorithm>
4 
5 #include <iostream>
6 
8 using edm::ProductID;
9 
10 IndexRangeAssociation::range
11 IndexRangeAssociation::get(const ProductID &id, unsigned int key) const {
12  typedef IndexRangeAssociation::id_offset_vector::const_iterator iter;
13  iter pos = std::lower_bound(id_offsets_.begin(), id_offsets_.end(), id, IDComparator());
14  if ((pos == id_offsets_.end()) || (pos->first != id)) {
15  throw cms::Exception("Bad Key") << "Product ID " << id << " not found in this IndexRangeAssociation\n";
16  }
17  // === Do we want this check ? I would say yes, even if it costs some extra CPU cycles
18  if ((pos + 1 != id_offsets_.end()) && (pos->second + key >= (pos+1)->second)) {
19  throw cms::Exception("Bad Offset") << "Key " << key << " goes beyond bounds "
20  << ((pos+1)->second - pos->second)
21  << " of this key collection within IndexRangeAssociation\n";
22  }
23  // === End check
24  offset_vector::const_iterator offs = ref_offsets_.begin() + pos->second + key;
25  if (offs >= ref_offsets_.end()-1) {
26  throw cms::Exception("Bad Offset") << "Key " << key << " goes beyond bounds " << ref_offsets_.size()-1 << " of this IndexRangeAssociation\n";
27  }
28  return range(*offs,*(offs+1));
29 }
30 
31 bool
33  typedef IndexRangeAssociation::id_offset_vector::const_iterator iter;
34  iter pos = std::lower_bound(id_offsets_.begin(), id_offsets_.end(), id, IDComparator());
35  return (pos != id_offsets_.end()) && (pos->first == id);
36 }
37 
38 void
40  if (isFilling_ || other.isFilling_) throw cms::Exception("Busy") << "Can't swap an IndexRangeAssociation while it's being filled!\n";
41  id_offsets_.swap(other.id_offsets_);
42  ref_offsets_.swap(other.ref_offsets_);
43 }
44 
46  assoc_(assoc), id_(id),
47  start_(assoc.ref_offsets_.empty() ? 0 : assoc.ref_offsets_.size() - 1), // must skip the end marker element
48  end_(start_ + size),
49  lastKey_(-1)
50 {
51  if (assoc_.isFilling_) throw cms::Exception("Unsupported Operation") <<
52  "IndexRangeAssociation::FastFiller: you already have one active filler for this map.\n";
53 
54  // Look if the key is there, or find the right place to insert it
55  typedef IndexRangeAssociation::id_offset_vector::iterator iter;
56  iter pos = std::lower_bound(assoc_.id_offsets_.begin(), assoc_.id_offsets_.end(), id, IndexRangeAssociation::IDComparator());
57 
58  // Check for duplicate ProductID
59  if ((pos != assoc_.id_offsets_.end()) && (pos->first == id)) throw cms::Exception("Duplicated Key") <<
60  "IndexRangeAssociation::FastFiller: there is already an entry for ProductID " << id << " in this map.\n";
61 
62  // Lock the map
63  assoc_.isFilling_ = true;
64 
65  // Insert the key, keeping id_offsets_ sorted
67 
68  int lastEnd = (assoc_.ref_offsets_.empty() ? 0 : assoc_.ref_offsets_.back());
69  assoc_.ref_offsets_.resize(end_ + 1, -1);
70  assoc_.ref_offsets_.back() = lastEnd;
71 }
72 
74  // I have to consolidate, replacing "-1" with the correct end offset.
75  // I can start from the end, as I know that the last item is never -1
76  typedef IndexRangeAssociation::offset_vector::iterator IT;
77  //std::cout << "Fixupping [" << start_ << ", " << end_ << "]" << std::endl;
78  //for(IT i = assoc_.ref_offsets_.begin() + start_; i <= assoc_.ref_offsets_.begin() + end_; ++i) { std::cout << " - " << *i << std::endl; }
79  IT top = assoc_.ref_offsets_.begin() + start_;
80  IT it = assoc_.ref_offsets_.begin() + end_;
81  int offset = *it;
82  for (--it; it >= top; --it) {
83  if (*it == -1) {
84  //std::cout << " > replace *it " << *it << " with offset " << offset << " at " << (it - top) << std::endl;
85  *it = offset; // replace -1 with real end offset
86  } else {
87  //std::cout << " > replace offset " << offset << " with *it " << *it << " at " << (it - top) << std::endl;
88  offset = *it; // take as new end offset for the preceding "-1"s
89  }
90  }
91  assoc_.isFilling_ = false; // unlock
92  //std::cout << "Fixupped [" << start_ << ", " << end_ << "]" << std::endl;
93  //for(IT i = assoc_.ref_offsets_.begin() + start_; i <= assoc_.ref_offsets_.begin() + end_; ++i) { std::cout << " - " << *i << std::endl; }
94 }
95 
96 void
97 IndexRangeAssociation::FastFiller::insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size) {
98  if (id != id_) IndexRangeAssociation::throwUnexpectedProductID(id,id_,"FastFiller::insert");
99  if (int(key) <= lastKey_) throw cms::Exception("Bad Key") <<
100  "IndexRangeAssociation::FastFiller: you must fill this in strict key order\n" <<
101  "\tLast key = " << lastKey_ << ", this key = " << key << "\n";
102  if (key >= end_) throw cms::Exception("Bad Key") <<
103  "IndexRangeAssociation::FastFiller: key index out of bounds for this collection\n" <<
104  "\tKey = " << key << ", bound = " << end_ << "\n";
105  if ((assoc_.ref_offsets_.back() != 0) && (int(startingOffset) != assoc_.ref_offsets_.back()))
106  throw cms::Exception("Bad Offset") <<
107  "IndexRangeAssociation::FastFiller: The start for this key is not the end of the preceding key.\n" <<
108  "\tThis offset = " << startingOffset << ", last key = " << lastKey_ <<
109  ", last end offset = " << assoc_.ref_offsets_.back() << "\n";
110  assoc_.ref_offsets_[start_ + key] = startingOffset;
111  lastKey_ = key;
112  assoc_.ref_offsets_.back() += size;
113 }
114 
115 void
117  throw cms::Exception("Unexpected ProductID") << where <<
118  ": found product id " << found << ", while expecting " << expected << ".\n" <<
119  "Make sure you're not mismatching references from different collections.\n";
120 }
static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where)
FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size)
Make a filler for a collection with a given product id and size.
U second(std::pair< T, U > const &p)
void swap(IndexRangeAssociation &other)
unsigned int size() const
Size of this collection (number of keys)
~FastFiller()
When the FastFiller goes out of scope, it unlocks the map so you can make a new one.
bool contains(ProductID id) const
True if this IndexRangeAssociation has info for this product id.
std::vector< LinkConnSpec >::const_iterator IT
unsigned int offset(bool)
std::pair< unsigned int, unsigned int > range
void insert(const RefKey &r, unsigned int startingOffset, unsigned int size)
Sets the starting offset for this key.
list key
Definition: combine.py:13
std::pair< edm::ProductID, unsigned int > id_off_pair
tuple size
Write out results.
T get(const Candidate &c)
Definition: component.h:55