3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-23 17:15:31 +00:00

fix vector<> to support non-POD types

adjust code to std::move and avoid unnecessary/illegal
This commit is contained in:
Nuno Lopes 2017-10-10 17:24:22 +01:00
parent 4d1acadabb
commit 9b54b4e784
35 changed files with 253 additions and 95 deletions

View file

@ -149,6 +149,13 @@ public:
new (m_buffer + m_pos) T(elem);
m_pos++;
}
void push_back(T && elem) {
if (m_pos >= m_capacity)
expand();
new (m_buffer + m_pos) T(std::move(elem));
m_pos++;
}
void pop_back() {
if (CallDestructors) {

View file

@ -54,7 +54,7 @@ public:
bool is_used() const { return m_state == HT_USED; }
T & get_data() { return m_data; }
const T & get_data() const { return m_data; }
void set_data(const T & d) { m_data = d; m_state = HT_USED; }
void set_data(T && d) { m_data = std::move(d); m_state = HT_USED; }
void set_hash(unsigned h) { m_hash = h; }
void mark_as_deleted() { m_state = HT_DELETED; }
void mark_as_free() { m_state = HT_FREE; }
@ -187,10 +187,42 @@ protected:
}
}
static void move_table(entry * source, unsigned source_capacity, entry * target, unsigned target_capacity) {
SASSERT(target_capacity >= source_capacity);
unsigned target_mask = target_capacity - 1;
entry * source_end = source + source_capacity;
entry * target_end = target + target_capacity;
for (entry * source_curr = source; source_curr != source_end; ++source_curr) {
if (source_curr->is_used()) {
unsigned hash = source_curr->get_hash();
unsigned idx = hash & target_mask;
entry * target_begin = target + idx;
entry * target_curr = target_begin;
for (; target_curr != target_end; ++target_curr) {
SASSERT(!target_curr->is_deleted());
if (target_curr->is_free()) {
*target_curr = std::move(*source_curr);
goto end;
}
}
for (target_curr = target; target_curr != target_begin; ++target_curr) {
SASSERT(!target_curr->is_deleted());
if (target_curr->is_free()) {
*target_curr = std::move(*source_curr);
goto end;
}
}
UNREACHABLE();
end:
;
}
}
}
void expand_table() {
unsigned new_capacity = m_capacity << 1;
entry * new_table = alloc_table(new_capacity);
copy_table(m_table, m_capacity, new_table, new_capacity);
move_table(m_table, m_capacity, new_table, new_capacity);
delete_table();
m_table = new_table;
m_capacity = new_capacity;
@ -202,7 +234,7 @@ protected:
if (memory::is_out_of_memory())
return;
entry * new_table = alloc_table(m_capacity);
copy_table(m_table, m_capacity, new_table, m_capacity);
move_table(m_table, m_capacity, new_table, m_capacity);
delete_table();
m_table = new_table;
m_num_deleted = 0;
@ -321,7 +353,7 @@ public:
#define INSERT_LOOP_BODY() { \
if (curr->is_used()) { \
if (curr->get_hash() == hash && equals(curr->get_data(), e)) { \
curr->set_data(e); \
curr->set_data(std::move(e)); \
return; \
} \
HS_CODE(m_st_collision++;); \
@ -330,7 +362,7 @@ public:
entry * new_entry; \
if (del_entry) { new_entry = del_entry; m_num_deleted--; } \
else { new_entry = curr; } \
new_entry->set_data(e); \
new_entry->set_data(std::move(e)); \
new_entry->set_hash(hash); \
m_size++; \
return; \
@ -342,7 +374,7 @@ public:
} \
} ((void) 0)
void insert(data const & e) {
void insert(data && e) {
if ((m_size + m_num_deleted) << 2 > (m_capacity * 3)) {
// if ((m_size + m_num_deleted) * 2 > (m_capacity)) {
expand_table();
@ -363,6 +395,11 @@ public:
UNREACHABLE();
}
void insert(const data & e) {
data tmp(e);
insert(std::move(tmp));
}
#define INSERT_LOOP_CORE_BODY() { \
if (curr->is_used()) { \
if (curr->get_hash() == hash && equals(curr->get_data(), e)) { \
@ -375,7 +412,7 @@ public:
entry * new_entry; \
if (del_entry) { new_entry = del_entry; m_num_deleted--; } \
else { new_entry = curr; } \
new_entry->set_data(e); \
new_entry->set_data(std::move(e)); \
new_entry->set_hash(hash); \
m_size++; \
et = new_entry; \
@ -393,7 +430,7 @@ public:
Return true if it is a new element, and false otherwise.
Store the entry/slot of the table in et.
*/
bool insert_if_not_there_core(data const & e, entry * & et) {
bool insert_if_not_there_core(data && e, entry * & et) {
if ((m_size + m_num_deleted) << 2 > (m_capacity * 3)) {
// if ((m_size + m_num_deleted) * 2 > (m_capacity)) {
expand_table();
@ -415,6 +452,11 @@ public:
return 0;
}
bool insert_if_not_there_core(const data & e, entry * & et) {
data temp(e);
return insert_if_not_there_core(std::move(temp), et);
}
/**
\brief Insert the element e if it is not in the table.
Return a reference to e or to an object identical to e

View file

@ -31,11 +31,10 @@ class mpq {
public:
mpq(int v):m_num(v), m_den(1) {}
mpq():m_den(1) {}
mpq(mpq && other) noexcept : m_num(std::move(other.m_num)), m_den(std::move(other.m_den)) {}
void swap(mpq & other) { m_num.swap(other.m_num); m_den.swap(other.m_den); }
mpz const & numerator() const { return m_num; }
mpz const & denominator() const { return m_den; }
double get_double() const;
};
inline void swap(mpq & m1, mpq & m2) { m1.swap(m2); }
@ -745,6 +744,12 @@ public:
reset_denominator(a);
}
mpq dup(const mpq & source) {
mpq temp;
set(temp, source);
return temp;
}
void swap(mpz & a, mpz & b) { mpz_manager<SYNCH>::swap(a, b); }
void swap(mpq & a, mpq & b) {

View file

@ -94,6 +94,9 @@ class mpz {
public:
mpz(int v):m_val(v), m_ptr(0) {}
mpz():m_val(0), m_ptr(0) {}
mpz(mpz && other) noexcept : m_val(other.m_val), m_ptr(0) {
std::swap(m_val, other.m_val);
}
void swap(mpz & other) {
std::swap(m_val, other.m_val);
std::swap(m_ptr, other.m_ptr);
@ -668,6 +671,12 @@ public:
}
}
void set(mpz & target, mpz && source) {
del(target);
target.m_val = source.m_val;
std::swap(target.m_ptr, source.m_ptr);
}
void set(mpz & a, int val) {
del(a);
a.m_val = val;
@ -700,6 +709,12 @@ public:
void set(mpz & target, unsigned sz, digit_t const * digits);
mpz dup(const mpz & source) {
mpz temp;
set(temp, source);
return temp;
}
void reset(mpz & a) {
del(a);
a.m_val = 0;

View file

@ -69,6 +69,10 @@ public:
m_key(k),
m_value(v) {
}
key_data(Key * k, Value && v) :
m_key(k),
m_value(std::move(v)) {
}
Value const & get_value() const { return m_value; }
Key & get_key () const { return *m_key; }
unsigned hash() const { return m_key->hash(); }
@ -86,7 +90,7 @@ public:
bool is_used() const { return m_data.m_key != reinterpret_cast<Key *>(0) && m_data.m_key != reinterpret_cast<Key *>(1); }
key_data const & get_data() const { return m_data; }
key_data & get_data() { return m_data; }
void set_data(key_data const & d) { m_data = d; }
void set_data(key_data && d) { m_data = std::move(d); }
void set_hash(unsigned h) { SASSERT(h == m_data.hash()); }
void mark_as_deleted() { m_data.m_key = reinterpret_cast<Key *>(1); }
void mark_as_free() { m_data.m_key = 0; }
@ -137,6 +141,10 @@ public:
void insert(Key * const k, Value const & v) {
m_table.insert(key_data(k, v));
}
void insert(Key * const k, Value && v) {
m_table.insert(key_data(k, std::move(v)));
}
key_data const & insert_if_not_there(Key * k, Value const & v) {
return m_table.insert_if_not_there(key_data(k, v));

View file

@ -63,7 +63,7 @@ public:
void resize(unsigned sz) {
if (sz < m_nodes.size())
dec_range_ref(m_nodes.begin() + sz, m_nodes.end());
m_nodes.resize(sz, 0);
m_nodes.resize(sz);
}
void resize(unsigned sz, T * d) {
@ -80,7 +80,7 @@ public:
void reserve(unsigned sz) {
if (sz <= m_nodes.size())
return;
m_nodes.resize(sz, 0);
m_nodes.resize(sz);
}
void shrink(unsigned sz) {

View file

@ -63,8 +63,7 @@ public:
unsigned old_sz = this->size();
if (sz <= old_sz)
shrink(sz);
typename Manager::numeral zero(0);
svector<typename Manager::numeral>::resize(sz, zero);
svector<typename Manager::numeral>::resize(sz, 0);
}
};

View file

@ -322,7 +322,7 @@ bool compare_arrays(const T * array1, const T * array2, unsigned size) {
template<typename T>
void force_ptr_array_size(T & v, unsigned sz) {
if (sz > v.size()) {
v.resize(sz, 0);
v.resize(sz);
}
}

View file

@ -26,6 +26,7 @@ Revision History:
#include "util/debug.h"
#include<algorithm>
#include<type_traits>
#include<memory.h>
#include "util/memory_manager.h"
#include "util/hash.h"
@ -74,9 +75,24 @@ class vector {
if (new_capacity <= old_capacity || new_capacity_T <= old_capacity_T) {
throw default_exception("Overflow encountered when expanding vector");
}
SZ *mem = (SZ*)memory::reallocate(reinterpret_cast<SZ*>(m_data)-2, new_capacity_T);
SZ *mem, *old_mem = reinterpret_cast<SZ*>(m_data) - 2;
if (std::is_trivially_copyable<T>::value) {
mem = (SZ*)memory::reallocate(old_mem, new_capacity_T);
} else {
mem = (SZ*)memory::allocate(new_capacity_T);
}
auto old_data = m_data;
auto old_size = size();
*mem = new_capacity;
m_data = reinterpret_cast<T *>(mem + 2);
if (!std::is_trivially_copyable<T>::value) {
static_assert(std::is_move_constructible<T>::value, "");
int i = 0;
for (auto I = old_data; I != old_data + old_size; ++I) {
new (&m_data[i++]) T(std::move(*I));
}
memory::deallocate(old_mem);
}
}
}
@ -148,6 +164,10 @@ public:
SASSERT(size() == source.size());
}
vector(vector&& other) noexcept : m_data(0) {
std::swap(m_data, other.m_data);
}
vector(SZ s, T const * data):
m_data(0) {
for (SZ i = 0; i < s; i++) {
@ -179,6 +199,16 @@ public:
return *this;
}
vector & operator=(vector && source) {
if (this == &source) {
return *this;
}
destroy();
m_data = 0;
std::swap(m_data, source.m_data);
return *this;
}
void reset() {
if (m_data) {
if (CallDestructors) {
@ -292,6 +322,11 @@ public:
m_data[idx] = val;
}
void set(SZ idx, T && val) {
SASSERT(idx < size());
m_data[idx] = std::move(val);
}
T & back() {
SASSERT(!empty());
return operator[](size() - 1);
@ -318,6 +353,14 @@ public:
reinterpret_cast<SZ *>(m_data)[SIZE_IDX]++;
}
void push_back(T && elem) {
if (m_data == 0 || reinterpret_cast<SZ *>(m_data)[SIZE_IDX] == reinterpret_cast<SZ *>(m_data)[CAPACITY_IDX]) {
expand_vector();
}
new (m_data + reinterpret_cast<SZ *>(m_data)[SIZE_IDX]) T(std::move(elem));
reinterpret_cast<SZ *>(m_data)[SIZE_IDX]++;
}
void insert(T const & elem) {
push_back(elem);
}
@ -357,7 +400,8 @@ public:
}
}
void resize(SZ s, T const & elem=T()) {
template<typename Args>
void resize(SZ s, Args args...) {
SZ sz = size();
if (s <= sz) { shrink(s); return; }
while (s > capacity()) {
@ -367,8 +411,23 @@ public:
reinterpret_cast<SZ *>(m_data)[SIZE_IDX] = s;
iterator it = m_data + sz;
iterator end = m_data + s;
for(; it != end; ++it) {
new (it) T(elem);
for (; it != end; ++it) {
new (it) T(std::forward<Args>(args));
}
}
void resize(SZ s) {
SZ sz = size();
if (s <= sz) { shrink(s); return; }
while (s > capacity()) {
expand_vector();
}
SASSERT(m_data != 0);
reinterpret_cast<SZ *>(m_data)[SIZE_IDX] = s;
iterator it = m_data + sz;
iterator end = m_data + s;
for (; it != end; ++it) {
new (it) T();
}
}
@ -439,10 +498,15 @@ public:
return m_data[idx];
}
void reserve(SZ s, T const & d = T()) {
void reserve(SZ s, T const & d) {
if (s > size())
resize(s, d);
}
void reserve(SZ s) {
if (s > size())
resize(s);
}
};
template<typename T>
@ -452,7 +516,12 @@ public:
ptr_vector(unsigned s):vector<T *, false>(s) {}
ptr_vector(unsigned s, T * elem):vector<T *, false>(s, elem) {}
ptr_vector(ptr_vector const & source):vector<T *, false>(source) {}
ptr_vector(ptr_vector && other) noexcept : vector<T*, false>(std::move(other)) {}
ptr_vector(unsigned s, T * const * data):vector<T *, false>(s, const_cast<T**>(data)) {}
ptr_vector & operator=(ptr_vector const & source) {
vector<T *, false>::operator=(source);
return *this;
}
};
template<typename T, typename SZ = unsigned>
@ -462,7 +531,12 @@ public:
svector(SZ s):vector<T, false, SZ>(s) {}
svector(SZ s, T const & elem):vector<T, false, SZ>(s, elem) {}
svector(svector const & source):vector<T, false, SZ>(source) {}
svector(svector && other) noexcept : vector<T, false, SZ>(std::move(other)) {}
svector(SZ s, T const * data):vector<T, false, SZ>(s, data) {}
svector & operator=(svector const & source) {
vector<T, false, SZ>::operator=(source);
return *this;
}
};
typedef svector<int> int_vector;
@ -494,23 +568,4 @@ struct vector_hash : public vector_hash_tpl<Hash, vector<typename Hash::data> >
template<typename Hash>
struct svector_hash : public vector_hash_tpl<Hash, svector<typename Hash::data> > {};
#include <vector>
// Specialize vector<std::string> to be an instance of std::vector instead.
// This will catch any regression of issue #564 and #420.
template <>
class vector<std::string, true, unsigned> : public std::vector<std::string> {
public:
vector(vector<std::string, true, unsigned> const& other): std::vector<std::string>(other) {}
vector(size_t sz, char const* s): std::vector<std::string>(sz, s) {}
vector() {}
void reset() { clear(); }
};
#endif /* VECTOR_H_ */