diff --git a/octa/internal/hashtable.h b/octa/internal/hashtable.h index 5f86129..77d66f7 100644 --- a/octa/internal/hashtable.h +++ b/octa/internal/hashtable.h @@ -151,6 +151,7 @@ namespace detail { const C &get_eq() const { return p_data.second().second().second(); } A &get_alloc() { return p_data.second().first().first(); } + const A &get_alloc() const { 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(); } @@ -159,12 +160,73 @@ namespace detail { p_data(nullptr, FAPair(AllocPair(alloc, CoreAllocPair(alloc, alloc)), FuncPair(hf, eqf))), p_maxlf(1.0f) { + if (!size) return; p_data.first() = octa::allocator_allocate(get_cpalloc(), size); memset(p_data.first(), 0, size * sizeof(Chain *)); } + Hashtable(const Hashtable &ht, const A &alloc): p_size(ht.p_size), + p_len(0), p_chunks(nullptr), p_unused(nullptr), + p_data(nullptr, FAPair(AllocPair(alloc, CoreAllocPair(alloc, alloc)), + FuncPair(ht.get_hash(), ht.get_eq()))), + p_maxlf(ht.p_maxlf) { + if (!p_size) return; + p_data.first() = octa::allocator_allocate(get_cpalloc(), p_size); + memset(p_data.first(), 0, p_size * sizeof(Chain *)); + Chain **och = ht.p_data.first(); + for (octa::Size h = 0; h < p_size; ++h) { + Chain *oc = och[h]; + for (; oc; oc = oc->next) { + Chain *nc = insert(h); + octa::allocator_destroy(get_alloc(), &nc->value); + octa::allocator_construct(get_alloc(), &nc->value, oc->value); + } + } + } + + Hashtable(Hashtable &&ht): p_size(ht.p_size), p_len(ht.p_len), + p_chunks(ht.p_chunks), p_unused(ht.p_unused), + p_data(octa::move(ht.p_data)), p_maxlf(ht.p_maxlf) { + ht.p_size = ht.p_len = 0; + ht.p_chunks = nullptr; + ht.p_unused = nullptr; + ht.p_data.first() = nullptr; + } + + Hashtable(Hashtable &&ht, const A &alloc): p_data(nullptr, + FAPair(AllocPair(alloc, CoreAllocPair(alloc, alloc)), + FuncPair(ht.get_hash(), ht.get_eq()))) { + p_size = ht.p_size; + if (alloc == ht.get_alloc()) { + p_len = ht.p_len; + p_chunks = ht.p_chunks; + p_unused = ht.p_unused; + p_data.first() = ht.p_data.first(); + p_maxlf = ht.p_maxlf; + ht.p_size = ht.p_len = 0; + ht.p_chunks = nullptr; + ht.p_unused = nullptr; + ht.p_data.first() = nullptr; + return; + } + p_len = 0; + p_chunks = nullptr; + p_unused = nullptr; + p_data.first() = octa::allocator_allocate(get_cpalloc(), p_size); + memset(p_data.first(), 0, p_size * sizeof(Chain *)); + Chain **och = ht.p_data.first(); + for (octa::Size h = 0; h < p_size; ++h) { + Chain *oc = och[h]; + for (; oc; oc = oc->next) { + Chain *nc = insert(h); + B::swap_elem(oc->value, nc->value); + } + } + } + ~Hashtable() { - octa::allocator_deallocate(get_cpalloc(), p_data.first(), p_size); + if (p_size) octa::allocator_deallocate(get_cpalloc(), + p_data.first(), p_size); delete_chunks(p_chunks); } @@ -304,7 +366,8 @@ namespace detail { } void rehash(octa::Size count) { - count = octa::max(count, octa::Size(p_len / max_load_factor())); + octa::Size fbcount = octa::Size(p_len / max_load_factor()); + if (fbcount > count) count = fbcount; Chain **och = p_data.first(); Chain **nch = octa::allocator_allocate(get_cpalloc(), count); @@ -327,7 +390,8 @@ namespace detail { } } - octa::allocator_deallocate(get_cpalloc(), och, osize); + if (och && osize) octa::allocator_deallocate(get_cpalloc(), + och, osize); delete_chunks(chunks); } diff --git a/octa/map.h b/octa/map.h index ff3af71..007877b 100644 --- a/octa/map.h +++ b/octa/map.h @@ -78,6 +78,14 @@ public: Map(octa::Size size, const A &alloc): Map(size, H(), C(), alloc) {} Map(octa::Size size, const H &hf, const A &alloc): Map(size, hf, C(), alloc) {} + Map(const Map &m): p_table(m.p_table, + octa::allocator_container_copy(m.p_table.get_alloc())) {} + + Map(const Map &m, const A &alloc): p_table(m.p_table, alloc) {} + + Map(Map &&m): p_table(octa::move(m.p_table)) {} + Map(Map &&m, const A &alloc): p_table(octa::move(m.p_table), alloc) {} + template Map(R range, octa::Size size = 1 << 10, const H &hf = H(), const C &eqf = C(), const A &alloc = A(), @@ -123,7 +131,7 @@ public: void clear() { p_table.clear(); } A get_allocator() const { - return p_table.get_challoc(); + return p_table.get_alloc(); } T &at(const K &key) { diff --git a/octa/vector.h b/octa/vector.h index 89231de..5ce6e22 100644 --- a/octa/vector.h +++ b/octa/vector.h @@ -127,9 +127,8 @@ public: v.p_len = v.p_cap = 0; } - Vector(Vector &&v, const A &a) { - if (a != v.a) { - p_buf.second() = a; + Vector(Vector &&v, const A &a): p_buf(nullptr, a) { + if (!(a == v.p_buf.second())) { reserve(v.p_cap); p_len = v.p_len; if (octa::IsPod()) { @@ -144,8 +143,7 @@ public: } return; } - new (&p_buf) VecPair(v.p_buf.first(), - octa::move(v.p_buf.second())); + p_buf.first() = v.p_buf.first(); p_len = v.p_len; p_cap = v.p_cap; v.p_buf.first() = nullptr;