diff --git a/ChangeLog b/ChangeLog index 7e34a077b..0ef1b8d0e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2011-04-09 Alexandre Duret-Lutz + + DVE2: Use mspool for compressed states. + + * iface/dve2/dve2.cc: Adjust to use the new mspool allocator, + and get rid of the std::vector used to store compressed states. + * src/misc/intvcomp.hh: Add an "int* -> int*" interface + in addition to the "int* -> vector*" interface. + * src/tgbatest/intvcomp.cc: Test the two interfaces. + 2011-04-09 Alexandre Duret-Lutz Add a multiple-size memory pool implementation. diff --git a/iface/dve2/dve2.cc b/iface/dve2/dve2.cc index 65607c60a..3d5c86dc3 100644 --- a/iface/dve2/dve2.cc +++ b/iface/dve2/dve2.cc @@ -29,6 +29,7 @@ #include "dve2.hh" #include "misc/hashfunc.hh" #include "misc/fixpool.hh" +#include "misc/mspool.hh" #include "misc/intvcomp.hh" @@ -130,17 +131,16 @@ namespace spot struct dve2_compressed_state: public state { - dve2_compressed_state(fixed_size_pool* p) - : count(1), pool(p) + dve2_compressed_state(int s, multiple_size_pool* p) + : size(s), count(1), pool(p) { } void compute_hash() { hash_value = 0; - std::vector::const_iterator i; - for (i = data->begin(); i != data->end(); ++i) - hash_value = wang32_hash(hash_value ^ *i); + for (int i = 0; i < size; ++i) + hash_value = wang32_hash(hash_value ^ vars[i]); } dve2_compressed_state* clone() const @@ -153,8 +153,7 @@ namespace spot { if (--count) return; - delete data; - pool->deallocate(this); + pool->deallocate(this, sizeof(*this) + size * sizeof(int)); } size_t hash() const @@ -174,20 +173,12 @@ namespace spot if (hash_value > o->hash_value) return 1; - if (data->size() < o->data->size()) + if (size < o->size) return -1; - if (data->size() > o->data->size()) + if (size > o->size) return 1; - std::pair::const_iterator, - std::vector::const_iterator> r; - r = std::mismatch(data->begin(), data->end(), o->data->begin()); - if (r.first == data->end()) - return 0; - if (*(r.first) < *(r.second)) - return -1; - else - return 1; + return memcmp(vars, o->vars, size * sizeof(*vars)); } private: @@ -197,10 +188,11 @@ namespace spot } public: + int size; mutable unsigned count; size_t hash_value; - fixed_size_pool* pool; - const std::vector* data; + multiple_size_pool* pool; + int vars[0]; }; //////////////////////////////////////////////////////////////////////// @@ -211,7 +203,8 @@ namespace spot typedef std::vector transitions_t; // FIXME: Vector->List transitions_t transitions; int state_size; - fixed_size_pool* pool; + void* pool; + int* compressed; ~callback_context() { @@ -224,8 +217,9 @@ namespace spot void transition_callback(void* arg, transition_info_t*, int *dst) { callback_context* ctx = static_cast(arg); + fixed_size_pool* p = static_cast(ctx->pool); dve2_state* out = - new(ctx->pool->allocate()) dve2_state(ctx->state_size, ctx->pool); + new(p->allocate()) dve2_state(ctx->state_size, p); memcpy(out->vars, dst, ctx->state_size * sizeof(int)); out->compute_hash(); ctx->transitions.push_back(out); @@ -234,11 +228,15 @@ namespace spot void transition_callback_compress(void* arg, transition_info_t*, int *dst) { callback_context* ctx = static_cast(arg); + multiple_size_pool* p = static_cast(ctx->pool); - dve2_compressed_state* out = - new(ctx->pool->allocate()) dve2_compressed_state(ctx->pool); - out->data = int_array_compress(dst, ctx->state_size); - // std::cerr << "dest " << out->data << std::endl; + size_t csize = ctx->state_size * 2; + int_array_array_compress(dst, ctx->state_size, ctx->compressed, csize); + + void* mem = p->allocate(sizeof(dve2_compressed_state) + + sizeof(int) * csize); + dve2_compressed_state* out = new(mem) dve2_compressed_state(csize, p); + memcpy(out->vars, ctx->compressed, csize * sizeof(int)); out->compute_hash(); ctx->transitions.push_back(out); } @@ -600,8 +598,8 @@ namespace spot state_size_(d_->get_state_variable_count()), dict_(dict), ps_(ps), compress_(compress), - uncompressed_(compress ? new int[state_size_] : - 0), + uncompressed_(compress ? new int[state_size_] : 0), + compressed_(compress ? new int[state_size_ * 2] : 0), statepool_(compress ? sizeof(dve2_compressed_state) : (sizeof(dve2_state) + state_size_ * sizeof(int))), state_condition_last_state_(0), state_condition_last_cc_(0) @@ -645,7 +643,10 @@ namespace spot { delete[] vname_; if (compress_) - delete[] uncompressed_; + { + delete[] uncompressed_; + delete[] compressed_; + } lt_dlclose(d_->handle); dict_->unregister_all_my_variables(d_); @@ -662,19 +663,26 @@ namespace spot virtual state* get_init_state() const { - fixed_size_pool* p = const_cast(&statepool_); if (compress_) { - dve2_compressed_state* res = - new(p->allocate()) dve2_compressed_state(p); d_->get_initial_state(uncompressed_); - res->data = int_array_compress(uncompressed_, state_size_); - // std::cerr << "init " << res->data << std::endl; + size_t csize = state_size_ * 2; + int_array_array_compress(uncompressed_, state_size_, + compressed_, csize); + + multiple_size_pool* p = + const_cast(&compstatepool_); + void* mem = p->allocate(sizeof(dve2_compressed_state) + + sizeof(int) * csize); + dve2_compressed_state* res = new(mem) + dve2_compressed_state(csize, p); + memcpy(res->vars, compressed_, csize * sizeof(int)); res->compute_hash(); return res; } else { + fixed_size_pool* p = const_cast(&statepool_); dve2_state* res = new(p->allocate()) dve2_state(state_size_, p); d_->get_initial_state(res->vars); res->compute_hash(); @@ -723,6 +731,24 @@ namespace spot return res; } + callback_context* build_cc(const int* vars, int& t) const + { + callback_context* cc = new callback_context; + cc->state_size = state_size_; + cc->pool = + const_cast(compress_ + ? static_cast(&compstatepool_) + : static_cast(&statepool_)); + cc->compressed = compressed_; + t = d_->get_successors(0, const_cast(vars), + compress_ + ? transition_callback_compress + : transition_callback, + cc); + assert((unsigned)t == cc->transitions.size()); + return cc; + } + bdd compute_state_condition(const state* st) const { @@ -740,17 +766,8 @@ namespace spot const int* vars = get_vars(st); bdd res = compute_state_condition_aux(vars); - - callback_context* cc = new callback_context; - cc->state_size = state_size_; - cc->pool = const_cast(&statepool_); - int t = d_->get_successors(0, const_cast(vars), - compress_ - ? transition_callback_compress - : transition_callback, - cc); - assert((unsigned)t == cc->transitions.size()); - state_condition_last_cc_ = cc; + int t; + callback_context* cc = build_cc(vars, t); if (t) { @@ -765,6 +782,7 @@ namespace spot cc->transitions.push_back(st->clone()); } + state_condition_last_cc_ = cc; state_condition_last_cond_ = res; state_condition_last_state_ = st->clone(); @@ -781,7 +799,8 @@ namespace spot down_cast(st); assert(s); - int_array_decompress(s->data, uncompressed_, state_size_); + int_array_array_decompress(s->vars, s->size, + uncompressed_, state_size_); vars = uncompressed_; } else @@ -810,17 +829,8 @@ namespace spot } else { - const int* vars = get_vars(local_state); - - cc = new callback_context; - cc->state_size = state_size_; - cc->pool = const_cast(&statepool_); - int t = d_->get_successors(0, const_cast(vars), - compress_ - ? transition_callback_compress - : transition_callback, - cc); - assert((unsigned)t == cc->transitions.size()); + int t; + cc = build_cc(get_vars(local_state), t); // Add a self-loop to dead-states if we care about these. if (t == 0 && scond != bddfalse) @@ -875,7 +885,9 @@ namespace spot bdd dead_prop; bool compress_; int* uncompressed_; + int* compressed_; fixed_size_pool statepool_; + multiple_size_pool compstatepool_; // This cache is used to speedup repeated calls to state_condition() // and get_succ(). diff --git a/src/misc/intvcomp.hh b/src/misc/intvcomp.hh index e00f4b666..1b18dd42e 100644 --- a/src/misc/intvcomp.hh +++ b/src/misc/intvcomp.hh @@ -183,11 +183,11 @@ namespace spot unsigned int bits_left_; }; - class int_array_compression: - public stream_compression_base + class int_array_vector_compression: + public stream_compression_base { public: - int_array_compression(int* array, size_t n) + int_array_vector_compression(const int* array, size_t n) : array_(array), n_(n), pos_(0), result_(new std::vector) { } @@ -226,20 +226,78 @@ namespace spot } protected: - int* array_; + const int* array_; size_t n_; size_t pos_; std::vector* result_; }; - const std::vector* - int_array_compress(int* array, unsigned int n) + class int_array_array_compression: + public stream_compression_base { - int_array_compression c(array, n); + public: + int_array_array_compression(const int* array, size_t n, + int* dest, size_t& dest_n) + : array_(array), n_(n), pos_(0), + result_size_(dest_n), result_(dest), result_end_(dest + dest_n) + { + result_size_ = 0; // this resets dest_n. + } + + void push_data(unsigned int i) + { + assert(result_ < result_end_); + ++result_size_; + *result_++ = static_cast(i); + } + + bool have_data() const + { + return pos_ < n_; + } + + unsigned int next_data() + { + return static_cast(array_[pos_++]); + } + + bool skip_if(unsigned int val) + { + if (!have_data()) + return false; + + if (static_cast(array_[pos_]) != val) + return false; + + ++pos_; + return true; + } + + protected: + const int* array_; + size_t n_; + size_t pos_; + size_t& result_size_; + int* result_; + int* result_end_; + }; + + const std::vector* + int_array_vector_compress(const int* array, size_t n) + { + int_array_vector_compression c(array, n); c.run(); return c.result(); } + void + int_array_array_compress(const int* array, size_t n, + int* dest, size_t& dest_size) + { + int_array_array_compression c(array, n, dest, dest_size); + c.run(); + } + ////////////////////////////////////////////////////////////////////// template @@ -394,12 +452,13 @@ namespace spot unsigned int buffer_mask_; }; - class int_array_decompression: - public stream_decompression_base + class int_vector_array_decompression: + public stream_decompression_base { public: - int_array_decompression(const std::vector* array, int* res, - size_t size) + int_vector_array_decompression(const std::vector* array, + int* res, + size_t size) : prev_(0), array_(array), n_(array->size()), pos_(0), result_(res), size_(size) { @@ -443,11 +502,70 @@ namespace spot size_t size_; }; - void - int_array_decompress(const std::vector* array, int* res, - size_t size) + class int_array_array_decompression: + public stream_decompression_base { - int_array_decompression c(array, res, size); + public: + int_array_array_decompression(const int* array, + size_t array_size, + int* res, + size_t size) + : prev_(0), array_(array), n_(array_size), pos_(0), result_(res), + size_(size) + { + } + + bool complete() const + { + return size_ == 0; + } + + void push_data(int i) + { + prev_ = i; + *result_++ = i; + --size_; + } + + void repeat(unsigned int i) + { + size_ -= i; + while (i--) + *result_++ = prev_; + } + + bool have_comp_data() const + { + return pos_ < n_; + } + + unsigned int next_comp_data() + { + return array_[pos_++]; + } + + protected: + int prev_; + const int* array_; + size_t n_; + size_t pos_; + int* result_; + size_t size_; + }; + + void + int_vector_array_decompress(const std::vector* array, int* res, + size_t size) + { + int_vector_array_decompression c(array, res, size); + c.run(); + } + + void + int_array_array_decompress(const int* array, size_t array_size, + int* res, size_t size) + { + int_array_array_decompression c(array, array_size, res, size); c.run(); } diff --git a/src/tgbatest/intvcomp.cc b/src/tgbatest/intvcomp.cc index 85c79f0ac..8c5cd6f1b 100644 --- a/src/tgbatest/intvcomp.cc +++ b/src/tgbatest/intvcomp.cc @@ -22,31 +22,32 @@ #include "misc/intvcomp.hh" #include -int check(int* comp, int size, unsigned expected = 0) +int check_av(int* data, int size, unsigned expected = 0) { - const std::vector* v = spot::int_array_compress(comp, size); + const std::vector* v = + spot::int_array_vector_compress(data, size); - std::cout << "C[" << v->size() << "] "; + std::cout << "VC[" << v->size() << "] "; for (size_t i = 0; i < v->size(); ++i) std::cout << (*v)[i] << " "; std::cout << std::endl; int* decomp = new int[size]; - spot::int_array_decompress(v, decomp, size); + spot::int_vector_array_decompress(v, decomp, size); - std::cout << "D[" << size << "] "; + std::cout << "VD[" << size << "] "; for (int i = 0; i < size; ++i) std::cout << decomp[i] << " "; std::cout << std::endl; - int res = memcmp(comp, decomp, size * sizeof(int)); + int res = memcmp(data, decomp, size * sizeof(int)); if (res) { std::cout << "*** cmp error *** " << res << std::endl; - std::cout << "E[" << size << "] "; + std::cout << "VE[" << size << "] "; for (int i = 0; i < size; ++i) - std::cout << comp[i] << " "; + std::cout << data[i] << " "; std::cout << std::endl; } @@ -65,6 +66,56 @@ int check(int* comp, int size, unsigned expected = 0) return !!res; } +int check_aa(int* data, int size, unsigned expected = 0) +{ + int* comp = new int[size *2]; + size_t csize = size * 2; + spot::int_array_array_compress(data, size, comp, csize); + + std::cout << "AC[" << csize << "] "; + for (size_t i = 0; i < csize; ++i) + std::cout << comp[i] << " "; + std::cout << std::endl; + + int* decomp = new int[size]; + spot::int_array_array_decompress(comp, csize, decomp, size); + + std::cout << "AD[" << size << "] "; + for (int i = 0; i < size; ++i) + std::cout << decomp[i] << " "; + std::cout << std::endl; + + int res = memcmp(data, decomp, size * sizeof(int)); + + if (res) + { + std::cout << "*** cmp error *** " << res << std::endl; + std::cout << "AE[" << size << "] "; + for (int i = 0; i < size; ++i) + std::cout << data[i] << " "; + std::cout << std::endl; + } + + if (expected && (csize * sizeof(int) != expected)) + { + std::cout << "*** size error *** (expected " + << expected << " bytes, got " << csize * sizeof(int) + << " bytes)" << std::endl; + res = 1; + } + + std::cout << std::endl; + + delete[] comp; + delete[] decomp; + return !!res; +} + +int check(int* comp, int size, unsigned expected = 0) +{ + return check_av(comp, size, expected) + check_aa(comp, size, expected); +} + int main() { int errors = 0;