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

View File

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

View File

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