1 #ifndef TrackingTools_TrajectoryCleaning_src_OtherHashMaps
2 #define TrackingTools_TrajectoryCleaning_src_OtherHashMaps
9 #include <boost/unordered_map.hpp>
10 #include <boost/range.hpp>
11 #include <boost/type_traits.hpp>
12 #include <boost/mpl/and.hpp>
13 #include <boost/mpl/logical.hpp>
14 #include <boost/mpl/assert.hpp>
15 #include <boost/mpl/if.hpp>
30 template<
typename K,
typename V,
typename Hasher=boost::hash<K>,
typename Equals=std::equal_to<K>,
typename Alloc=std::allocator<V> >
33 BOOST_MPL_ASSERT( (boost::mpl::and_<boost::has_trivial_destructor<K>, boost::has_trivial_destructor<V> > ));
37 typedef typename boost::mpl::if_<typename boost::is_pointer<V>, V, V
const &>
::type value_ref;
43 void clear(
size_t newBucketSize=0) {
44 if (newBucketSize != 0) {
82 template<
typename Item>
141 std::cout <<
"Dumping HASH MULTIMAP" << std::endl;
147 std::cout <<
" ["<<row<<
"] " << *
p << std::endl;
151 for (
typename std::list<KeyItem *>::iterator it =
keyRows_.begin(),
last =
keyRows_.end(); it !=
last; ++it, ++row) {
153 std::cout <<
" Key Row " << row <<
" (of size " << keyRowSize_ <<
")" << std::endl;
155 std::cout <<
" @ " <<
p <<
" [" <<
p->key <<
", @" <<
p->value <<
"], next = " <<
p->next << std::endl;
157 std::cout <<
" ^^^ this was the last valid item." << std::endl;
161 if (lastI == 0)
break;
164 std::cout <<
" Value Items " << std::endl;
167 std::cout <<
" Value Row " << row <<
" (of size " << valueRowSize_ <<
")" << std::endl;
169 std::cout <<
" @ " <<
p <<
" [" <<
p->value <<
"], next = " <<
p->next << std::endl;
171 std::cout <<
" ^^^ this was the last valid item." << std::endl;
175 if (lastI == 0)
break;
177 std::cout <<
" End of dump" << std::endl;
182 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
184 bucketSize_(buckets), bucketCapacity_(bucketSize_),
185 keyRowSize_(keyRowSize),
186 valueRowSize_(valueRowSize),
194 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
197 for (
typename std::list<KeyItem *>::iterator it = keyRows_.begin(),
last = keyRows_.end(); it !=
last; ++it) {
198 keyAlloc_.deallocate(*it, keyRowSize_);
200 for (
typename std::list<ValueItem *>::iterator it = valueRows_.begin(),
last = valueRows_.end(); it !=
last; ++it) {
201 valueAlloc_.deallocate(*it, valueRowSize_);
203 ptrAlloc_.deallocate(buckets_, bucketCapacity_);
206 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
209 if (keyRows_.size() > maxRows_) {
211 typename std::list<KeyItem *>::iterator it = keyRows_.begin(),
last = keyRows_.end();
212 for (std::advance(it, maxRows_); it !=
last; ++it) {
213 keyAlloc_.deallocate(*it, keyRowSize_);
215 keyRows_.resize(maxRows_);
217 if (valueRows_.size() > maxRows_) {
219 typename std::list<ValueItem *>::iterator it = valueRows_.begin(),
last = valueRows_.end();
220 for (std::advance(it, maxRows_); it !=
last; ++it) {
221 valueAlloc_.deallocate(*it, valueRowSize_);
223 valueRows_.resize(maxRows_);
227 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
230 if (nextKeyItem_ == keyEndMarker_) {
232 if (currentKeyRow_ == keyRows_.end()) {
233 keyRows_.push_back(keyAlloc_.allocate(keyRowSize_));
234 currentKeyRow_ = keyRows_.end(); --currentKeyRow_;
236 nextKeyItem_ = *currentKeyRow_;
237 keyEndMarker_ = nextKeyItem_ + keyRowSize_;
239 keyAlloc_.construct(nextKeyItem_,
KeyItem(next, key, 0));
241 return (nextKeyItem_-1);
243 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
246 if (nextValueItem_ == valueEndMarker_) {
248 if (currentValueRow_ == valueRows_.end()) {
249 valueRows_.push_back(valueAlloc_.allocate(valueRowSize_));
250 currentValueRow_ = valueRows_.end(); --currentValueRow_;
252 nextValueItem_ = *currentValueRow_;
253 valueEndMarker_ = nextValueItem_ + valueRowSize_;
255 valueAlloc_.construct(nextValueItem_,
ValueItem(next, value));
257 return (nextValueItem_-1);
260 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
264 size_t hash = hasher_(key);
265 KeyItem * & buck = buckets_[hash % bucketSize_];
268 if (eq_(curr->
key, key)) {
274 buck = push_back_(key, buck);
278 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
286 template<
typename K,
typename V,
typename Hasher,
typename Equals,
typename Alloc>
290 size_t hash = hasher_(key);
291 for (
KeyItem * curr = buckets_[hash % bucketSize_]; curr; curr = curr->
next) {
303 template<
typename K,
typename V>
308 typedef typename std::vector<value_type>::iterator
iterator;
318 for (
typename std::vector<value_type>::iterator it =
data_.begin(), ed =
data_.end(); it != ed; ++it) {
319 if (it->first == k)
return it->second;
322 return data_.back().second;
~SimpleAllocHashMultiMap()
ValueItem * valueEndMarker_
ValueItem * nextValueItem_
item_iterator< ValueItem > value_iterator
std::pair< K, V > value_type
std::list< ValueItem * > valueRows_
KeyItem & find_or_insert_(K const &key)
const_iterator begin() const
KeyItemPtrAllocator ptrAlloc_
const_iterator end() const
const Item::value_type value_type
Alloc::template rebind< KeyItem >::other KeyItemAllocator
bool operator!=(const self_type &other) const
const value_type * pointer
BOOST_MPL_ASSERT((boost::mpl::and_< boost::has_trivial_destructor< K >, boost::has_trivial_destructor< V > >))
::std::forward_iterator_tag iterator_category
const value_type & reference
std::list< ValueItem * >::iterator currentValueRow_
KeyItem * push_back_(K const &key, KeyItem *next)
ValueItem(ValueItem *next1, value_ref val)
void insert(K const &key, value_ref value)
V & operator[](const K &k)
value_iterator values(K const &key)
Container::value_type value_type
boost::mpl::if_< typename boost::is_pointer< V >, V, V const & >::type value_ref
Alloc::template rebind< ValueItem >::other ValueItemAllocator
SimpleAllocHashMultiMap< K, V, Hasher, Equals, Alloc > map_type
std::vector< value_type >::const_iterator const_iterator
ValueItemAllocator valueAlloc_
const value_type & operator()() const
const value_type & operator()() const
std::vector< value_type > data_
std::vector< value_type >::iterator iterator
KeyItemAllocator keyAlloc_
const value_type & operator*() const
item_iterator< Item > self_type
Alloc::template rebind< KeyItem * >::other KeyItemPtrAllocator
bool operator==(const self_type &other) const
void clear(size_t newBucketSize=0)
item_iterator(const Item *it)
std::list< KeyItem * > keyRows_
const value_type * operator->() const
ptrdiff_t difference_type
KeyItem(KeyItem *next1, K const &key1, ValueItem *val1)
SimpleAllocHashMultiMap(size_t buckets, size_t keyRowSize, size_t valueRowSize, size_t maxRows=50)
std::list< KeyItem * >::iterator currentKeyRow_