CrystalSpace

Public API Reference

csutil/cowwrapper.h

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2006 by Frank Richter
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public
00015     License along with this library; if not, write to the Free
00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_CSUTIL_COWWRAPPER_H__
00020 #define __CS_CSUTIL_COWWRAPPER_H__
00021 
00022 #include "csutil/custom_new_disable.h"
00023 
00024 #include "csutil/allocator.h"
00025 
00030 namespace CS
00031 {
00032 
00061   template<typename T, class MemoryAllocator = Memory::AllocatorMalloc>
00062   class CowWrapper
00063   {
00065     struct WrappedData
00066     {
00067       int refcount;
00068   
00069       void IncRef () { refcount++; }
00070       void DecRef () 
00071       { 
00072         refcount--; 
00073         if (refcount == 0) 
00074         {
00075           this->~WrappedData();
00076           MemoryAllocator::Free (this);
00077         }
00078       }
00079       int GetRefCount () const { return refcount; }
00080       
00081       T data;
00082     public:
00083       WrappedData (const T& other) : refcount (1), data (other) {}
00084       WrappedData (const WrappedData& other) : refcount (1), data (other.data) {}
00085     };
00086   public:
00087     static const size_t allocSize = sizeof (WrappedData);
00088   private:
00089     csRef<WrappedData> data;
00090     inline WrappedData* NewData (const T& other)
00091     {
00092       WrappedData* p = (WrappedData*)MemoryAllocator::Alloc (allocSize);
00093       new (p) WrappedData (other);
00094       return p;
00095     }
00096   public:
00098     CowWrapper (const CowWrapper& other) : data (other.data) {}
00100     CowWrapper (const T& other)
00101     {
00102       data.AttachNew (NewData (other));
00103     }
00104 
00106     const T& operator* () const
00107     {
00108       return data->data;
00109     }
00115     T& operator* ()
00116     {
00117       if (data->GetRefCount() > 1)
00118       {
00119         WrappedData* newData = NewData (data->data);
00120         data.AttachNew (newData);
00121       }
00122       return data->data;
00123     }
00125     const T* operator -> () const
00126     { return &(operator*()); }
00132     T* operator -> ()
00133     { return &(operator*()); }
00134   };
00135 
00136 } // namespace CS
00137 
00138 #include "csutil/custom_new_enable.h"
00139 
00140 #endif // __CS_CSUTIL_COWWRAPPER_H__

Generated for Crystal Space by doxygen 1.4.7