|
CLAM-Development
1.3
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program 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 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #ifndef StreamImpl_hxx 00023 #define StreamImpl_hxx 00024 00025 #include "Region.hxx" 00026 #include <list> 00027 #include <vector> 00028 #include "PhantomBuffer.hxx" 00029 namespace CLAM 00030 { 00031 00033 template <typename T> 00034 class StdList : public std::list<T> 00035 {}; 00036 00037 template <typename T> 00038 class StdVector : public std::vector<T> 00039 {}; 00040 00041 00042 00043 template< typename Token, template <class> class DataStructure > 00044 class StreamImpl 00045 { 00046 00047 public: 00048 void NewWritingRegionSize( Region& writer ); 00050 void NewReadingRegionSize( Region& ); 00051 void WriterHasAdvanced( Region& writer ); 00052 void ReaderHasAdvanced( Region& reader ); 00056 Token& Read(int physicalIndex, int size); 00057 Token& operator[](int physicalIndex); 00058 int LogicalSize() const; 00059 bool ExistsCircularOverlap(int rear, int writingHead) const; 00060 00061 private: 00062 void RegionHasAdvanced( Region& region ); 00063 00064 DataStructure<Token> mDataImpl; 00065 }; 00066 00068 00069 template< typename Token, template <class> class DataStructure > 00070 void StreamImpl<Token,DataStructure>::NewWritingRegionSize( Region& writer ) 00071 { 00072 if ( writer.Size() <= LogicalSize() ) return; 00073 int newTokens = writer.Size() - LogicalSize(); 00074 for( int i=0; i<newTokens; i++) 00075 mDataImpl.push_back(Token()); 00076 } 00077 00078 template< typename Token, template <class> class DataStructure > 00079 void StreamImpl<Token,DataStructure>::RegionHasAdvanced( Region& region ) 00080 { 00081 region.BeginDistance( region.BeginDistance() + region.Hop() ); 00082 00083 if (region.BeginDistance() >= LogicalSize() ) // circular movement 00084 region.BeginDistance( region.BeginDistance() - LogicalSize() ); 00085 } 00086 00087 template< typename Token, template <class> class DataStructure > 00088 void StreamImpl<Token,DataStructure>::NewReadingRegionSize( Region& ) 00089 { 00090 } 00091 00092 template< typename Token, template <class> class DataStructure > 00093 void StreamImpl<Token,DataStructure>::WriterHasAdvanced( Region& writer ) 00094 { 00095 for( int i=0; i<writer.Hop(); i++) 00096 mDataImpl.push_back(Token()); 00097 00098 RegionHasAdvanced( writer ); 00099 } 00100 00101 template< typename Token, template <class> class DataStructure > 00102 void StreamImpl<Token,DataStructure>::ReaderHasAdvanced( Region& reader ) 00103 { 00104 // TODO: discard old tokens 00105 RegionHasAdvanced( reader); 00106 } 00107 00108 template< typename Token, template <class> class DataStructure > 00109 Token& StreamImpl<Token,DataStructure>::Read(int physicalIndex, int size) 00110 { 00111 return operator[](physicalIndex); 00112 } 00113 00114 template< typename Token, template <class> class DataStructure > 00115 Token& StreamImpl<Token,DataStructure>::operator[](int physicalIndex) 00116 { 00117 CLAM_DEBUG_ASSERT( physicalIndex < int(mDataImpl.size()), "StreamImpl operator[] - Index out of bounds" ); 00118 typename DataStructure<Token>::iterator it; 00119 int i; 00120 for(i=0, it = mDataImpl.begin(); i<physicalIndex; it++, i++); 00121 return (*it); 00122 } 00123 00124 template< typename Token, template <class> class DataStructure > 00125 int StreamImpl<Token,DataStructure>::LogicalSize() const 00126 { 00127 return int(mDataImpl.size()); 00128 } 00129 00130 template< typename Token, template <class> class DataStructure > 00131 bool StreamImpl<Token,DataStructure>::ExistsCircularOverlap(int rear, int writingHead) const 00132 { 00133 return false; 00134 } 00135 00136 //--------------------------------------------------------------------------------- 00137 00138 template< typename Token > 00139 class StreamImpl<Token, PhantomBuffer> 00140 { 00141 00142 public: 00143 void NewWritingRegionSize( Region& writer ); 00144 void NewReadingRegionSize( Region& reader ); 00146 void WriterHasAdvanced( Region& writer ); 00147 void ReaderHasAdvanced( Region& reader ); 00148 00149 Token& Read(int physicalIndex, int size); 00150 Token& operator[](int physicalIndex); 00151 int LogicalSize() const; 00156 int PhantomSize(); 00157 bool ExistsCircularOverlap(int rear, int writingHead) const; 00158 private: 00159 int ExponentOfClosestGreaterPowerOfTwo( int newSize); 00160 void CommonNewRegionSize( Region& anyRegion ); 00161 bool ReaderAffectedByInsertion( Region & reader, Region & writer ) const; 00162 void UpdateBeginDistanceOfReadingRegions( Region & writer, int tokensInserted ); 00163 void RegionHasAdvanced( Region& region ); 00164 00165 PhantomBuffer<Token> mDataImpl; 00166 }; 00167 00169 00170 template< typename Token > 00171 void StreamImpl<Token, PhantomBuffer>::NewWritingRegionSize( Region& writer ) 00172 { 00173 CLAM_DEBUG_ASSERT( writer.Size()>0, "StreamImpl::newWritingRegionSize() - size must be greater than 0" ); 00174 CLAM_DEBUG_ASSERT( !writer.ProducerRegion(), "StreamImpl::newWritingRegionSize() - region must be a WritingRegion" ); 00175 CommonNewRegionSize( writer ); 00176 } 00177 00178 template< typename Token > 00179 void StreamImpl<Token, PhantomBuffer>::NewReadingRegionSize( Region& reader ) 00180 { 00181 CLAM_DEBUG_ASSERT( reader.ProducerRegion(), "StreamImpl::newReadingRegionSize() - region must be a ReadingRegion" ); 00182 CommonNewRegionSize(reader); 00183 } 00184 00185 template< typename Token > 00186 void StreamImpl<Token, PhantomBuffer>::CommonNewRegionSize( Region& anyRegion ) 00187 { 00188 int newLogicalSize; 00189 int newPhantomSize; 00190 00191 if(anyRegion.Size()==1) 00192 { 00193 newLogicalSize = anyRegion.Size(); 00194 newPhantomSize = 0; 00195 } 00196 else 00197 { 00198 int logicalSizeCandidate = anyRegion.Size()*2; 00199 newLogicalSize = 1 << ExponentOfClosestGreaterPowerOfTwo(logicalSizeCandidate); 00200 newPhantomSize = anyRegion.Size()-1; 00201 } 00202 00203 if(newLogicalSize <= LogicalSize()) 00204 return; 00205 00206 CLAM_DEBUG_ASSERT(newLogicalSize > LogicalSize(), "StreamImpl::commonNewRegionSize() - new logical size" 00207 "must be greater than the older logical size" ); 00208 00209 Region & producer = anyRegion.ProducerRegion() ? (*anyRegion.ProducerRegion()) : anyRegion; 00210 int insertionPos = producer.BeginDistance(); 00211 00212 int tokensToInsert = newLogicalSize - LogicalSize(); 00213 00214 mDataImpl.Resize( 00215 newLogicalSize, 00216 std::max(newPhantomSize,PhantomSize()), // phantom buffer size 00217 insertionPos ); 00218 00219 UpdateBeginDistanceOfReadingRegions( producer, tokensToInsert ); 00220 } 00221 00222 template< typename Token > 00223 bool StreamImpl<Token, PhantomBuffer>::ReaderAffectedByInsertion( Region & reader, Region & writer ) const 00224 { 00225 // a reader will be affected by the insertion of new tokens due a writer's resize if: 00226 00227 // a) the reader is physically positioned (beginDistance) at the rear of the writer. 00228 if (reader.BeginDistance() > writer.BeginDistance()) 00229 return true; 00230 00231 // b) the reader is physically positioned (beginDistance) at the same position than the writer AND 00232 // is logically position (pos) after the writer. It means that the writer is exactly at 00233 // LogicalSize() positions before the reader. 00234 if( reader.BeginDistance()==writer.BeginDistance() && reader.Pos() < writer.Pos() ) 00235 return true; 00236 return false; 00237 } 00238 00239 template< typename Token > 00240 void StreamImpl<Token, PhantomBuffer>::UpdateBeginDistanceOfReadingRegions( Region & writer, int tokensInserted ) 00241 { 00244 Region::ReadingRegionsIterator actualReader; 00245 00246 for ( actualReader=writer.BeginReaders(); actualReader!=writer.EndReaders(); actualReader++) 00247 if( ReaderAffectedByInsertion(**actualReader, writer) ) 00248 (*actualReader)->BeginDistance( (*actualReader)->BeginDistance() + tokensInserted ); 00249 } 00250 00251 template< typename Token > 00252 void StreamImpl<Token, PhantomBuffer>::RegionHasAdvanced( Region& region ) 00253 { 00254 region.BeginDistance( region.BeginDistance() + region.Hop()); 00255 if (region.BeginDistance() >= LogicalSize() ) // circular movement 00256 region.BeginDistance( region.BeginDistance() - LogicalSize()); 00257 } 00258 00259 template< typename Token > 00260 void StreamImpl<Token, PhantomBuffer>::WriterHasAdvanced( Region& writer ) 00261 { 00262 mDataImpl.Touch( writer.BeginDistance(), writer.Size() ); 00263 RegionHasAdvanced( writer ); 00264 } 00265 00266 template< typename Token > 00267 void StreamImpl<Token, PhantomBuffer>::ReaderHasAdvanced( Region& reader ) 00268 { 00269 RegionHasAdvanced( reader ); 00270 } 00271 00272 template< typename Token > 00273 Token& StreamImpl<Token, PhantomBuffer>::Read(int physicalIndex, int size) 00274 { 00275 return *mDataImpl.Read( physicalIndex, size ); 00276 } 00277 00278 template< typename Token > 00279 Token& StreamImpl<Token, PhantomBuffer>::operator[](int physicalIndex) 00280 { 00281 CLAM_DEBUG_ASSERT( physicalIndex < LogicalSize()+PhantomSize(), "StreamImpl::operator[] - Index out of bounds" ); 00282 return Read( physicalIndex, 1); 00283 } 00284 00285 template< typename Token > 00286 int StreamImpl<Token, PhantomBuffer>::LogicalSize() const 00287 { 00288 return mDataImpl.LogicalSize(); 00289 } 00290 00291 template< typename Token > 00292 int StreamImpl<Token, PhantomBuffer>::PhantomSize() 00293 { 00294 return mDataImpl.PhantomSize(); 00295 } 00296 00297 template< typename Token > 00298 bool StreamImpl<Token, PhantomBuffer>::ExistsCircularOverlap(int rear, int writingHead) const 00299 { 00300 return writingHead - rear > LogicalSize(); 00301 } 00302 00303 template< typename Token > 00304 int StreamImpl<Token, PhantomBuffer>::ExponentOfClosestGreaterPowerOfTwo( int newSize) 00305 { 00306 int newLogicalSize = 1; 00307 int power = 0; 00308 while( newLogicalSize < newSize ) 00309 { 00310 newLogicalSize <<= 1; 00311 power++; 00312 } 00313 return power; 00314 } 00315 00316 } // namespace CLAM 00317 00318 #endif // StreamImpl_hxx 00319
1.7.6.1