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 __WritingRegion_hxx__ 00023 #define __WritingRegion_hxx__ 00024 00025 #include "ReadingRegion.hxx" 00026 #include "StreamImpl.hxx" 00027 00028 #include <iostream> // TODO: remove 00029 00030 namespace CLAM 00031 { 00032 00033 template< typename Token, template <class> class DataStructure = PhantomBuffer> 00034 class WritingRegion : public Region 00035 { 00036 public: 00037 typedef StreamImpl< Token, DataStructure > ProperStream; 00038 typedef Token ProperToken; 00039 typedef ReadingRegion< WritingRegion<Token,DataStructure> > ProperReadingRegion; 00040 00041 WritingRegion(); 00042 virtual ~WritingRegion(); 00043 00044 Region::ReadingRegionsIterator BeginReaders(); 00045 Region::ReadingRegionsIterator EndReaders(); 00046 void LinkRegions( ProperReadingRegion & reader); 00047 void RemoveRegion( Region & region ); 00048 00053 void CenterEvenRegions(); 00054 00058 ProperStream& Stream(); 00059 00061 int RearmostReadingPos(); 00062 00068 bool CanProduce(); 00069 void Produce(); 00070 00071 Token& operator[](int offset); // TODO decide if operator[0] is the best option to get the data chunk 00072 bool FulfilsInvariant(); 00073 int LogicalStreamSize(); 00074 Region* ProducerRegion(); 00075 00079 void ClearData(); 00080 00081 00082 /* 00083 * Synchronizes Follower Region and returns last written Tokens 00084 */ 00085 Token & GetLastWrittenData( int offset = 0); 00086 private: 00088 WritingRegion(const WritingRegion<Token>& original){} 00089 void SizeChanged(const int & newSize); 00090 int GetGreatestReaderRegionSize(); 00091 00092 /* 00093 * This method checks that all the regions have even size and are located at the correct position (the beginning of the buffer ) 00094 */ 00095 void CheckRegionsAreEven(); 00096 void CenterReadingRegions( int centralIndex ); 00097 00098 /* 00099 * Synchronizes the follower region with the last zone written, with the same size and hop than the writer. 00100 */ 00101 void SyncFollowerRegion(); 00102 00103 ReadingRegionsList mReadingRegions; 00104 ProperStream mStream; 00105 ProperReadingRegion mFollowerRegion; 00106 }; 00107 00109 00110 template< typename Token, template <class> class DataStructure> 00111 WritingRegion< Token, DataStructure >::WritingRegion() 00112 { 00113 SizeChanged( Size() ); 00114 } 00115 00116 template< typename Token, template <class> class DataStructure> 00117 WritingRegion< Token, DataStructure >::~WritingRegion() 00118 { 00119 ReadingRegionsIterator it; 00120 for(it=BeginReaders(); it!=EndReaders(); it++) 00121 (*it)->RemoveProducer(); 00122 mReadingRegions.clear(); 00123 } 00124 00125 template< typename Token, template <class> class DataStructure> 00126 Region::ReadingRegionsIterator WritingRegion< Token, DataStructure >::BeginReaders() 00127 { 00128 return mReadingRegions.begin(); 00129 } 00130 00131 template< typename Token, template <class> class DataStructure> 00132 Region::ReadingRegionsIterator WritingRegion< Token, DataStructure >::EndReaders() 00133 { 00134 return mReadingRegions.end(); 00135 } 00136 00137 template< typename Token, template <class> class DataStructure> 00138 void WritingRegion< Token, DataStructure >::LinkRegions( ProperReadingRegion & reader) 00139 { 00140 mReadingRegions.push_back(&reader); 00141 reader.LinkProducerRegion(*this); 00142 reader.LinkAndNotifySizeToStream( Stream() ); 00143 } 00144 00145 template< typename Token, template <class> class DataStructure> 00146 int WritingRegion< Token, DataStructure >::GetGreatestReaderRegionSize() 00147 { 00148 int maxSize = 0; 00149 00150 ReadingRegionsIterator it; 00151 for(it=BeginReaders(); it!=EndReaders(); it++) 00152 { 00153 if(((*it)->Size())>maxSize) 00154 maxSize = (*it)->Size(); 00155 } 00156 00157 return maxSize; 00158 } 00159 00160 template< typename Token, template <class> class DataStructure> 00161 void WritingRegion<Token, DataStructure >::CheckRegionsAreEven() 00162 { 00163 //TODO: writer must be even? 00164 CLAM_ASSERT( Size()%2==0, "WritingRegion::CheckRegionsAreEven - Writer's size must be even for centering." ); 00165 00166 ReadingRegionsIterator it; 00167 for(it=BeginReaders(); it!=EndReaders(); it++) 00168 { 00169 CLAM_ASSERT( (*it)->Size()%2==0, "WritingRegion::CheckRegionsAreEven - Reader's size must be even for centering."); 00170 } 00171 00172 } 00173 00174 template< typename Token, template <class> class DataStructure> 00175 void WritingRegion< Token, DataStructure >::ClearData() 00176 { 00177 for( int i=0; i<Size(); i++ ) 00178 operator[](i) = Token(); 00179 } 00180 00181 template< typename Token, template <class> class DataStructure> 00182 void WritingRegion< Token, DataStructure >::CenterReadingRegions( int centralIndex ) 00183 { 00184 ReadingRegionsIterator it; 00185 for(it=BeginReaders(); it!=EndReaders(); it++) 00186 { 00187 int hopToMove = centralIndex - (*it)->Size()/2; 00188 (*it)->Pos( hopToMove ); 00189 (*it)->BeginDistance( hopToMove ); 00190 } 00191 } 00192 00193 template< typename Token, template <class> class DataStructure> 00194 void WritingRegion< Token, DataStructure >::CenterEvenRegions() 00195 { 00196 CheckRegionsAreEven(); 00197 int centralIndex = GetGreatestReaderRegionSize()/2; 00198 00199 Pos( 0 ); 00200 BeginDistance( 0); 00201 00202 int currentHop = Hop(); 00203 int currentSize = Size(); 00204 00205 Size( centralIndex); 00206 Hop( centralIndex ); 00207 00208 ClearData(); 00209 00210 00211 CenterReadingRegions( centralIndex ); 00212 00213 Produce(); 00214 Size( currentSize ); 00215 Hop( currentHop ); 00216 00217 00218 00219 } 00220 00221 template< typename Token, template <class> class DataStructure> 00222 void WritingRegion< Token, DataStructure >::RemoveRegion( Region & region ) 00223 { 00224 CLAM_ASSERT( region.ProducerRegion()==this, "Region::RemoveRegion() - Trying to remove an unlinked region"); 00225 00226 mReadingRegions.remove( ®ion ); 00227 region.RemoveProducer(); 00228 } 00229 00230 template< typename Token, template <class> class DataStructure> 00231 typename WritingRegion< Token, DataStructure>::ProperStream& WritingRegion< Token, DataStructure >::Stream() 00232 { 00233 return mStream; 00234 } 00235 00236 template< typename Token, template <class> class DataStructure> 00237 int WritingRegion< Token, DataStructure >::RearmostReadingPos() 00238 { 00239 int result = Pos(); 00240 ReadingRegionsIterator it; 00241 for(it=mReadingRegions.begin(); it!=mReadingRegions.end(); it++) 00242 if( (*it)->Pos() < result) result = (*it)->Pos(); 00243 00244 return result; 00245 } 00246 00247 template< typename Token, template <class> class DataStructure> 00248 bool WritingRegion< Token, DataStructure >::CanProduce() 00249 { 00250 CLAM_DEBUG_ASSERT( FulfilsInvariant(), "WritingRegion::canProduce() - fulfils invariant checking failed" ); 00251 return !mStream.ExistsCircularOverlap( RearmostReadingPos(), Pos()+Size() ); 00252 } 00253 00254 template< typename Token, template <class> class DataStructure> 00255 void WritingRegion< Token, DataStructure >::Produce() 00256 { 00257 CLAM_DEBUG_ASSERT( CanProduce(), "WritingRegion::produce() - WritingRegion can't produce" ); 00258 Pos( Pos() + Hop()); 00259 // reserve stream tokens for next position 00260 mStream.WriterHasAdvanced( *this ); 00261 } 00262 00263 template< typename Token, template <class> class DataStructure> 00264 Token& WritingRegion< Token, DataStructure >::operator[](int offset) 00265 { 00266 00267 CLAM_DEBUG_ASSERT(0 <= offset && offset < Size(), "WritingRegion::operator [] - Index out of bounds" ); 00268 int physicalIndex = BeginDistance() + offset; 00269 00270 if (offset==0) 00271 return mStream.Read(physicalIndex, Size()); 00272 return mStream[physicalIndex]; 00273 } 00274 00275 template< typename Token, template <class> class DataStructure> 00276 bool WritingRegion< Token, DataStructure >::FulfilsInvariant() 00277 { 00278 ReadingRegionsIterator it; 00279 for(it=mReadingRegions.begin(); it!=mReadingRegions.end(); it++) 00280 if( (*it)->Pos() >= Pos()+Size() ) 00281 return false; 00282 return true; 00283 } 00284 00285 template< typename Token, template <class> class DataStructure> 00286 int WritingRegion< Token, DataStructure >::LogicalStreamSize() 00287 { 00288 return mStream.LogicalSize(); 00289 } 00290 00291 template< typename Token, template <class> class DataStructure> 00292 Region* WritingRegion< Token, DataStructure >::ProducerRegion() 00293 { 00294 return 0; 00295 } 00296 00297 template< typename Token, template <class> class DataStructure> 00298 void WritingRegion< Token, DataStructure >::SizeChanged(const int & newSize) 00299 { 00300 mStream.NewWritingRegionSize( *this ); 00301 } 00302 00303 template< typename Token, template <class> class DataStructure> 00304 void WritingRegion< Token, DataStructure >::SyncFollowerRegion() 00305 { 00306 mFollowerRegion.LinkProducerRegion(*this); 00307 mFollowerRegion.Size( Size() ); 00308 mFollowerRegion.Hop( Hop() ); 00309 mFollowerRegion.LinkAndNotifySizeToStream( Stream() ); 00310 00311 mFollowerRegion.Pos( Pos() - Hop() ); 00312 mFollowerRegion.BeginDistance( BeginDistance() - Hop() ); 00313 if(mFollowerRegion.BeginDistance() < 0 ) 00314 mFollowerRegion.BeginDistance( mFollowerRegion.BeginDistance() + mStream.LogicalSize() ); 00315 } 00316 00317 template< typename Token, template <class> class DataStructure> 00318 Token & WritingRegion< Token, DataStructure >::GetLastWrittenData( int offset) 00319 { 00320 SyncFollowerRegion(); 00321 int physicalIndex = mFollowerRegion.BeginDistance() + offset; 00322 // CLAM_ASSERT( physicalIndex < mStream.LogicalSize(), "WritingRegion GetLastWrittenData - Out of bounds access" ); 00323 return mStream.operator[]( physicalIndex ); 00324 } 00325 00326 } // namespace CLAM 00327 00328 #endif // __WritingRegion_hxx__ 00329