cleaner multihash handling

master
Daniel Kolesa 2015-06-18 01:17:01 +01:00
parent e0ce128d13
commit 7cf50febd9
3 changed files with 27 additions and 31 deletions

View File

@ -140,7 +140,8 @@ namespace detail {
typename T, /* value type */
typename H, /* hash func */
typename C, /* equality check */
typename A /* allocator */
typename A, /* allocator */
bool Multihash
> struct Hashtable {
static constexpr octa::Size CHUNKSIZE = 64;
@ -328,7 +329,6 @@ namespace detail {
return B::get_data(c->value);
}
template<bool multi>
octa::Size remove(const K &key) {
if (!p_len) return 0;
octa::Size olen = p_len;
@ -342,7 +342,7 @@ namespace detail {
p_unused = c;
octa::allocator_destroy(get_alloc(), &c->value);
octa::allocator_construct(get_alloc(), &c->value);
if (!multi) return 1;
if (!Multihash) return 1;
} else {
p = &c->next;
}
@ -351,7 +351,6 @@ namespace detail {
return olen - p_len;
}
template<bool multi>
octa::Size count(const K &key) {
if (!p_len) return 0;
octa::Size h = get_hash()(key) & (p_size - 1);
@ -359,7 +358,7 @@ namespace detail {
for (Chain *c = p_data.first()[h]; c; c = c->next)
if (get_eq()(key, B::get_key(c->value))) {
++ret;
if (!multi) break;
if (!Multihash) break;
}
return ret;
}
@ -407,6 +406,14 @@ namespace detail {
rehash_ahead(1);
E elem(octa::forward<Args>(args)...);
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
if (Multihash) {
/* multihash: always insert */
Chain *ch = insert(h);
B::swap_elem(ch->value, elem);
Chain **hch = p_data.first();
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
ch), true);
}
Chain *found = nullptr;
bool ins = true;
for (Chain *c = p_data.first()[h]; c; c = c->next) {
@ -425,18 +432,6 @@ namespace detail {
found), ins);
}
template<typename ...Args>
octa::Pair<Range, bool> emplace_multi(Args &&...args) {
rehash_ahead(1);
E elem(octa::forward<Args>(args)...);
octa::Size h = get_hash()(B::get_key(elem)) & (p_size - 1);
Chain *ch = insert(h);
B::swap_elem(ch->value, elem);
Chain **hch = p_data.first();
return octa::make_pair(Range(hch + h + 1, hch + bucket_count(),
ch), true);
}
bool find(const K &key, octa::Size &h, Chain *&oc) const {
if (!p_size) return false;
h = get_hash()(key) & (p_size - 1);

View File

@ -47,7 +47,8 @@ template<
> struct Map {
private:
using Base = octa::detail::Hashtable<
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>, K, T, H, C, A
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
K, T, H, C, A, false
>;
Base p_table;
@ -197,11 +198,11 @@ public:
}
octa::Size erase(const K &key) {
return p_table.remove<false>(key);
return p_table.remove(key);
}
octa::Size count(const K &key) {
return p_table.count<false>(key);
return p_table.count(key);
}
Range find(const K &key) { return p_table.find(key); }
@ -241,7 +242,7 @@ template<
private:
using Base = octa::detail::Hashtable<
octa::detail::MapBase<K, T, A>, octa::Pair<const K, T>,
K, T, H, C, A
K, T, H, C, A, true
>;
Base p_table;
@ -368,15 +369,15 @@ public:
template<typename ...Args>
octa::Pair<Range, bool> emplace(Args &&...args) {
return p_table.emplace_multi(octa::forward<Args>(args)...);
return p_table.emplace(octa::forward<Args>(args)...);
}
octa::Size erase(const K &key) {
return p_table.remove<true>(key);
return p_table.remove(key);
}
octa::Size count(const K &key) {
return p_table.count<true>(key);
return p_table.count(key);
}
Range find(const K &key) { return p_table.find(key); }

View File

@ -38,7 +38,7 @@ template<
> struct Set {
private:
using Base = octa::detail::Hashtable<
octa::detail::SetBase<T, A>, T, T, T, H, C, A
octa::detail::SetBase<T, A>, T, T, T, H, C, A, false
>;
Base p_table;
@ -165,11 +165,11 @@ public:
}
octa::Size erase(const T &key) {
return p_table.remove<false>(key);
return p_table.remove(key);
}
octa::Size count(const T &key) {
return p_table.count<false>(key);
return p_table.count(key);
}
Range find(const Key &key) { return p_table.find(key); }
@ -208,7 +208,7 @@ template<
> struct Multiset {
private:
using Base = octa::detail::Hashtable<
octa::detail::SetBase<T, A>, T, T, T, H, C, A
octa::detail::SetBase<T, A>, T, T, T, H, C, A, true
>;
Base p_table;
@ -334,15 +334,15 @@ public:
template<typename ...Args>
octa::Pair<Range, bool> emplace(Args &&...args) {
return p_table.emplace_multi(octa::forward<Args>(args)...);
return p_table.emplace(octa::forward<Args>(args)...);
}
octa::Size erase(const T &key) {
return p_table.remove<true>(key);
return p_table.remove(key);
}
octa::Size count(const T &key) {
return p_table.count<true>(key);
return p_table.count(key);
}
Range find(const T &key) { return p_table.find(key); }