sprint 1-alpha
|
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