00001
00006 #ifndef _DIVINE_EXPLICIT_STORAGE_HH_
00007 #define _DIVINE_EXPLICIT_STORAGE_HH_
00008
00009
00010 #ifndef DOXYGEN_PROCESSING
00011 #include "system/state.hh"
00012 #include "storage/compressor.hh"
00013 #include "common/error.hh"
00014 #include "common/hash_function.hh"
00015
00016 namespace divine {
00017 #endif //DOXYGEN_PROCESSING
00018
00019 #define EXPLICIT_STORAGE_ERR_TYPE 11
00020 #define EXPLICIT_STORAGE_HASH_SEED 0xBA9A9ABA
00021
00022
00024
00037 class state_ref_t{
00038 public:
00039 state_ref_t();
00040 size_t hres;
00041 size_t id;
00042 std::string to_string();
00043
00045 void invalidate();
00046
00048 bool is_valid();
00049 };
00050
00052 inline std::ostream & operator<<(std::ostream & ostr, const state_ref_t & ref)
00053 { ostr << '[' << ref.hres << ", " << ref.id << ']'; return ostr; }
00054
00056 inline static bool operator==(const state_ref_t & r1, const state_ref_t & r2)
00057 {
00058 if (memcmp(&r1,&r2,sizeof(state_ref_t))==0) return true;
00059 else return false;
00060 }
00061
00063 inline static bool operator!=(const state_ref_t & r1, const state_ref_t & r2)
00064 {
00065 if (memcmp(&r1,&r2,sizeof(state_ref_t))!=0) return true;
00066 else return false;
00067 }
00068
00070 inline static bool operator<(const state_ref_t & r1, const state_ref_t & r2)
00071 {
00072 if (memcmp(&r1,&r2,sizeof(state_ref_t))<0) return true;
00073 else return false;
00074 }
00075
00077 inline static bool operator<=(const state_ref_t & r1, const state_ref_t & r2)
00078 {
00079 if (memcmp(&r1,&r2,sizeof(state_ref_t))<=0) return true;
00080 else return false;
00081 }
00082
00084 inline static bool operator>(const state_ref_t & r1, const state_ref_t & r2)
00085 {
00086 if (memcmp(&r1,&r2,sizeof(state_ref_t))>0) return true;
00087 else return false;
00088 }
00089
00091 inline static bool operator>=(const state_ref_t & r1, const state_ref_t & r2)
00092 {
00093 if (memcmp(&r1,&r2,sizeof(state_ref_t))>=0) return true;
00094 else return false;
00095 }
00096
00097
00098
00100 class explicit_storage_t {
00101 public:
00102
00104 explicit_storage_t(divine::error_vector_t& = gerr);
00105
00110 void init();
00111
00114 void insert(state_t);
00115
00119 void insert(state_t,state_ref_t&);
00120
00128 bool is_stored_if_not_insert(state_t,state_ref_t&);
00129
00131 bool is_stored(state_t);
00132
00135 bool is_stored(state_t,state_ref_t&);
00136
00139 bool delete_by_ref(state_ref_t);
00140
00145 void delete_all_states(bool leave_collision_lists = false);
00146
00149 state_t reconstruct(state_ref_t);
00150
00154 size_t get_mem_used();
00155
00159 size_t get_mem_max_used();
00160
00162 size_t get_states_stored();
00163
00165 size_t get_states_max_stored();
00166
00168 size_t get_coltables();
00169
00171 size_t get_max_coltable();
00172
00175 size_t get_ht_occupancy();
00176
00180 void set_compression_method(size_t);
00181
00185 void set_ht_size(size_t);
00186
00188 void set_hash_function(hash_functions_t);
00189
00192 void set_col_init_size(size_t);
00193
00197 void set_col_resize(size_t);
00198
00202 bool set_mem_limit(size_t);
00203
00206 void set_appendix_size(size_t);
00207
00210 template <class appendix_t>
00211 void set_appendix(appendix_t)
00212 {
00213 if (initialized)
00214 {
00215 errvec<<"storage: you cannot call set function after init"
00216 <<thr(EXPLICIT_STORAGE_ERR_TYPE);
00217 }
00218 appendix_size = sizeof(appendix_t);
00219 }
00220
00222 void* app_by_ref(state_ref_t refer);
00223
00225 template <class appendix_t>
00226 bool get_app_by_ref(state_ref_t refer, appendix_t& result)
00227 {
00228
00229 if (appendix_size==0)
00230 {
00231 errvec <<"No appendix set. Cannot use get_app_by_ref()"
00232 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00233 return false;
00234 }
00235
00236 if (!(storage.ht_base[refer.hres].col_table))
00237 {
00238 errvec <<"Invalid reference used in get_app_by_ref()."
00239 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00240 return false;
00241 }
00242 else
00243 {
00244 if (!(storage.ht_base[refer.hres].col_table[refer.id].ptr))
00245 {
00246 errvec <<"Invalid reference used in get_app_by_ref()."
00247 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00248 return false;
00249 }
00250 else
00251 {
00252 memcpy(&result,
00253 storage.ht_base[refer.hres].col_table[refer.id].ptr +
00254 storage.ht_base[refer.hres].col_table[refer.id].size,
00255 sizeof(appendix_t));
00256 }
00257 }
00258
00259 return true;
00260 }
00261
00263 template <class appendix_t>
00264 bool set_app_by_ref(state_ref_t refer, appendix_t appen)
00265 {
00266
00267 if (appendix_size==0)
00268 {
00269 errvec <<"No appendix set. Cannot use set_app_by_ref()"
00270 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00271 return false;
00272 }
00273
00274 if (!(storage.ht_base[refer.hres].col_table))
00275 {
00276 errvec <<"Invalid reference used in set_app_by_ref()."
00277 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00278 return false;
00279 }
00280 else
00281 {
00282 if (!(storage.ht_base[refer.hres].col_table[refer.id].ptr))
00283 {
00284 errvec <<"Invalid reference used in set_app_by_ref()."
00285 <<psh(EXPLICIT_STORAGE_ERR_TYPE);
00286 return false;
00287 }
00288 else
00289 {
00290
00291 memcpy(storage.ht_base[refer.hres].col_table[refer.id].ptr +
00292 storage.ht_base[refer.hres].col_table[refer.id].size,
00293 &appen,
00294 sizeof(appendix_t));
00295 }
00296 }
00297
00298 return true;
00299 }
00300
00301 protected:
00302 typedef struct {
00303 char *ptr;
00304 int size;
00305 } col_member_t;
00306
00307 typedef struct {
00308 size_t col_size;
00309 col_member_t *col_table;
00310 } ht_member_t;
00311
00312 typedef struct {
00313 ht_member_t *ht_base;
00314 size_t states_stored;
00315 size_t states_max_stored;
00316 size_t states_col;
00317 size_t states_max_col;
00318 size_t ht_occupancy;
00319 size_t max_ht_occupancy;
00320 size_t collisions;
00321 size_t max_collisions;
00322 } storage_t;
00323
00324 storage_t storage;
00325
00326 bool initialized;
00327
00328 size_t compression_method;
00329 compressor_t compressor;
00330
00331 size_t ht_size;
00332 size_t col_init_size;
00333 size_t col_resize;
00334
00335 size_t appendix_size;
00336
00337 error_vector_t& errvec;
00338
00339 size_t mem_limit;
00340 size_t mem_used;
00341 size_t mem_max_used;
00342
00343 void mem_counting(int);
00344 hash_function_t hasher;
00345
00346
00347
00348 };
00349 #ifndef DOXYGEN_PROCESSING
00350 }
00351 #endif //end of namespace divine which shouldn't be seen by Doxygen
00352 #endif
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373