Fixed inline problem for hollow iterator.

This commit is contained in:
Davi Reis 2012-04-15 01:23:44 -03:00
parent ea1cb4709e
commit c52152bcb4
2 changed files with 48 additions and 35 deletions

View File

@ -30,11 +30,13 @@ struct hollow_iterator_base
typedef self_type& self_reference; typedef self_type& self_reference;
typedef typename iterator::reference reference; typedef typename iterator::reference reference;
typedef typename iterator::pointer pointer; typedef typename iterator::pointer pointer;
hollow_iterator_base() : it_(), empty_() { } inline hollow_iterator_base() : it_(), empty_() { }
hollow_iterator_base(iterator it, is_empty empty) : it_(it), empty_(empty) { inline hollow_iterator_base(iterator it, is_empty empty, bool solid) : it_(it), empty_(empty) {
advance(); if (!solid) advance();
} }
hollow_iterator_base(const self_type& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; } // Same as above, assumes solid==true.
inline hollow_iterator_base(iterator it, is_empty empty) : it_(it), empty_(empty) {}
inline hollow_iterator_base(const self_type& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; }
template <typename const_iterator> template <typename const_iterator>
hollow_iterator_base(const hollow_iterator_base<const_iterator, is_empty>& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; } hollow_iterator_base(const hollow_iterator_base<const_iterator, is_empty>& rhs) { it_ = rhs.it_; empty_ = rhs.empty_; }
@ -58,13 +60,22 @@ struct hollow_iterator_base
} }
}; };
template <typename container_type, typename iterator> auto make_hollow( template <typename container_type, typename iterator>
inline auto make_solid(
container_type* v, const vector<bool>* p, iterator it) -> container_type* v, const vector<bool>* p, iterator it) ->
hollow_iterator_base<iterator, is_empty<const container_type>> { hollow_iterator_base<iterator, is_empty<const container_type>> {
return hollow_iterator_base<iterator, is_empty<const container_type>>( return hollow_iterator_base<iterator, is_empty<const container_type>>(
it, is_empty<const container_type>(v, p)); it, is_empty<const container_type>(v, p));
} }
template <typename container_type, typename iterator>
inline auto make_hollow(
container_type* v, const vector<bool>* p, iterator it) ->
hollow_iterator_base<iterator, is_empty<const container_type>> {
return hollow_iterator_base<iterator, is_empty<const container_type>>(
it, is_empty<const container_type>(v, p), false);
}
} // namespace cxxmph } // namespace cxxmph
#endif // __CXXMPH_HOLLOW_ITERATOR_H__ #endif // __CXXMPH_HOLLOW_ITERATOR_H__

View File

@ -23,6 +23,7 @@
#include "mph_bits.h" #include "mph_bits.h"
#include "mph_index.h" #include "mph_index.h"
#include "hollow_iterator.h"
namespace cxxmph { namespace cxxmph {
@ -46,14 +47,15 @@ class mph_map {
typedef HashFcn hasher; typedef HashFcn hasher;
typedef EqualKey key_equal; typedef EqualKey key_equal;
typedef typename std::vector<value_type>::pointer pointer; typedef typename vector<value_type>::pointer pointer;
typedef typename std::vector<value_type>::reference reference; typedef typename vector<value_type>::reference reference;
typedef typename std::vector<value_type>::const_reference const_reference; typedef typename vector<value_type>::const_reference const_reference;
typedef typename std::vector<value_type>::size_type size_type; typedef typename vector<value_type>::size_type size_type;
typedef typename std::vector<value_type>::difference_type difference_type; typedef typename vector<value_type>::difference_type difference_type;
typedef typename std::vector<value_type>::iterator iterator; typedef is_empty<const vector<value_type>> is_empty_type;
typedef typename std::vector<value_type>::const_iterator const_iterator; typedef hollow_iterator_base<typename vector<value_type>::iterator, is_empty_type> iterator;
typedef hollow_iterator_base<typename vector<value_type>::const_iterator, is_empty_type> const_iterator;
// For making macros simpler. // For making macros simpler.
typedef void void_type; typedef void void_type;
@ -80,7 +82,7 @@ class mph_map {
data_type& operator[](const key_type &k); data_type& operator[](const key_type &k);
const data_type& operator[](const key_type &k) const; const data_type& operator[](const key_type &k) const;
size_type bucket_count() const { return index_.minimal_perfect_hash_size() + slack_.bucket_count(); } size_type bucket_count() const { return index_.perfect_hash_size() + slack_.bucket_count(); }
void rehash(size_type nbuckets /*ignored*/); void rehash(size_type nbuckets /*ignored*/);
protected: // mimicking STL implementation protected: // mimicking STL implementation
@ -101,8 +103,8 @@ class mph_map {
} }
void pack(); void pack();
std::vector<value_type> values_; vector<value_type> values_;
std::vector<bool> present_; vector<bool> present_;
SimpleMPHIndex<Key, typename seeded_hash<HashFcn>::hash_function> index_; SimpleMPHIndex<Key, typename seeded_hash<HashFcn>::hash_function> index_;
// TODO(davi) optimize slack to use hash from index rather than calculate its own // TODO(davi) optimize slack to use hash from index rather than calculate its own
typedef unordered_map<h128, uint32_t, h128::hash32> slack_type; typedef unordered_map<h128, uint32_t, h128::hash32> slack_type;
@ -151,13 +153,13 @@ MPH_MAP_METHOD_DECL(void_type, pack)() {
make_iterator_first(begin()), make_iterator_first(begin()),
make_iterator_first(end()), size_); make_iterator_first(end()), size_);
if (!success) { exit(-1); } if (!success) { exit(-1); }
std::vector<value_type> new_values(index_.minimal_perfect_hash_size()); vector<value_type> new_values(index_.perfect_hash_size());
new_values.reserve(new_values.size() * 2); new_values.reserve(new_values.size() * 2);
std::vector<bool> new_present(index_.minimal_perfect_hash_size(), false); vector<bool> new_present(index_.perfect_hash_size(), false);
new_present.reserve(new_present.size() * 2); new_present.reserve(new_present.size() * 2);
for (iterator it = begin(), it_end = end(); it != it_end; ++it) { for (iterator it = begin(), it_end = end(); it != it_end; ++it) {
size_type id = index_.minimal_perfect_hash(it->first); size_type id = index_.perfect_hash(it->first);
assert(id < index_.minimal_perfect_hash_size()); assert(id < index_.perfect_hash_size());
assert(id < new_values.size()); assert(id < new_values.size());
new_values[id] = *it; new_values[id] = *it;
new_present[id] = true; new_present[id] = true;
@ -168,10 +170,10 @@ MPH_MAP_METHOD_DECL(void_type, pack)() {
slack_type().swap(slack_); slack_type().swap(slack_);
} }
MPH_MAP_METHOD_DECL(iterator, begin)() { return values_.begin(); } MPH_MAP_METHOD_DECL(iterator, begin)() { return make_hollow(&values_, &present_, values_.begin()); }
MPH_MAP_METHOD_DECL(iterator, end)() { return values_.end(); } MPH_MAP_METHOD_DECL(iterator, end)() { return make_solid(&values_, &present_, values_.end()); }
MPH_MAP_METHOD_DECL(const_iterator, begin)() const { return values_.begin(); } MPH_MAP_METHOD_DECL(const_iterator, begin)() const { return make_hollow(&values_, &present_, values_.begin()); }
MPH_MAP_METHOD_DECL(const_iterator, end)() const { return values_.end(); } MPH_MAP_METHOD_DECL(const_iterator, end)() const { return make_solid(&values_, &present_, values_.end()); }
MPH_MAP_METHOD_DECL(bool_type, empty)() const { return size_ == 0; } MPH_MAP_METHOD_DECL(bool_type, empty)() const { return size_ == 0; }
MPH_MAP_METHOD_DECL(size_type, size)() const { return size_; } MPH_MAP_METHOD_DECL(size_type, size)() const { return size_; }
@ -184,7 +186,7 @@ MPH_MAP_METHOD_DECL(void_type, clear)() {
} }
MPH_MAP_METHOD_DECL(void_type, erase)(iterator pos) { MPH_MAP_METHOD_DECL(void_type, erase)(iterator pos) {
present_[pos - begin] = false; present_[pos.it_ - begin().it_] = false;
*pos = value_type(); *pos = value_type();
--size_; --size_;
} }
@ -196,16 +198,16 @@ MPH_MAP_METHOD_DECL(void_type, erase)(const key_type& k) {
MPH_MAP_INLINE_METHOD_DECL(const_iterator, find)(const key_type& k) const { MPH_MAP_INLINE_METHOD_DECL(const_iterator, find)(const key_type& k) const {
auto idx = index(k); auto idx = index(k);
auto it = begin() + idx; typename vector<value_type>::const_iterator vit = values_.begin() + idx;
if (idx == -1 || it->first != k) return end(); if (idx == -1 || vit->first != k) return end();
return it; return make_solid(&values_, &present_, vit);;
} }
MPH_MAP_INLINE_METHOD_DECL(iterator, find)(const key_type& k) { MPH_MAP_INLINE_METHOD_DECL(iterator, find)(const key_type& k) {
auto idx = index(k); auto idx = index(k);
auto it = begin() + idx; typename vector<value_type>::iterator vit = values_.begin() + idx;
if (idx == -1 || it->first != k) return end(); if (idx == -1 || vit->first != k) return end();
return it; return make_solid(&values_, &present_, vit);;
} }
MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const { MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const {
@ -213,10 +215,10 @@ MPH_MAP_INLINE_METHOD_DECL(my_int32_t, index)(const key_type& k) const {
auto sit = slack_.find(hasher128_.hash128(k, 0)); auto sit = slack_.find(hasher128_.hash128(k, 0));
if (sit != slack_.end()) return sit->second; if (sit != slack_.end()) return sit->second;
} }
if (__builtin_expect(index_.minimal_perfect_hash_size(), 1)) { if (__builtin_expect(index_.perfect_hash_size(), 1)) {
auto minimal_perfect_hash = index_.minimal_perfect_hash(k); auto perfect_hash = index_.perfect_hash(k);
if (__builtin_expect(present_[minimal_perfect_hash], true)) { if (__builtin_expect(present_[perfect_hash], true)) {
return minimal_perfect_hash; return perfect_hash;
} }
} }
return -1; return -1;