home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,485 of 33,346   
   Kaba to Kaba   
   Re: Layered data structures   
   16 Jul 12 18:06:28   
   
   From: kaba@nowhere.com   
      
   14.7.2012 3:23, Kaba wrote:   
   > Consider data structures A and B, where B refers to parts of A.   
   > Then the modification, or destruction, of A, invalidates the state   
   > of B. How can we guarantee that A is not modified or destructed   
   > while B is referring to A?   
      
   First, let us rephrase the problem slightly better.   
      
   Consider data structures A and B, where B refers to parts of A. Then the   
   modification, or destruction, of A, invalidates the state of B. How   
   can we guarantee that the state of B is always valid?   
      
   ### Option 7: Read pointers   
      
   In this option A is derived from ReadProtected, which injects a   
   reference count into A. Whoever wants to place A into an immutable   
   state, obtains a ReadPtr from the ReadProtected object. To this   
   extent, ReadProtected is implicitly convertible to a ReadPtr, and   
   this is the only way to obtain an original ReadPtr. Other   
   ReadPtr's are copies of each other. The reference count in   
   ReadProtected is the number of ReadPtr's that reference the   
   derived class A. ReadProtected contains a member function   
   readProtect(), which is used to check that there are no active ReadPtr's.   
      
   #include    
   #include    
   #include    
      
   typedef int integer;   
      
   template    
   class ReadProtected;   
      
   template    
   class ReadPtr   
   {   
   public:   
       const Type& operator*() const   
       {   
           return data_;   
       }   
      
       const Type* operator->() const   
       {   
           return data_;   
       }   
      
       ReadPtr()   
           : data_(0)   
           , count_(0)   
       {   
       }   
      
       ReadPtr(ReadPtr&& that)   
           : data_(0)   
           , count_(0)   
       {   
           swap(that);   
       }   
      
       ReadPtr(const ReadPtr& that)   
           : data_(that.data_)   
           , count_(that.count_)   
       {   
           increaseCount();   
       }   
      
       ReadPtr& operator=(ReadPtr that)   
       {   
           swap(that);   
           return *this;   
       }   
      
       ~ReadPtr()   
       {   
           clear();   
       }   
      
       void swap(ReadPtr& that)   
       {   
           using std::swap;   
           swap(data_, that.data_);   
           swap(count_, that.count_);   
       }   
      
       void clear()   
       {   
           decreaseCount();   
           data_ = 0;   
           count_ = 0;   
       }   
      
       integer count() const   
       {   
           assert(count_);   
           return *count_;   
       }   
      
   private:   
       friend class ReadProtected;   
      
       explicit ReadPtr(const Type* data, integer* count)   
           : data_(data)   
           , count_(count)   
       {   
           increaseCount();   
       }   
      
       void increaseCount()   
       {   
           if (count_)   
           {   
               ++(*count_);   
           }   
       }   
      
       void decreaseCount()   
       {   
           if (count_)   
           {   
               --(*count_);   
           }   
       }   
      
       const Type* data_;   
       integer* count_;   
   };   
      
   template    
   class ReadProtected   
   {   
   public:   
       ReadProtected()   
       : readCount_(new integer(0))   
       {   
       }   
      
       ~ReadProtected()   
       {   
           readProtect();   
       }   
      
       void swap(ReadProtected& that)   
       {   
           readCount_.swap(that.readCount_);   
       }   
      
       operator ReadPtr() const   
       {   
           return ReadPtr((const Type*)this, readCount_.get());   
       }   
      
   protected:   
       void readProtect()   
       {   
           bool ObjectIsMutable =   
               (*readCount_ == 0);   
           assert(ObjectIsMutable);   
       }   
      
       std::unique_ptr readCount_;   
   };   
      
   class Grammar   
       : public ReadProtected   
   {   
   public:   
       Grammar()   
       {   
       }   
      
       void mutate()   
       {   
           readProtect();   
       }   
      
       integer query() const   
       {   
           return 0;   
       }   
   };   
      
   class GrammarAnalysis   
   {   
   public:   
       explicit GrammarAnalysis(   
           const ReadPtr& grammar)   
           : grammar_(grammar)   
       {   
           grammar_->query();   
       }   
      
   private:   
       ReadPtr grammar_;   
   };   
      
   int main()   
   {   
       Grammar grammar;   
      
       // Ok   
       grammar.mutate();   
       {   
           GrammarAnalysis analysis(grammar);   
      
           // Ok   
           grammar.query();   
      
           // Error   
           grammar.mutate();   
       }   
      
       // Ok   
       grammar.mutate();   
      
       return 0;   
   }   
      
   This is starting to look like an acceptable solution to me. The only   
   downside is that one must derive from ReadProtected. This ok, but then   
   for example when swapping Grammars, one needs to remember to swap the   
   ReadProtected too. Note that it is necessary that A be reference-counted   
   and that its mutable functions be marked explicitly, so these are not   
   extraneous.   
      
   --   
   http://kaba.hilvi.org   
      
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca