CLAM-Development
1.1
|
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 logicalSizeCandidate = anyRegion.Size()*2; 00189 00190 if(logicalSizeCandidate <= LogicalSize()) 00191 return; 00192 00193 Region & producer = anyRegion.ProducerRegion() ? (*anyRegion.ProducerRegion()) : anyRegion; 00194 int insertionPos = producer.BeginDistance(); 00195 00196 int newLogicalSize = 1 << ExponentOfClosestGreaterPowerOfTwo(logicalSizeCandidate); 00197 00198 CLAM_DEBUG_ASSERT(newLogicalSize > LogicalSize(), "StreamImpl::commonNewRegionSize() - new logical size" 00199 "must be greater than the older logical size" ); 00200 int tokensToInsert = newLogicalSize - LogicalSize(); 00201 00202 mDataImpl.Resize( 00203 newLogicalSize, 00204 anyRegion.Size()*2, // phantom buffer size 00205 insertionPos ); 00206 00207 UpdateBeginDistanceOfReadingRegions( producer, tokensToInsert ); 00208 } 00209 00210 template< typename Token > 00211 bool StreamImpl<Token, PhantomBuffer>::ReaderAffectedByInsertion( Region & reader, Region & writer ) const 00212 { 00213 // a reader will be affected by the insertion of new tokens due a writer's resize if: 00214 00215 // a) the reader is physically positioned (beginDistance) at the rear of the writer. 00216 if (reader.BeginDistance() > writer.BeginDistance()) 00217 return true; 00218 00219 // b) the reader is physically positioned (beginDistance) at the same position than the writer AND 00220 // is logically position (pos) after the writer. It means that the writer is exactly at 00221 // LogicalSize() positions before the reader. 00222 if( reader.BeginDistance()==writer.BeginDistance() && reader.Pos() < writer.Pos() ) 00223 return true; 00224 return false; 00225 } 00226 00227 template< typename Token > 00228 void StreamImpl<Token, PhantomBuffer>::UpdateBeginDistanceOfReadingRegions( Region & writer, int tokensInserted ) 00229 { 00232 Region::ReadingRegionsIterator actualReader; 00233 00234 for ( actualReader=writer.BeginReaders(); actualReader!=writer.EndReaders(); actualReader++) 00235 if( ReaderAffectedByInsertion(**actualReader, writer) ) 00236 (*actualReader)->BeginDistance( (*actualReader)->BeginDistance() + tokensInserted ); 00237 } 00238 00239 template< typename Token > 00240 void StreamImpl<Token, PhantomBuffer>::RegionHasAdvanced( Region& region ) 00241 { 00242 region.BeginDistance( region.BeginDistance() + region.Hop()); 00243 if (region.BeginDistance() >= LogicalSize() ) // circular movement 00244 region.BeginDistance( region.BeginDistance() - LogicalSize()); 00245 } 00246 00247 template< typename Token > 00248 void StreamImpl<Token, PhantomBuffer>::WriterHasAdvanced( Region& writer ) 00249 { 00250 mDataImpl.Touch( writer.BeginDistance(), writer.Size() ); 00251 RegionHasAdvanced( writer ); 00252 } 00253 00254 template< typename Token > 00255 void StreamImpl<Token, PhantomBuffer>::ReaderHasAdvanced( Region& reader ) 00256 { 00257 RegionHasAdvanced( reader ); 00258 } 00259 00260 template< typename Token > 00261 Token& StreamImpl<Token, PhantomBuffer>::Read(int physicalIndex, int size) 00262 { 00263 return *mDataImpl.Read( physicalIndex, size ); 00264 } 00265 00266 template< typename Token > 00267 Token& StreamImpl<Token, PhantomBuffer>::operator[](int physicalIndex) 00268 { 00269 CLAM_DEBUG_ASSERT( physicalIndex < LogicalSize()+PhantomSize(), "StreamImpl::operator[] - Index out of bounds" ); 00270 return Read( physicalIndex, 1); 00271 } 00272 00273 template< typename Token > 00274 int StreamImpl<Token, PhantomBuffer>::LogicalSize() const 00275 { 00276 return mDataImpl.LogicalSize(); 00277 } 00278 00279 template< typename Token > 00280 int StreamImpl<Token, PhantomBuffer>::PhantomSize() 00281 { 00282 return mDataImpl.PhantomSize(); 00283 } 00284 00285 template< typename Token > 00286 bool StreamImpl<Token, PhantomBuffer>::ExistsCircularOverlap(int rear, int writingHead) const 00287 { 00288 return writingHead - rear > LogicalSize(); 00289 } 00290 00291 template< typename Token > 00292 int StreamImpl<Token, PhantomBuffer>::ExponentOfClosestGreaterPowerOfTwo( int newSize) 00293 { 00294 int newLogicalSize = 1; 00295 int power = 0; 00296 while( newLogicalSize < newSize ) 00297 { 00298 newLogicalSize <<= 1; 00299 power++; 00300 } 00301 return power; 00302 } 00303 00304 } // namespace CLAM 00305 00306 #endif // StreamImpl_hxx 00307