sprint 1-alpha
sprint/container/shared_vector.h
Go to the documentation of this file.
00001 /******************************************************************************
00002 *   sprint::shared_vector
00003 *
00004 *   Copyright (C) 2005-2011  Paolo Medici <www.pmx.it>
00005 *
00006 *  This library is free software; you can redistribute it and/or
00007 *  modify it under the terms of the GNU Lesser General Public
00008 *  License as published by the Free Software Foundation; either
00009 *  version 2.1 of the License, or (at your option) any later version.
00010 *
00011 *  This library is distributed in the hope that it will be useful,
00012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 *  Lesser General Public License for more details.
00015 *
00016 *  You should have received a copy of the GNU Lesser General Public
00017 *  License along with this library; if not, write to the Free Software
00018 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 *
00020 *******************************************************************************/
00021 
00027 #ifndef _SPRINT_SHAREDVECTOR_H
00028 #define _SPRINT_SHAREDVECTOR_H
00029 
00030 #include <cstring>
00031 // #include <bits/allocator.h>
00032 #include <memory>
00033 
00034 namespace sprint {
00035 
00041 template<typename _Tp, typename _Alloc = std::allocator<unsigned char> >
00042 class shared_vector: public _Alloc {
00043         protected:
00044         
00045         // base pointer
00046     struct _Rep {
00047       long m_size;      
00048       long m_capacity;  
00049       long m_refCount;  
00050     };
00051 
00052     static const int suggestedSize = (65536 - sizeof(_Rep)/sizeof(_Tp));
00053 
00055     _Tp *m_data;
00056 
00057         // the _Rep info block (where memory begins)
00058     _Rep *_M_rep() const
00059       { 
00060                         return &((reinterpret_cast<_Rep*>(m_data))[-1]); 
00061           }
00062         
00063     // alloc memory using current allocator             
00064                 _Rep *alloc(long size)
00065                 {
00066                                 unsigned char *p = this->allocate( sizeof(_Tp) * size + sizeof(_Rep) );
00067                                 _Rep *r = reinterpret_cast<_Rep*>(p);
00068                                 r->m_capacity = size;
00069                                 r->m_refCount = 1;
00070                                 return r;
00071                 }
00072                 
00073         // release memory using current allocator
00074                 void release(_Rep *r)
00075                 {
00076                         if ( (--r->m_refCount) == 0)
00077                          {
00078                                 this->deallocate( reinterpret_cast<unsigned char*>(r),  r->m_capacity * sizeof(_Tp) + sizeof(_Rep) );                   
00079              }
00080                 }
00081                 
00082 
00083 
00084 public:
00085                 shared_vector(long size = suggestedSize ) 
00086                         { 
00087                                 _Rep * r = alloc(size);
00088                                 r->m_size = 0;
00089                                 m_data = reinterpret_cast<_Tp * >( &r[1] );
00090                         }
00091                         
00092                 shared_vector(const shared_vector & s)
00093                 {
00094                         m_data = s.m_data;
00095                         ++_M_rep()->m_refCount;
00096                 }
00097        
00098         ~shared_vector()
00099         {
00100                         release(_M_rep());
00101                 }
00102 
00104         void resize(long new_size)
00105         {
00106           reserve(new_size);
00107                                 _M_rep()->m_size = new_size;
00108                                 // TODO: initialize new data
00109         }
00110 
00112         void reserve(long reserve)
00113         {
00114                 _Rep *r = _M_rep();
00115                 if(reserve > r->m_capacity)
00116                         {
00117                     // TODO: reserve arrotondare a un valore X
00118                                 _Rep *nr = alloc(reserve);
00119                                 nr->m_size = r->m_size;
00120                                 memcpy(&nr[1], &r[1], r->m_size * sizeof(_Tp));
00121                                 release(r);
00122                                 m_data = reinterpret_cast<_Tp *>( &r[1] );
00123                         }
00124         }
00125                 
00127                 inline int size() const
00128                     {  return _M_rep()->m_size;       }  
00129                 
00131         inline int capacity() const
00132                     {  return _M_rep()->m_capacity;   }  
00133                 
00134         inline _Tp & operator[](int i)     
00135             {  return m_data[i];             }
00136             
00138         inline _Tp * begin() { return &m_data[0]; }
00139         inline const _Tp * begin() const { return &m_data[0]; }
00141         inline const _Tp * end() const { return &m_data[_M_rep()->m_size]; }
00142                 
00143                 inline const _Tp & operator[](int i) const  
00144             {  return m_data[i];             }          
00145 
00146          inline bool unique() const      
00147             {  return  _M_rep()->m_refCount==1;    }
00148          
00149      inline long use_count() const      
00150             {  return  _M_rep()->m_refCount;     }
00151      
00152 };
00153 
00154 }
00155 
00156 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines