CLAM-Development  1.4.0
StreamImpl.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #ifndef StreamImpl_hxx
23 #define StreamImpl_hxx
24 
25 #include "Region.hxx"
26 #include <list>
27 #include <vector>
28 #include "PhantomBuffer.hxx"
29 namespace CLAM
30 {
31 
33 template <typename T>
34 class StdList : public std::list<T>
35 {};
36 
37 template <typename T>
38 class StdVector : public std::vector<T>
39 {};
40 
41 
42 
43 template< typename Token, template <class> class DataStructure >
45 {
46 
47 public:
48  void NewWritingRegionSize( Region& writer );
51  void WriterHasAdvanced( Region& writer );
52  void ReaderHasAdvanced( Region& reader );
56  Token& Read(int physicalIndex, int size);
57  Token& operator[](int physicalIndex);
58  int LogicalSize() const;
59  bool ExistsCircularOverlap(int rear, int writingHead) const;
60 
61 private:
62  void RegionHasAdvanced( Region& region );
63 
64  DataStructure<Token> mDataImpl;
65 };
66 
68 
69 template< typename Token, template <class> class DataStructure >
71 {
72  if ( writer.Size() <= LogicalSize() ) return;
73  int newTokens = writer.Size() - LogicalSize();
74  for( int i=0; i<newTokens; i++)
75  mDataImpl.push_back(Token());
76 }
77 
78 template< typename Token, template <class> class DataStructure >
80 {
81  region.BeginDistance( region.BeginDistance() + region.Hop() );
82 
83  if (region.BeginDistance() >= LogicalSize() ) // circular movement
84  region.BeginDistance( region.BeginDistance() - LogicalSize() );
85 }
86 
87 template< typename Token, template <class> class DataStructure >
89 {
90 }
91 
92 template< typename Token, template <class> class DataStructure >
94 {
95  for( int i=0; i<writer.Hop(); i++)
96  mDataImpl.push_back(Token());
97 
98  RegionHasAdvanced( writer );
99 }
100 
101 template< typename Token, template <class> class DataStructure >
103 {
104  // TODO: discard old tokens
105  RegionHasAdvanced( reader);
106 }
107 
108 template< typename Token, template <class> class DataStructure >
109 Token& StreamImpl<Token,DataStructure>::Read(int physicalIndex, int size)
110 {
111  return operator[](physicalIndex);
112 }
113 
114 template< typename Token, template <class> class DataStructure >
116 {
117  CLAM_DEBUG_ASSERT( physicalIndex < int(mDataImpl.size()), "StreamImpl operator[] - Index out of bounds" );
118  typename DataStructure<Token>::iterator it;
119  int i;
120  for(i=0, it = mDataImpl.begin(); i<physicalIndex; it++, i++);
121  return (*it);
122 }
123 
124 template< typename Token, template <class> class DataStructure >
126 {
127  return int(mDataImpl.size());
128 }
129 
130 template< typename Token, template <class> class DataStructure >
131 bool StreamImpl<Token,DataStructure>::ExistsCircularOverlap(int rear, int writingHead) const
132 {
133  return false;
134 }
135 
136 //---------------------------------------------------------------------------------
137 
138 template< typename Token >
140 {
141 
142 public:
143  void NewWritingRegionSize( Region& writer );
144  void NewReadingRegionSize( Region& reader );
146  void WriterHasAdvanced( Region& writer );
147  void ReaderHasAdvanced( Region& reader );
148 
149  Token& Read(int physicalIndex, int size);
150  Token& operator[](int physicalIndex);
151  int LogicalSize() const;
156  int PhantomSize();
157  bool ExistsCircularOverlap(int rear, int writingHead) const;
158 private:
159  int ExponentOfClosestGreaterPowerOfTwo( int newSize);
160  void CommonNewRegionSize( Region& anyRegion );
161  bool ReaderAffectedByInsertion( Region & reader, Region & writer ) const;
162  void UpdateBeginDistanceOfReadingRegions( Region & writer, int tokensInserted );
163  void RegionHasAdvanced( Region& region );
164 
165  PhantomBuffer<Token> mDataImpl;
166 };
167 
169 
170 template< typename Token >
172 {
173  CLAM_DEBUG_ASSERT( writer.Size()>0, "StreamImpl::newWritingRegionSize() - size must be greater than 0" );
174  CLAM_DEBUG_ASSERT( !writer.ProducerRegion(), "StreamImpl::newWritingRegionSize() - region must be a WritingRegion" );
175  CommonNewRegionSize( writer );
176 }
177 
178 template< typename Token >
180 {
181  CLAM_DEBUG_ASSERT( reader.ProducerRegion(), "StreamImpl::newReadingRegionSize() - region must be a ReadingRegion" );
182  CommonNewRegionSize(reader);
183 }
184 
185 template< typename Token >
187 {
188  int newLogicalSize;
189  int newPhantomSize;
190 
191  if(anyRegion.Size()==1)
192  {
193  newLogicalSize = anyRegion.Size();
194  newPhantomSize = 0;
195  }
196  else
197  {
198  int logicalSizeCandidate = anyRegion.Size()*2;
199  newLogicalSize = 1 << ExponentOfClosestGreaterPowerOfTwo(logicalSizeCandidate);
200  newPhantomSize = anyRegion.Size()-1;
201  }
202 
203  if(newLogicalSize <= LogicalSize())
204  return;
205 
206  CLAM_DEBUG_ASSERT(newLogicalSize > LogicalSize(), "StreamImpl::commonNewRegionSize() - new logical size"
207  "must be greater than the older logical size" );
208 
209  Region & producer = anyRegion.ProducerRegion() ? (*anyRegion.ProducerRegion()) : anyRegion;
210  int insertionPos = producer.BeginDistance();
211 
212  int tokensToInsert = newLogicalSize - LogicalSize();
213 
214  mDataImpl.Resize(
215  newLogicalSize,
216  std::max(newPhantomSize,PhantomSize()), // phantom buffer size
217  insertionPos );
218 
219  UpdateBeginDistanceOfReadingRegions( producer, tokensToInsert );
220 }
221 
222 template< typename Token >
223 bool StreamImpl<Token, PhantomBuffer>::ReaderAffectedByInsertion( Region & reader, Region & writer ) const
224 {
225  // a reader will be affected by the insertion of new tokens due a writer's resize if:
226 
227  // a) the reader is physically positioned (beginDistance) at the rear of the writer.
228  if (reader.BeginDistance() > writer.BeginDistance())
229  return true;
230 
231  // b) the reader is physically positioned (beginDistance) at the same position than the writer AND
232  // is logically position (pos) after the writer. It means that the writer is exactly at
233  // LogicalSize() positions before the reader.
234  if( reader.BeginDistance()==writer.BeginDistance() && reader.Pos() < writer.Pos() )
235  return true;
236  return false;
237 }
238 
239 template< typename Token >
240 void StreamImpl<Token, PhantomBuffer>::UpdateBeginDistanceOfReadingRegions( Region & writer, int tokensInserted )
241 {
244  Region::ReadingRegionsIterator actualReader;
245 
246  for ( actualReader=writer.BeginReaders(); actualReader!=writer.EndReaders(); actualReader++)
247  if( ReaderAffectedByInsertion(**actualReader, writer) )
248  (*actualReader)->BeginDistance( (*actualReader)->BeginDistance() + tokensInserted );
249 }
250 
251 template< typename Token >
252 void StreamImpl<Token, PhantomBuffer>::RegionHasAdvanced( Region& region )
253 {
254  region.BeginDistance( region.BeginDistance() + region.Hop());
255  if (region.BeginDistance() >= LogicalSize() ) // circular movement
256  region.BeginDistance( region.BeginDistance() - LogicalSize());
257 }
258 
259 template< typename Token >
261 {
262  mDataImpl.Touch( writer.BeginDistance(), writer.Size() );
263  RegionHasAdvanced( writer );
264 }
265 
266 template< typename Token >
268 {
269  RegionHasAdvanced( reader );
270 }
271 
272 template< typename Token >
273 Token& StreamImpl<Token, PhantomBuffer>::Read(int physicalIndex, int size)
274 {
275  return *mDataImpl.Read( physicalIndex, size );
276 }
277 
278 template< typename Token >
280 {
281  CLAM_DEBUG_ASSERT( physicalIndex < LogicalSize()+PhantomSize(), "StreamImpl::operator[] - Index out of bounds" );
282  return Read( physicalIndex, 1);
283 }
284 
285 template< typename Token >
287 {
288  return mDataImpl.LogicalSize();
289 }
290 
291 template< typename Token >
293 {
294  return mDataImpl.PhantomSize();
295 }
296 
297 template< typename Token >
298 bool StreamImpl<Token, PhantomBuffer>::ExistsCircularOverlap(int rear, int writingHead) const
299 {
300  return writingHead - rear > LogicalSize();
301 }
302 
303 template< typename Token >
305 {
306  int newLogicalSize = 1;
307  int power = 0;
308  while( newLogicalSize < newSize )
309  {
310  newLogicalSize <<= 1;
311  power++;
312  }
313  return power;
314 }
315 
316 } // namespace CLAM
317 
318 #endif // StreamImpl_hxx
319