StreamImpl.hxx

Go to the documentation of this file.
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 
Generated by  doxygen 1.6.3