CLAM-Development  1.4.0
WritingRegion.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 __WritingRegion_hxx__
23 #define __WritingRegion_hxx__
24 
25 #include "ReadingRegion.hxx"
26 #include "StreamImpl.hxx"
27 
28 #include <iostream> // TODO: remove
29 
30 namespace CLAM
31 {
32 
33 template< typename Token, template <class> class DataStructure = PhantomBuffer>
34 class WritingRegion : public Region
35 {
36 public:
38  typedef Token ProperToken;
40 
41  WritingRegion();
42  virtual ~WritingRegion();
43 
46  void LinkRegions( ProperReadingRegion & reader);
47  void RemoveRegion( Region & region );
48 
53  void CenterEvenRegions();
54 
59 
61  int RearmostReadingPos();
62 
68  bool CanProduce();
69  void Produce();
70 
71  Token& operator[](int offset); // TODO decide if operator[0] is the best option to get the data chunk
72  bool FulfilsInvariant();
73  int LogicalStreamSize();
75 
79  void ClearData();
80 
81 
82  /*
83  * Synchronizes Follower Region and returns last written Tokens
84  */
85  Token & GetLastWrittenData( int offset = 0);
86 private:
88  WritingRegion(const WritingRegion<Token>& original){}
89  void SizeChanged(const int & newSize);
90  int GetGreatestReaderRegionSize();
91 
92  /*
93  * This method checks that all the regions have even size and are located at the correct position (the beginning of the buffer )
94  */
95  void CheckRegionsAreEven();
96  void CenterReadingRegions( int centralIndex );
97 
98  /*
99  * Synchronizes the follower region with the last zone written, with the same size and hop than the writer.
100  */
101  void SyncFollowerRegion();
102 
103  ReadingRegionsList mReadingRegions;
104  ProperStream mStream;
105  ProperReadingRegion mFollowerRegion;
106 };
107 
109 
110 template< typename Token, template <class> class DataStructure>
112 {
113  SizeChanged( Size() );
114 }
115 
116 template< typename Token, template <class> class DataStructure>
118 {
120  for(it=BeginReaders(); it!=EndReaders(); it++)
121  (*it)->RemoveProducer();
122  mReadingRegions.clear();
123 }
124 
125 template< typename Token, template <class> class DataStructure>
127 {
128  return mReadingRegions.begin();
129 }
130 
131 template< typename Token, template <class> class DataStructure>
133 {
134  return mReadingRegions.end();
135 }
136 
137 template< typename Token, template <class> class DataStructure>
139 {
140  mReadingRegions.push_back(&reader);
141  reader.LinkProducerRegion(*this);
142  reader.LinkAndNotifySizeToStream( Stream() );
143 }
144 
145 template< typename Token, template <class> class DataStructure>
147 {
148  int maxSize = 0;
149 
150  ReadingRegionsIterator it;
151  for(it=BeginReaders(); it!=EndReaders(); it++)
152  {
153  if(((*it)->Size())>maxSize)
154  maxSize = (*it)->Size();
155  }
156 
157  return maxSize;
158 }
159 
160 template< typename Token, template <class> class DataStructure>
161 void WritingRegion<Token, DataStructure >::CheckRegionsAreEven()
162 {
163  //TODO: writer must be even?
164  CLAM_ASSERT( Size()%2==0, "WritingRegion::CheckRegionsAreEven - Writer's size must be even for centering." );
165 
166  ReadingRegionsIterator it;
167  for(it=BeginReaders(); it!=EndReaders(); it++)
168  {
169  CLAM_ASSERT( (*it)->Size()%2==0, "WritingRegion::CheckRegionsAreEven - Reader's size must be even for centering.");
170  }
171 
172 }
173 
174 template< typename Token, template <class> class DataStructure>
176 {
177  for( int i=0; i<Size(); i++ )
178  operator[](i) = Token();
179 }
180 
181 template< typename Token, template <class> class DataStructure>
183 {
184  ReadingRegionsIterator it;
185  for(it=BeginReaders(); it!=EndReaders(); it++)
186  {
187  int hopToMove = centralIndex - (*it)->Size()/2;
188  (*it)->Pos( hopToMove );
189  (*it)->BeginDistance( hopToMove );
190  }
191 }
192 
193 template< typename Token, template <class> class DataStructure>
195 {
196  CheckRegionsAreEven();
197  int centralIndex = GetGreatestReaderRegionSize()/2;
198 
199  Pos( 0 );
200  BeginDistance( 0);
201 
202  int currentHop = Hop();
203  int currentSize = Size();
204 
205  Size( centralIndex);
206  Hop( centralIndex );
207 
208  ClearData();
209 
210 
211  CenterReadingRegions( centralIndex );
212 
213  Produce();
214  Size( currentSize );
215  Hop( currentHop );
216 
217 
218 
219 }
220 
221 template< typename Token, template <class> class DataStructure>
223 {
224  CLAM_ASSERT( region.ProducerRegion()==this, "Region::RemoveRegion() - Trying to remove an unlinked region");
225 
226  mReadingRegions.remove( &region );
227  region.RemoveProducer();
228 }
229 
230 template< typename Token, template <class> class DataStructure>
232 {
233  return mStream;
234 }
235 
236 template< typename Token, template <class> class DataStructure>
238 {
239  int result = Pos();
241  for(it=mReadingRegions.begin(); it!=mReadingRegions.end(); it++)
242  if( (*it)->Pos() < result) result = (*it)->Pos();
243 
244  return result;
245 }
246 
247 template< typename Token, template <class> class DataStructure>
249 {
250  CLAM_DEBUG_ASSERT( FulfilsInvariant(), "WritingRegion::canProduce() - fulfils invariant checking failed" );
251  return !mStream.ExistsCircularOverlap( RearmostReadingPos(), Pos()+Size() );
252 }
253 
254 template< typename Token, template <class> class DataStructure>
256 {
257  CLAM_DEBUG_ASSERT( CanProduce(), "WritingRegion::produce() - WritingRegion can't produce" );
258  Pos( Pos() + Hop());
259  // reserve stream tokens for next position
260  mStream.WriterHasAdvanced( *this );
261 }
262 
263 template< typename Token, template <class> class DataStructure>
265 {
266 
267  CLAM_DEBUG_ASSERT(0 <= offset && offset < Size(), "WritingRegion::operator [] - Index out of bounds" );
268  int physicalIndex = BeginDistance() + offset;
269 
270  if (offset==0)
271  return mStream.Read(physicalIndex, Size());
272  return mStream[physicalIndex];
273 }
274 
275 template< typename Token, template <class> class DataStructure>
277 {
279  for(it=mReadingRegions.begin(); it!=mReadingRegions.end(); it++)
280  if( (*it)->Pos() >= Pos()+Size() )
281  return false;
282  return true;
283 }
284 
285 template< typename Token, template <class> class DataStructure>
287 {
288  return mStream.LogicalSize();
289 }
290 
291 template< typename Token, template <class> class DataStructure>
293 {
294  return 0;
295 }
296 
297 template< typename Token, template <class> class DataStructure>
299 {
300  mStream.NewWritingRegionSize( *this );
301 }
302 
303 template< typename Token, template <class> class DataStructure>
304 void WritingRegion< Token, DataStructure >::SyncFollowerRegion()
305 {
306  mFollowerRegion.LinkProducerRegion(*this);
307  mFollowerRegion.Size( Size() );
308  mFollowerRegion.Hop( Hop() );
309  mFollowerRegion.LinkAndNotifySizeToStream( Stream() );
310 
311  mFollowerRegion.Pos( Pos() - Hop() );
312  mFollowerRegion.BeginDistance( BeginDistance() - Hop() );
313  if(mFollowerRegion.BeginDistance() < 0 )
314  mFollowerRegion.BeginDistance( mFollowerRegion.BeginDistance() + mStream.LogicalSize() );
315 }
316 
317 template< typename Token, template <class> class DataStructure>
319 {
320  SyncFollowerRegion();
321  int physicalIndex = mFollowerRegion.BeginDistance() + offset;
322 // CLAM_ASSERT( physicalIndex < mStream.LogicalSize(), "WritingRegion GetLastWrittenData - Out of bounds access" );
323  return mStream.operator[]( physicalIndex );
324 }
325 
326 } // namespace CLAM
327 
328 #endif // __WritingRegion_hxx__
329