persistance.h

Go to the documentation of this file.
00001 #ifndef PERSISTANCE_H
00002 #define PERSISTANCE_H
00003 
00004 
00005 #ifndef ENABLE_PERSISTANCE
00006 
00007 #  include "persistance-noop.h"
00008 
00009 #else
00010 
00011 #include <vector>
00012 #include <iterator>
00013 #include "hash_set.h"
00014 #include "hash_map.h"
00015 #include "iterator_wrapper.h"
00016 #include "assert.h"
00017 #include <limits>
00018 
00019 class PersistantObject;
00020 
00021 namespace hashers {
00022   template <> struct hash<PersistantObject*> {
00023     unsigned long operator() (const PersistantObject* obj) const {
00024       return (unsigned long)(obj);
00025     }
00026   };
00027   template <> struct hash<const PersistantObject*> {
00028     unsigned long operator() (const PersistantObject* obj) const {
00029       return (unsigned long)(obj);
00030     }
00031   };
00032 };
00033 
00047 class PersistantStore {
00048     friend class PersistantObject;
00049   public:
00050     PersistantStore ();
00051     int add_checkpoint(); /* return the new view number */
00052     void set_view(int);
00053     void set_view_current();
00054     void undo();
00055     void commit();
00056 
00057     int get_time() const;
00058     bool viewing_current() const;
00059     bool logging() const;
00060     bool logging_after_pop() const;
00061 
00062   private:
00068     void notify_access(PersistantObject* data);
00069 
00076     void notify_born(PersistantObject* data);
00077 
00083     void notify_died(PersistantObject* data);
00084 
00091     typedef hashers::hash_set<PersistantObject*> ModifySet;
00092     std::vector<ModifySet> modifications_;
00093     std::vector<ModifySet> births_;
00094     ModifySet died_in_pop_; /* don't commit/undo these, we just deleted them! */
00095 
00096     int current_view_;
00097 
00098     /* True if we are currently popping a checkpoint off. */
00099     bool popping_;
00100 
00101     /* illegal */
00102     PersistantStore(const PersistantStore&);
00103     PersistantStore& operator = (const PersistantStore&);
00104 };
00105 
00110 class PersistantObject {
00111   public:
00112     /* Save a bit on storage. */
00113     PersistantStore& get_store() const {
00114       return store_;
00115     }
00116 
00117   protected:
00118     friend class PersistantStore;
00119 
00120     PersistantObject(PersistantStore& store) : store_(store) {
00121       store_.notify_born(this);
00122     }
00123 
00124     virtual ~PersistantObject() {
00125       store_.notify_died(this);
00126     }
00127 
00129     virtual void undo() = 0;
00130 
00132     virtual void commit() = 0;
00133 
00136     virtual void preincarnate() = 0;
00137 
00141     void notify_access() { store_.notify_access(this); }
00142 
00144     int current_view() const { return store_.current_view_; }
00145 
00147     int logging() const { return store_.logging(); }
00148 
00151     int logging_after_pop() const { return store_.logging_after_pop(); }
00152 
00153   private:
00154     PersistantStore& store_;
00155 
00156     /* illegal */
00157     PersistantObject(const PersistantObject&);
00158     PersistantObject& operator = (const PersistantObject&);
00159 };
00160 
00165 template <class datum_type, bool copy_on_push> class StackPersistantObject
00166 : public PersistantObject
00167 {
00168   protected:
00169     struct timed_entry {
00170       int time;
00171       datum_type datum;
00172       timed_entry(int t, const datum_type& d) :
00173         time(t), datum(d) { }
00174     };
00175 
00176     StackPersistantObject(PersistantStore& store,
00177         const datum_type& initial)
00178       : PersistantObject(store)
00179       {
00180         data_.push_back(timed_entry(store.get_time(), initial));
00181       }
00182     virtual ~StackPersistantObject() { }
00183 
00184     datum_type& get_handle() {
00185       int time = current_view();
00186       if (data_.back().time != time) {
00187     /* Don't notify unless we're pushing a new timestep on:
00188        we either have notified already, or we were allocated
00189        during this timestep. */
00190     notify_access();
00191         assert(data_.back().time < time);
00192         if(copy_on_push) {
00193           data_.push_back(timed_entry(time, data_.back().datum));
00194         } else {
00195           data_.push_back(timed_entry(time, datum_type()));
00196         }
00197       }
00198       return data_.back().datum;
00199     }
00200 
00201     int get_current_index() const {
00202       int time = current_view();
00203       for (int idx = data_.size() - 1; idx >= 0; idx--) {
00204         if (data_[idx].time <= time) {
00205           return idx;
00206         }
00207       }
00208       assert(0);
00209       return -1;
00210     }
00211 
00217     virtual void merge_times(datum_type& older, const datum_type& newer) = 0;
00218 
00219   private:
00226     virtual void commit() {
00227       assert(data_.size() >= 2);
00228       timed_entry& newer = data_[data_.size() - 1];
00229       timed_entry& older = data_[data_.size() - 2];
00230       int timestep_after_commit = newer.time - 1;
00231       if (older.time == timestep_after_commit) {
00232     merge_times(older.datum, newer.datum);
00233     data_.pop_back();
00234       } else {
00235     newer.time = timestep_after_commit;
00236       }
00237     }
00238 
00239     virtual void preincarnate() {
00240       /* we can only be preincarnated if we're at the first checkpoint */
00241       assert(data_.size() == 1);
00242       data_[0].time--;
00243     }
00244 
00245   protected:
00246     std::vector<timed_entry> data_;
00247 
00248   private:
00249     /* illegal */
00250     StackPersistantObject(const StackPersistantObject&);
00251     StackPersistantObject& operator = (const StackPersistantObject&);
00252 };
00253 
00254 
00260 template <class Datum> class PersistantData
00261 : public StackPersistantObject<Datum, true> {
00262   public:
00263     PersistantData (PersistantStore& store, const Datum& initial)
00264       : StackPersistantObject<Datum, true>(store, initial)
00265       { }
00266     virtual ~PersistantData() { }
00267 
00268     const Datum& operator *() const {
00269       return this->data_[this->get_current_index()].datum;
00270     }
00271 
00272     Datum& access() {
00273       return this->get_handle();
00274     }
00275 
00276   protected:
00277     virtual void undo() {
00278       this->data_.pop_back();
00279     }
00280     virtual void merge_times(Datum& older, const Datum& newer) {
00281       /* just lose the old value */
00282       older = newer;
00283     }
00284 
00285   private:
00286     /* illegal */
00287     PersistantData(const PersistantData&);
00288     PersistantData& operator = (const PersistantData&);
00289 };
00290 
00301 template <class Datum, int n> class PersistantArray {
00302   private:
00303     PersistantData<Datum> *data_[n];
00304 
00305   public:
00306     /* Create the array using the default element.  Requires the
00307        datum to have a no-arg constructor. */
00308     PersistantArray(PersistantStore& store) {
00309       for(int i = 0; i < n; i++) {
00310         data_[i] = new PersistantData<Datum>(store, Datum());
00311       }
00312     }
00313 
00314     /* Create the array using a given initial element. */
00315     PersistantArray(PersistantStore& store, const Datum& initial) {
00316       for(int i = 0; i < n; i++) {
00317         data_[i] = new PersistantData<Datum>(store, initial);
00318       }
00319     }
00320 
00321     ~PersistantArray() {
00322       for(int i = 0; i < n; i++) {
00323         delete data_[i];
00324       }
00325     }
00326 
00327     const Datum& operator[] (int i) const {
00328       return **data_[i];
00329     }
00330     Datum& access (int i) {
00331       return data_[i]->access();
00332     }
00333 
00334     class iterator : public Tumble::iterators::dedereferencer<PersistantData<Datum>**, Datum, const Datum&> {
00335       private:
00336         typedef Tumble::iterators::dedereferencer<PersistantData<Datum>**, Datum, const Datum&> super;
00337       public:
00338         iterator() { }
00339         iterator(PersistantData<Datum>** it) : super(it) { }
00340         iterator(PersistantArray& array) : super(array.begin()) { }
00341     };
00342     class const_iterator : public Tumble::iterators::dedereferencer<const PersistantData<Datum>* const *, const Datum> {
00343       private:
00344         typedef Tumble::iterators::dedereferencer<const PersistantData<Datum>*const *, const Datum> super;
00345       public:
00346         const_iterator() { }
00347         const_iterator(const PersistantData<Datum>* const * it) : super(it) { }
00348         const_iterator(const PersistantArray& array) : super(array.begin()) { }
00349     };
00350 
00351     iterator begin() { return data_; }
00352     const_iterator begin() const { return data_; }
00353     iterator end() { return data_ + n; }
00354     const_iterator end() const { return data_ + n; }
00355 
00356     iterator operator+ (int i) {
00357       assert(i <= n);
00358       return iterator(data_ + i);
00359     }
00360     const_iterator operator+ (int i) const {
00361       assert(i <= n);
00362       return const_iterator(data_ + i);
00363     }
00364 
00365   private:
00366     /* illegal */
00367     PersistantArray(const PersistantArray&);
00368     PersistantArray& operator = (const PersistantArray&);
00369 };
00370 
00371 template <class Datum> class PersistantVector {
00372   public:
00373     /* Defined in the order on the SGI STL page for vector */
00374     typedef typename std::vector<Datum>::value_type value_type;
00375     typedef typename std::vector<Datum>::pointer pointer;
00376     typedef typename std::vector<Datum>::reference reference;
00377     typedef typename std::vector<Datum>::const_reference const_reference;
00378     typedef typename std::vector<Datum>::size_type size_type;
00379     typedef typename std::vector<Datum>::difference_type difference_type;
00380 
00381     typedef Tumble::iterators::dedereferencer<PersistantData<Datum>**, value_type, const_reference> iterator;
00382     typedef Tumble::iterators::dedereferencer<const PersistantData<Datum>*const *, value_type, const_reference> const_iterator;
00383 
00384     /* TODO: reverse_iterator, const_reverse_iterator */
00385 
00386     iterator begin() { return iterator(data_); }
00387     iterator end() { return iterator(data_ + size()); }
00388 
00389     const_iterator begin() const { return const_iterator(data_); }
00390     const_iterator end() const { return const_iterator(data_ + size()); }
00391 
00392     /* TODO: rbegin, rend */
00393 
00394     size_type size() const { return *size_; }
00395     size_type max_size() const { return std::numeric_limits<int>::max(); }
00396     size_type capacity() const { return allocated_size_; /* not really... */ }
00397     bool empty() const { return size() == 0; }
00398 
00399     /* reference operator[](size_type i)
00400        - don't allow accidentally allocating when trying to just read */
00401     reference access(size_type i) {
00402       assert(i < size()); /* would fail if we'd never allocated */
00403       if (data_[i] == NULL) {
00404         data_[i] = new PersistantData<value_type>(get_store(), Datum());
00405       }
00406       return data_[i]->access();
00407     }
00408 
00409     const_reference operator[](size_type i) const {
00410       assert(i < size());
00411       return **(data_[i]);
00412     }
00413 
00414     PersistantVector(PersistantStore& store) :
00415       size_(store, 0), data_(NULL), allocated_size_(0) { }
00416 
00417     PersistantVector(PersistantStore& store, size_type n) :
00418       size_(store, 0), data_(NULL), allocated_size_(0) {
00419         reserve(n);
00420         for(size_type i = 0; i < n; i++) {
00421           data_[i] = new PersistantData<Datum>(get_store(), Datum());
00422         }
00423         size_.access() = n;
00424       }
00425 
00426     PersistantVector(PersistantStore& store, size_type n, const Datum& t) :
00427       size_(store, 0), data_(NULL), allocated_size_(0) {
00428         reserve(n);
00429         for(size_type i = 0; i < n; i++) {
00430           data_[i] = new PersistantData<Datum>(get_store(), t);
00431         }
00432         size_.access() = n;
00433       }
00434 
00435     template <class InputIterator>
00436     PersistantVector(PersistantStore& store, InputIterator begin,
00437                      InputIterator end) :
00438       size_(store, 0), data_(NULL), allocated_size_(0) {
00439         for( ; begin != end; ++begin) {
00440           push_back(*begin);
00441         }
00442       }
00443 
00444     ~PersistantVector() {
00445       for(size_type i = 0; i < allocated_size_; i++) {
00446         delete data_[i];
00447       }
00448       delete[] data_;
00449     }
00450 
00451     void reserve(size_type sz) {
00452       if (sz <= allocated_size_) {
00453         return;
00454       }
00455       size_type oldalloc = allocated_size_;
00456       PersistantData<value_type> **olddata = data_;
00457 
00458       allocated_size_ = sz;
00459       data_ = new PersistantData<value_type>* [sz];
00460       for(size_type i = 0; i < oldalloc; i++) {
00461         data_[i] = olddata[i];
00462       }
00463       for(size_type i = oldalloc; i < sz; i++) {
00464         data_[i] = NULL;
00465       }
00466       delete[] olddata;
00467     }
00468 
00469     reference access_front() {
00470       return access(0);
00471     }
00472     const_reference front() const {
00473       return operator[] (0);
00474     }
00475 
00476     reference access_back() {
00477       return access(size() - 1);
00478     }
00479 
00480     const_reference back() const {
00481       return operator[] (size() - 1);
00482     }
00483 
00484     void push_back(const Datum& d) {
00485       size_type sz = size();
00486       ensure_capacity(sz + 1);
00487       if (data_[sz] == NULL) {
00488         data_[sz] = new PersistantData<value_type> (get_store(), d);
00489       } else {
00490         data_[sz]->access() = d;
00491       }
00492       ++size_.access();
00493     }
00494 
00495     void pop_back() {
00496       --size_.access();
00497     }
00498 
00499     iterator insert(iterator pos, const Datum& x) {
00500       if (pos == end()) {
00501         push_back(x);
00502       }
00503       else {
00504         difference_type index = pos - begin();
00505         assert(index >= 0); assert(index < size());
00506         push_back(back());
00507         for(size_type i = size() - 1; i > index; i--) {
00508           access(i) = operator[](i - 1);
00509         }
00510         access(index) = x;
00511       }
00512     }
00513 
00524     iterator erase(iterator pos) {
00525       difference_type index = pos - begin();
00526       assert(index >= 0); assert(size_type(index) < size());
00527       size_type sz = size();
00528       for(size_type i = index; i < sz - 1; i++) {
00529         access(i) = operator[](i + 1);
00530       }
00531       pop_back();
00532     }
00533 
00538     void clear() {
00539       size_.access() = 0;
00540     }
00541 
00547     PersistantStore& get_store() const {
00548       return size_.get_store();
00549     }
00550 
00551   private:
00552     void ensure_capacity(size_type sz) {
00553       if (sz > allocated_size_) {
00554         if (allocated_size_ == 0) {
00555           reserve(sz);
00556         } else {
00557           reserve((allocated_size_ * 2 > sz) ? (allocated_size_ * 2) : sz);
00558         }
00559       }
00560     }
00561 
00562   private:
00563     /* illegal */
00564     PersistantVector(const PersistantVector&);
00565     PersistantVector& operator=(const PersistantVector&);
00566 
00567   private:
00568     /* Data members */
00569     PersistantData<size_type> size_;
00570     PersistantData<value_type> **data_;
00571     size_type allocated_size_;
00572 };
00573 
00574 template <class Datum>
00575 bool operator==(const PersistantVector<Datum>& v1,
00576                 const PersistantVector<Datum>& v2) {
00577   if (v1.size() != v2.size()) {
00578     return false;
00579   }
00580   typename PersistantVector<Datum>::const_iterator it1 = v1.begin();
00581   typename PersistantVector<Datum>::const_iterator it2 = v2.begin();
00582   while(it1 != v1.end()) {
00583     if (*it1 != *it2) {
00584       return false;
00585     }
00586     ++it1;
00587     ++it2;
00588   }
00589   return true;
00590 }
00591 
00592 template <class Datum>
00593 bool operator< (const PersistantVector<Datum>& v1,
00594                 const PersistantVector<Datum>& v2) {
00595   typename PersistantVector<Datum>::const_iterator it1 = v1.begin();
00596   typename PersistantVector<Datum>::const_iterator it2 = v2.begin();
00597   while(it1 != v1.end()) {
00598     if (it2 == v2.end()) {
00599       return true; /* v2 is longer, so it's lexicographically later */
00600     }
00601     if (*it1 < *it2) {
00602       return true;
00603     } else if (*it2 < *it1) {
00604       return false;
00605     }
00606     ++it1;
00607     ++it2;
00608   }
00609   if (it2 == v2.end()) {
00610     /* same length, so we're == */
00611     return false;
00612   } else {
00613     /* v2 is longer, so v1 is < */
00614     return true;
00615   }
00616 }
00617 
00618 
00619 /* really a member of PersistantMemoryPool */
00620 template <class Datum> struct PMP_pair {
00621   struct PMP_hash {
00622     unsigned long operator() (const Datum& d) const {
00623       return (unsigned long)(d);
00624     }
00625   };
00626   hashers::hash_set<Datum, PMP_hash> allocated, deleted;
00627   typedef typename hashers::hash_set<Datum, PMP_hash>::iterator iterator;
00628 };
00629 
00638 template <class Datum> class PersistantMemoryPool
00639 : public StackPersistantObject<PMP_pair<Datum*>, false> {
00640   public:
00641     PersistantMemoryPool(PersistantStore& store) :
00642       StackPersistantObject<PMP_pair<Datum*>, false>(store,PMP_pair<Datum*>())
00643     { }
00644 
00645     virtual ~PersistantMemoryPool() {
00646       /* go through all allocated items, delete them. */
00647       for(int i = this->data_.size() - 1; i >= 0; i--) {
00648         typename PMP_pair<Datum*>::iterator it;
00649         for(it = this->data_[i].datum.allocated.begin();
00650             it != this->data_[i].datum.allocated.end(); ++it) {
00651           dofinaldelete(*it);
00652         }
00653       }
00654       /* the allocated/deleted lists will be nuked automatically */
00655     }
00656 
00657     void mark_allocated(Datum *key) {
00658       /* whether or not we're logging, we need to keep track of 'key' */
00659       PMP_pair<Datum*>& handle = this->get_handle();
00660       handle.allocated.insert(key);
00661       assert(handle.deleted.count(key) == 0);
00662     }
00663 
00664     void mark_deleted(Datum *key) {
00665       /* whether or not we're logging, we need to keep track of 'key' */
00666       PMP_pair<Datum*>& handle = this->get_handle();
00667       if (handle.allocated.count(key) != 0) {
00668         /* delete/allocate in the same checkpoint: actually delete it,
00669            since now we will never undo the deletion. */
00670         handle.allocated.erase(key);
00671         dodelete(key);
00672       } else {
00673         assert(this->logging());
00674         handle.deleted.insert(key);
00675       }
00676     }
00677 
00678   protected:
00679     virtual void undo() {
00680       assert(this->logging());
00681       /* Allocated entries must be deleted; deleted entries
00682        * simply get not deleted. */
00683       typename PMP_pair<Datum*>::iterator it;
00684       for(it = this->data_.back().datum.allocated.begin();
00685           it != this->data_.back().datum.allocated.end(); ++it) {
00686         dodelete(*it);
00687       }
00688       this->data_.pop_back();
00689     }
00690 
00691     virtual void merge_times(PMP_pair<Datum*>& older,
00692                  const PMP_pair<Datum*>& newer) {
00693       older.allocated.insert(newer.allocated.begin(), newer.allocated.end());
00694       for (typename PMP_pair<Datum*>::iterator it = newer.deleted.begin();
00695       it != newer.deleted.end(); ++it) {
00696     if (older.allocated.erase(*it)) {
00697       /* allocated and deleted in the same timestep: just delete it */
00698       dodelete(*it);
00699     } else {
00700       /* allocated in a prior timestep; mark it deleted */
00701       assert(this->logging_after_pop()); // there must be a prior time
00702       older.deleted.insert(*it);
00703     }
00704       }
00705     }
00706 
00711     virtual void dodelete(Datum *d) {
00712       delete d;
00713     }
00714 
00718     virtual void dofinaldelete(Datum *d) {
00719       delete d;
00720     }
00721 
00722   private:
00723     /* illegal */
00724     PersistantMemoryPool(const PersistantMemoryPool&);
00725     PersistantMemoryPool& operator = (const PersistantMemoryPool&);
00726 };
00727 
00731 template <class Value>
00732 class PersistantList {
00733   private:
00734     struct node {
00735       PersistantData<node*> prev_;
00736       PersistantData<node*> next_;
00737       PersistantData<Value> value_;
00738       node(PersistantStore& store, node *prev, node *next, const Value& initial)
00739     : prev_(store, prev), next_(store, next), value_(store, initial)
00740         { }
00741     };
00742 
00743     PersistantData<int> size_;
00744     PersistantData<node*> first_;
00745     PersistantData<node*> last_;
00746     PersistantMemoryPool<node> pool_;
00747 
00748     node *do_insert(node *prev, node *next, const Value& v) {
00749       node *newnode = new node(get_store(), prev, next, v);
00750       pool_.mark_allocated(newnode);
00751       size_.access()++;
00752 
00753       if (prev) {
00754     prev->next_.access() = newnode;
00755       } else {
00756     first_.access() = newnode;
00757       }
00758       if (next) {
00759     next->prev_.access() = newnode;
00760       } else {
00761     last_.access() = newnode;
00762       }
00763       return newnode;
00764     }
00765 
00766   public:
00767     struct const_iterator {
00768       friend class PersistantList;
00769       protected:
00770         node *n_;
00771 
00772         const_iterator(node *n) : n_(n) { }
00773       public:
00774         const_iterator() { }
00775 
00776         const Value& operator*() const {
00777           return *n_->value_;
00778         }
00779         const Value *operator->() const {
00780           return &operator*();
00781         }
00782         Value& access() {
00783           return n_->value_.access();
00784         }
00785 
00786         const_iterator& operator++() {
00787           n_ = *n_->next_; return *this;
00788         }
00789         const_iterator& operator--() {
00790           n_ = *n_->prev_; return *this;
00791         }
00792         bool operator== (const const_iterator& other) const {
00793           return n_ == other.n_;
00794         }
00795         bool operator!= (const const_iterator& other) const {
00796           return n_ != other.n_;
00797         }
00798 
00799         unsigned long hashcode() const {
00800           return (unsigned long) n_;
00801         }
00802 
00803         /* stl stuff */
00804         typedef ptrdiff_t                     difference_type;
00805         typedef std::bidirectional_iterator_tag iterator_category;
00806         typedef Value                         value_type;
00807         typedef const Value   &               reference;
00808         typedef const Value   *               pointer;
00809     };
00810     
00814     struct iterator : public const_iterator {
00815       friend class PersistantList;
00816       private:
00817         iterator(node *n) : const_iterator(n) { }
00818       public:
00819         iterator() { }
00820 
00821         Value& access() const {
00822           return const_iterator::n_->value_.access();
00823         }
00824 
00825         iterator& operator++() {
00826           const_iterator::operator++();
00827           return *this;
00828         }
00829         iterator& operator--() {
00830           const_iterator::operator--();
00831           return *this;
00832         }
00833     };
00834 
00835     PersistantList(PersistantStore& store)
00836       : size_(store, 0), first_(store, NULL), last_(store, NULL), pool_(store)
00837       { }
00838 
00839     iterator begin() const {
00840       return iterator(*first_);
00841     }
00842     iterator end() const {
00843       return iterator(NULL);
00844     }
00845     const Value& back() const {
00846       return *iterator(*last_);
00847     }
00848     const Value& first() const {
00849       return *iterator(*first_);
00850     }
00851     int size() const {
00852       return *size_;
00853     }
00854     bool empty() const {
00855       return size() == 0;
00856     }
00857 
00858     iterator insert(iterator it, const Value& v) {
00859       node *prev = const_cast<node*>(*it.n_->prev_);
00860       node *next = const_cast<node*>(*it.n_->next_);
00861       return iterator(do_insert(prev, next, v));
00862     }
00863     iterator push_back(const Value& v) {
00864       return iterator(do_insert(const_cast<node*>(*last_), NULL, v));
00865     }
00866     iterator push_front(const Value& v) {
00867       return iterator(do_insert(NULL, const_cast<node*>(*first_), v));
00868     }
00869 
00870     iterator erase(iterator it) {
00871       node *prev = const_cast<node*>(*it.n_->prev_);
00872       node *next = const_cast<node*>(*it.n_->next_);
00873       if (prev) {
00874     prev->next_.access() = next;
00875       } else {
00876     first_.access() = next;
00877       }
00878       if (next) {
00879     next->prev_.access() = prev;
00880       } else {
00881     last_.access() = prev;
00882       }
00883       size_.access()--;
00884       pool_.mark_deleted(it.n_);
00885       return iterator(next);
00886     }
00887     void pop_back() {
00888       return erase(iterator(*last_));
00889     }
00890     void pop_front() {
00891       return erase(begin());
00892     }
00893 
00894     PersistantStore& get_store() const { return size_.get_store(); }
00895 };
00896 
00908 template <class Key, class HashFcn = hashers::hash<Key>,
00909       class EqualKey = std::equal_to<Key> >
00910 class PersistantHashSet {
00911   private:
00921     struct map_data {
00922       private:
00923         PersistantData< bool > valid_;
00924         Key data_;
00925         PersistantData< map_data* > next_;
00926         PersistantData< map_data* > prev_;
00927 
00928       public:
00929         map_data(PersistantStore& store, const Key& dat)
00930           : valid_(store, true)
00931           , data_(dat)
00932           , next_(store, NULL)
00933           , prev_(store, NULL) {
00934           }
00935 
00936         /* unlink from the iterate list */
00937         void unlink() {
00938           map_data *next = get_next();
00939           map_data *prev = get_prev();
00940           if (next) {
00941             set_next(NULL);  // otherwise, it's already NULL
00942             next->set_prev(prev);
00943           }
00944           if (prev) {
00945             set_prev(NULL);  // otherwise, it's already NULL
00946             prev->set_next(next);
00947           }
00948         }
00949 
00950         bool has_data() const {
00951           return *valid_;
00952         }
00953 
00954         void set_valid(bool valid = true) {
00955           valid_.access() = valid;
00956         }
00957 
00958         const Key& get_data() const {
00959           assert(has_data());
00960           return data_;
00961         }
00962         const Key& unconditional_get_data() const {
00963           return data_;
00964         }
00965 
00966         map_data *get_next() const {
00967           return *next_;
00968         }
00969 
00970         map_data *get_prev() const {
00971           return *prev_;
00972         }
00973 
00974         void set_next(map_data *next) {
00975           next_.access() = next;
00976         }
00977 
00978         void set_prev(map_data *prev) {
00979           prev_.access() = prev;
00980         }
00981     };
00982 
00983     struct deref_hasher {
00984       HashFcn hasher_;
00985       int operator()(const Key *key) const {
00986     return hasher_(*key);
00987       }
00988     };
00989 
00990     struct deref_equal {
00991       EqualKey equal_;
00992       bool operator()(const Key *key1, const Key *key2) const {
00993     return equal_(*key1, *key2);
00994       }
00995     };
00996 
00997     typedef hashers::hash_map<const Key*, map_data*, deref_hasher, deref_equal> map_type;
00998 
01003     struct Reaper : public PersistantMemoryPool<map_data> {
01004       public:
01005     Reaper(PersistantStore& store, map_type& hashset)
01006       : PersistantMemoryPool<map_data>(store), hashset_(hashset) { }
01007 
01008       protected:
01009         /* Just remove from the hash; all the other stuff will magically
01010            get undone. */
01011     virtual void dodelete(map_data *data) {
01012       bool diderase;
01013           /* get the key out of the map_data, whether or not it's valid */
01014           diderase = hashset_.erase(& data->unconditional_get_data());
01015           assert(diderase);
01016       delete data;
01017     }
01018         /* on final deletion, just delete -- the hashset is about
01019            to go, too */
01020 
01021       private:
01022     map_type& hashset_;
01023     };
01024 
01025     map_data *internal_find(const Key& key) const {
01026       typename map_type::const_iterator it = datamap_.find(&key);
01027       if(it == datamap_.end()) {
01028         return NULL;
01029       } else {
01030         return (*it).second;
01031       }
01032     }
01033 
01034   public:
01039     class iterator {
01040       private:
01041     friend class PersistantHashSet;
01042     iterator(map_data *data) : datap(data) { }
01043       public:
01044     iterator() { datap = NULL; }
01045 
01046     const Key& operator *() const {
01047       assert(datap->has_data());
01048       return datap->get_data();
01049     }
01050         const Key *operator->() const {
01051           return &operator*();
01052         }
01053 
01054     iterator& operator++() {
01055       assert(datap);
01056       datap = datap->get_next();
01057       return *this;
01058     }
01059     bool operator == (iterator other) const {
01060       return datap == other.datap;
01061     }
01062     bool operator != (iterator other) const {
01063       return ! (other == *this);
01064     }
01065 
01066         /* stl stuff */
01067         typedef ptrdiff_t                     difference_type;
01068         typedef std::forward_iterator_tag     iterator_category;
01069         typedef Key                           value_type;
01070         typedef const Key     &               reference;
01071         typedef const Key     *               pointer;
01072 
01073       private:
01074     map_data *datap;
01075     };
01076     /* all our iterators are const */
01077     typedef iterator const_iterator;
01078 
01082     PersistantHashSet(PersistantStore& store)
01083       : size_(store, 0), first_(store, NULL), reaper_(store, datamap_)
01084       { }
01085 
01089     iterator find(const Key& key) const {
01090       map_data *datap = internal_find(key);
01091 
01092       if(!datap || !datap->has_data()) {
01093         return end();
01094       } else {
01095         return iterator(datap);
01096       }
01097     }
01098 
01103     size_t count(const Key& key) const {
01104       return (find(key) == end()) ? 0 : 1;
01105     }
01106 
01110     bool operator[] (const Key& key) const {
01111       return find(key) != end();
01112     }
01113 
01117     int size() const {
01118       return *size_;
01119     }
01120 
01124     bool empty() const {
01125       return size() == 0;
01126     }
01127 
01133     std::pair<iterator,bool> insert(const Key& key) {
01134       assert(get_store().viewing_current());
01135 
01136       bool didinsert;
01137       map_data *founddata;
01138 
01139       founddata = internal_find(key);
01140       if (founddata == NULL) {
01141         founddata = new map_data(get_store(), key);
01142     reaper_.mark_allocated(founddata); /* avoid leaking on undo */
01143         datamap_.insert(std::make_pair(&(founddata->get_data()), founddata));
01144         push_first(founddata);
01145         didinsert = true;
01146       } else if (!founddata->has_data()) {
01147         founddata->set_valid();
01148         push_first(founddata);
01149         didinsert = true;
01150       } else {
01151         didinsert = false;
01152       }
01153       return std::make_pair(iterator(founddata), didinsert);
01154     }
01155 
01161     bool erase(iterator it) {
01162       assert(get_store().viewing_current());
01163       if(it == end()) {
01164         return false;
01165       }
01166       /* unlink the current data */
01167       map_data *datap = it.datap;
01168       assert(datap->has_data());
01169       unlink_data(datap);
01170       datap->set_valid(false);
01171       reaper_.mark_deleted(datap); /* possibly deletes it immediately */
01172       return true;
01173     }
01174 
01175     bool erase(const Key& key) {
01176       return erase(find(key));
01177     }
01178 
01182     void clear() {
01183       while (!empty()) {
01184         erase(begin());
01185       }
01186     }
01187 
01188     iterator begin() const {
01189       return iterator(*first_);
01190     }
01191     iterator end() const {
01192       return iterator(NULL);
01193     }
01194 
01195     PersistantStore& get_store() const { return size_.get_store(); }
01196 
01197   private:
01202     void push_first(map_data *newfirst) {
01203       map_data *oldfirst = *first_;
01204       assert(oldfirst == NULL || oldfirst->get_prev() == NULL);
01205       assert(newfirst->get_prev() == NULL);
01206       assert(newfirst->get_next() == NULL);
01207       if (oldfirst) {
01208     oldfirst->set_prev(newfirst);
01209     newfirst->set_next(oldfirst); /* otherwise, it's already NULL */
01210       }
01211       first_.access() = newfirst;
01212       size_.access()++;
01213     }
01214 
01219     void unlink_data(map_data *tounlink) {
01220       if (tounlink == begin().datap) {
01221         first_.access() = tounlink->get_next();
01222       }
01223       tounlink->unlink();
01224       if (tounlink->has_data()) {
01225     size_.access()--;
01226       }
01227     }
01228 
01229     map_type datamap_;
01230     PersistantData<int> size_;
01231     PersistantData<map_data*> first_;
01232     Reaper reaper_;
01233 
01234   private:
01235     /* illegal */
01236     PersistantHashSet(const PersistantHashSet&);
01237     PersistantHashSet& operator = (const PersistantHashSet&);
01238 };
01239 
01245 template <class Key, class Value, class HashFcn = hashers::hash<Key>,
01246       class EqualKey = std::equal_to<Key> >
01247 class PersistantHashMap {
01248   public:
01249     class iterator;
01250     friend class iterator;
01251 
01252   private:
01253     typedef PersistantData<Value> value_type;
01254 
01255     struct hasher {
01256       HashFcn fn;
01257       unsigned long operator()(const std::pair<Key,value_type*>& p) const {
01258         return fn(p.first);
01259       }
01260     };
01261     struct equaler {
01262       EqualKey fn;
01263       unsigned long operator()(const std::pair<Key,value_type*>& p1,
01264                                const std::pair<Key,value_type*>& p2) const {
01265         return fn(p1.first, p2.first);
01266       }
01267     };
01268 
01270     static std::pair<Key, value_type*> search_key(const Key& k) {
01271       return std::make_pair(k, (value_type*)NULL);
01272     }
01273 
01276     struct PHM_pair {
01277       friend class iterator;
01278       const Key& first;
01279       const Value& second;
01280       private:
01281       PHM_pair(const Key& k, value_type *vptr)
01282         : first(k), second(**vptr) { }
01283     };
01284 
01286     typedef PersistantHashSet< std::pair<Key, value_type*>,
01287         hasher, equaler> set_type;
01288 
01289     /* data members */
01290     set_type set_;
01291     PersistantMemoryPool<value_type> pool_;
01292 
01293   public:
01294     class iterator {
01295       friend class PersistantHashMap;
01296       private:
01297     typename set_type::iterator it_;
01298     iterator(typename set_type::iterator it) : it_(it) { }
01299       public:
01300     iterator() { }
01301     PHM_pair operator*() const {
01302       return PHM_pair((*it_).first, (*it_).second);
01303     }
01304     iterator& operator++() {
01305       ++it_;
01306       return *this;
01307     }
01308     bool operator==(const iterator& other) const {
01309       return it_ == other.it_;
01310     }
01311     bool operator!=(const iterator& other) const {
01312       return it_ != other.it_;
01313     }
01314 
01315         /* stl stuff */
01316         typedef ptrdiff_t                     difference_type;
01317         typedef std::forward_iterator_tag     iterator_category;
01318         typedef PHM_pair                      value_type;
01319         typedef const PHM_pair&               reference;
01320         typedef const PHM_pair*               pointer;
01321     };
01322     /* all our iterators are const */
01323     typedef iterator const_iterator;
01324 
01325 
01326     PersistantHashMap(PersistantStore& store)
01327       : set_(store), pool_(store)
01328       { }
01329 
01330     int size() const {
01331       return set_.size();
01332     }
01333     bool empty() const {
01334       return size() == 0;
01335     }
01336     iterator begin() const {
01337       return iterator(set_.begin());
01338     }
01339     iterator end() const {
01340       return iterator(set_.end());
01341     }
01342     iterator find(const Key& k) const {
01343       return iterator(set_.find(search_key(k)));
01344     }
01345     int count(const Key& k) const {
01346       if (find(k) == end()) {
01347         return 0;
01348       } else {
01349         return 1;
01350       }
01351     }
01352 
01353     std::pair<iterator,bool> insert(const std::pair<Key,Value>& v) {
01354       return insert(v.first, v.second);
01355     }
01356 
01357     std::pair<iterator,bool> insert(const Key& k, const Value& v) {
01358       std::pair<typename set_type::iterator,bool> p =
01359     set_.insert(search_key(k));
01360       typename set_type::iterator it = p.first;
01361 
01362       // cast away const so we can muck with the value
01363       value_type*& storedval = const_cast<value_type*&>( (*it).second );
01364       if (storedval) {
01365     storedval->access() = v;
01366     return std::make_pair(iterator(it), p.second);
01367       } else {
01368     storedval = new PersistantData<Value>(get_store(), v);
01369     pool_.mark_allocated(storedval);
01370     return std::make_pair(iterator(it), true);
01371       }
01372     }
01373 
01374     bool erase(iterator it) {
01375       return set_.erase(it.it_);
01376     }
01377     bool erase(const Key& k) {
01378       return erase(find(k));
01379     }
01380 
01381     /* This is only allowed when we are allowed to modify, and
01382      * is inefficient and ugly.  Use find() and insert() instead. */
01383     Value& operator[] (const Key& k) {
01384       iterator found = find(k);
01385       if (found == end()) {
01386         found = insert(k, Value()).first;
01387       }
01388       // cast away const so we can call access()
01389       value_type *storedval = const_cast<value_type*>((*found.it_).second);
01390       return storedval->access();
01391     }
01392 
01393     PersistantStore& get_store() const { return set_.get_store(); }
01394 
01395   private:
01396     /* illegal */
01397     PersistantHashMap(const PersistantHashMap&);
01398     PersistantHashMap& operator = (const PersistantHashMap&);
01399 };
01400 #endif /* ENABLE_PERSISTANCE */
01401 
01402 #endif /* PERSISTANCE_H */

Generated on Mon May 24 09:53:30 2010 for TUMBLE by  doxygen 1.5.2