use allocators for hashtables always

master
Daniel Kolesa 2015-06-16 01:46:34 +01:00
parent 8324f5f9cc
commit 3b65b0cb99
2 changed files with 17 additions and 13 deletions

View File

@ -18,8 +18,8 @@ namespace octa {
namespace detail {
template<typename T>
struct HashChain {
T value;
HashChain<T> *next;
T value;
};
}
@ -132,7 +132,8 @@ namespace detail {
using CPA = octa::AllocatorRebind<A, Chain *>;
using CHA = octa::AllocatorRebind<A, Chunk>;
using AllocPair = octa::detail::CompressedPair<CPA, CHA>;
using CoreAllocPair = octa::detail::CompressedPair<CPA, CHA>;
using AllocPair = octa::detail::CompressedPair<A, CoreAllocPair>;
using FuncPair = octa::detail::CompressedPair<H, C>;
using FAPair = octa::detail::CompressedPair<AllocPair, FuncPair>;
using DataPair = octa::detail::CompressedPair<Chain **, FAPair>;
@ -149,12 +150,14 @@ namespace detail {
const H &get_hash() const { return p_data.second().second().first(); }
const C &get_eq() const { return p_data.second().second().second(); }
CPA &get_cpalloc() { return p_data.second().first().first(); }
CHA &get_challoc() { return p_data.second().first().second(); }
A &get_alloc() { return p_data.second().first().first(); }
CPA &get_cpalloc() { return p_data.second().first().second().first(); }
CHA &get_challoc() { return p_data.second().first().second().second(); }
Hashtable(octa::Size size, const H &hf, const C &eqf, const A &alloc):
p_size(size), p_len(0), p_chunks(nullptr), p_unused(nullptr),
p_data(nullptr, FAPair(AllocPair(alloc, alloc), FuncPair(hf, eqf))),
p_data(nullptr, FAPair(AllocPair(alloc, CoreAllocPair(alloc, alloc)),
FuncPair(hf, eqf))),
p_maxlf(1.0f) {
p_data.first() = octa::allocator_allocate(get_cpalloc(), size);
memset(p_data.first(), 0, size * sizeof(Chain *));
@ -191,7 +194,7 @@ namespace detail {
template<typename U>
T &insert(octa::Size h, U &&key) {
Chain *c = insert(h);
B::set_key(c->value, octa::forward<U>(key));
B::set_key(c->value, octa::forward<U>(key), get_alloc());
return B::get_data(c->value);
}
@ -203,8 +206,8 @@ namespace detail {
while (c) {
if (get_eq()(key, B::get_key(c->value))) {
*p = c->next;
c->value.~E();
new (&c->value) E;
octa::allocator_destroy(get_alloc(), &c->value);
octa::allocator_construct(get_alloc(), &c->value);
c->next = p_unused;
p_unused = c;
--p_len;

View File

@ -17,7 +17,7 @@
namespace octa {
namespace detail {
template<typename K, typename T> struct MapBase {
template<typename K, typename T, typename A> struct MapBase {
using Element = octa::Pair<const K, T>;
static inline const K &get_key(Element &e) {
@ -27,9 +27,10 @@ namespace detail {
return e.second;
}
template<typename U>
static inline void set_key(Element &e, U &&key) {
e.first.~K();
new ((K *)&e.first) K(octa::forward<U>(key));
static inline void set_key(Element &e, U &&key, A &alloc) {
octa::allocator_destroy(alloc, &e);
octa::allocator_construct(alloc, &e, octa::forward<U>(key),
octa::move(T()));
}
static inline void swap_elem(Element &a, Element &b) {
octa::swap(*((K *)&a.first), *((K *)&b.first));
@ -46,7 +47,7 @@ template<
> struct Map {
private:
using Base = octa::detail::Hashtable<
octa::detail::MapBase<K, T>, 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
>;
Base p_table;
public: