QRSS Rx Network receiver. A receiver to sample a segment of RF spectrum and send this data to a server for further processing and display. NXP mbed Design Challenge entry (Honorable Mention). Published in Circuit Cellar, Feb 2012

Dependencies:   NetServices mbed DNSResolver

Committer:
claytong
Date:
Wed Jan 25 20:32:53 2012 +0000
Revision:
0:82ff15078322
1.0 (initial public release)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
claytong 0:82ff15078322 1 /*---------------------------------------------------------------------------
claytong 0:82ff15078322 2
claytong 0:82ff15078322 3 QRSS Receiver Application
claytong 0:82ff15078322 4
claytong 0:82ff15078322 5 by Clayton ZL3TKA/VK1TKA
claytong 0:82ff15078322 6 clayton@isnotcrazy.com
claytong 0:82ff15078322 7
claytong 0:82ff15078322 8 Header File for Buffer System
claytong 0:82ff15078322 9 Designed to buffer 32 bit I/Q samples
claytong 0:82ff15078322 10
claytong 0:82ff15078322 11 ---------------------------------------------------------------------------*/
claytong 0:82ff15078322 12 #ifndef _BUFFERSYS_H
claytong 0:82ff15078322 13 #define _BUFFERSYS_H
claytong 0:82ff15078322 14
claytong 0:82ff15078322 15 #include "mbed.h"
claytong 0:82ff15078322 16 #include "global.h"
claytong 0:82ff15078322 17
claytong 0:82ff15078322 18 // Definitions
claytong 0:82ff15078322 19
claytong 0:82ff15078322 20 #ifndef BUFFERSYS_SIZE
claytong 0:82ff15078322 21 #define BUFFERSYS_SIZE 512
claytong 0:82ff15078322 22 #endif
claytong 0:82ff15078322 23
claytong 0:82ff15078322 24 //
claytong 0:82ff15078322 25 // Structures
claytong 0:82ff15078322 26 //
claytong 0:82ff15078322 27
claytong 0:82ff15078322 28 //---------------------------------------------------------------------------
claytong 0:82ff15078322 29 //
claytong 0:82ff15078322 30 // A Sample structure
claytong 0:82ff15078322 31 // The single data sample point
claytong 0:82ff15078322 32 //
claytong 0:82ff15078322 33 typedef struct _data_sample
claytong 0:82ff15078322 34 {
claytong 0:82ff15078322 35 int32_t iQData;
claytong 0:82ff15078322 36 int32_t iIData;
claytong 0:82ff15078322 37 } TDataSample;
claytong 0:82ff15078322 38
claytong 0:82ff15078322 39 // Long samples - more bit sizes
claytong 0:82ff15078322 40 // Not used by the buffers, but available for other parts in the system
claytong 0:82ff15078322 41 typedef struct _long_data_sample
claytong 0:82ff15078322 42 {
claytong 0:82ff15078322 43 int64_t iQData;
claytong 0:82ff15078322 44 int64_t iIData;
claytong 0:82ff15078322 45 } TLongDataSample;
claytong 0:82ff15078322 46
claytong 0:82ff15078322 47 extern const TDataSample NullSample;
claytong 0:82ff15078322 48
claytong 0:82ff15078322 49 //
claytong 0:82ff15078322 50 // Classes
claytong 0:82ff15078322 51 //
claytong 0:82ff15078322 52
claytong 0:82ff15078322 53 // Forward references
claytong 0:82ff15078322 54 class TBufferPool;
claytong 0:82ff15078322 55
claytong 0:82ff15078322 56 //---------------------------------------------------------------------------
claytong 0:82ff15078322 57 //
claytong 0:82ff15078322 58 // A Buffer Data Class
claytong 0:82ff15078322 59 // The actual thing that holds the sample data
claytong 0:82ff15078322 60 //
claytong 0:82ff15078322 61 class TBufferData
claytong 0:82ff15078322 62 {
claytong 0:82ff15078322 63 // create/destroy
claytong 0:82ff15078322 64 public:
claytong 0:82ff15078322 65 // creates the buffer
claytong 0:82ff15078322 66 TBufferData() :
claytong 0:82ff15078322 67 iLength(0),
claytong 0:82ff15078322 68 pNext(NULL),
claytong 0:82ff15078322 69 iRefCount(0),
claytong 0:82ff15078322 70 pPool(NULL)
claytong 0:82ff15078322 71 {}
claytong 0:82ff15078322 72 // delete the buffer
claytong 0:82ff15078322 73 ~TBufferData()
claytong 0:82ff15078322 74 {}
claytong 0:82ff15078322 75
claytong 0:82ff15078322 76 // API
claytong 0:82ff15078322 77 public:
claytong 0:82ff15078322 78
claytong 0:82ff15078322 79 // Check the reference count
claytong 0:82ff15078322 80 // Any operation that changes a buffer's data (or provides a write pointer) MUST check
claytong 0:82ff15078322 81 // iRefCount and throw exception if not = 1
claytong 0:82ff15078322 82 inline void CheckRefCount( void ) const
claytong 0:82ff15078322 83 {
claytong 0:82ff15078322 84 if ( iRefCount != 1 )
claytong 0:82ff15078322 85 error( "TBufferData::CheckRefCount RefCount not equal to 1\r\n" );
claytong 0:82ff15078322 86 }
claytong 0:82ff15078322 87
claytong 0:82ff15078322 88 // Clear the buffer
claytong 0:82ff15078322 89 void Clear( void )
claytong 0:82ff15078322 90 {
claytong 0:82ff15078322 91 iLength = 0;
claytong 0:82ff15078322 92 }
claytong 0:82ff15078322 93
claytong 0:82ff15078322 94 // Append a sample
claytong 0:82ff15078322 95 bool Append( const TDataSample *pSample )
claytong 0:82ff15078322 96 {
claytong 0:82ff15078322 97 CheckRefCount();
claytong 0:82ff15078322 98 // Check for overflows
claytong 0:82ff15078322 99 if ( iLength>=BUFFERSYS_SIZE )
claytong 0:82ff15078322 100 return false; // no room
claytong 0:82ff15078322 101 // Append the data
claytong 0:82ff15078322 102 asSamples[iLength] = *pSample;
claytong 0:82ff15078322 103 iLength ++;
claytong 0:82ff15078322 104 return true;
claytong 0:82ff15078322 105 }
claytong 0:82ff15078322 106
claytong 0:82ff15078322 107 // Remove samples form the end of the buffer
claytong 0:82ff15078322 108 // Fails if there are not enough samples to remove
claytong 0:82ff15078322 109 bool Remove( int iSamples )
claytong 0:82ff15078322 110 {
claytong 0:82ff15078322 111 CheckRefCount();
claytong 0:82ff15078322 112 if ( iSamples<0 )
claytong 0:82ff15078322 113 error( "TBufferData::Remove Invalid remove number\r\n" );
claytong 0:82ff15078322 114 // Check for underflow
claytong 0:82ff15078322 115 if ( iLength<iSamples )
claytong 0:82ff15078322 116 { // underflow - remove all anyway
claytong 0:82ff15078322 117 iLength = 0;
claytong 0:82ff15078322 118 return false;
claytong 0:82ff15078322 119 }
claytong 0:82ff15078322 120 // adjust the length
claytong 0:82ff15078322 121 iLength -= iSamples;
claytong 0:82ff15078322 122 return true;
claytong 0:82ff15078322 123 }
claytong 0:82ff15078322 124
claytong 0:82ff15078322 125 // data
claytong 0:82ff15078322 126 private:
claytong 0:82ff15078322 127
claytong 0:82ff15078322 128 // the buffer
claytong 0:82ff15078322 129 TDataSample asSamples[BUFFERSYS_SIZE];
claytong 0:82ff15078322 130
claytong 0:82ff15078322 131 // data size count
claytong 0:82ff15078322 132 int iLength; // current samples count
claytong 0:82ff15078322 133
claytong 0:82ff15078322 134 // a pointer for queuing
claytong 0:82ff15078322 135 TBufferData *pNext;
claytong 0:82ff15078322 136
claytong 0:82ff15078322 137 // a reference counter for counting holders of this buffer
claytong 0:82ff15078322 138 int iRefCount;
claytong 0:82ff15078322 139
claytong 0:82ff15078322 140 // a timestamp of the sample capture
claytong 0:82ff15078322 141 uint32_t uiTimestamp;
claytong 0:82ff15078322 142
claytong 0:82ff15078322 143 // a pointer to this buffers pool (to return it too)
claytong 0:82ff15078322 144 TBufferPool *pPool; // the pool that the buffer came from
claytong 0:82ff15078322 145
claytong 0:82ff15078322 146 #ifdef BUFFER_DEBUG
claytong 0:82ff15078322 147 // details of buffer ownership (for debugging only)
claytong 0:82ff15078322 148 bool bQueued; // the buffer is in a queue
claytong 0:82ff15078322 149 bool bPooled; // the buffer is in a pool (unused buffer)
claytong 0:82ff15078322 150 #endif
claytong 0:82ff15078322 151
claytong 0:82ff15078322 152 //Declare the buffer classes as friendly
claytong 0:82ff15078322 153 //so it can access the protected members of buffers.
claytong 0:82ff15078322 154 friend class TBufferHandle;
claytong 0:82ff15078322 155 friend class TBufferQueue;
claytong 0:82ff15078322 156 friend class TBufferPool;
claytong 0:82ff15078322 157
claytong 0:82ff15078322 158
claytong 0:82ff15078322 159 };
claytong 0:82ff15078322 160
claytong 0:82ff15078322 161 //---------------------------------------------------------------------------
claytong 0:82ff15078322 162 //
claytong 0:82ff15078322 163 // A Buffer Handle Class
claytong 0:82ff15078322 164 // Something that holds a buffer
claytong 0:82ff15078322 165 // Can also be the base class for something that processes a buffer
claytong 0:82ff15078322 166 //
claytong 0:82ff15078322 167 class TBufferHandle
claytong 0:82ff15078322 168 {
claytong 0:82ff15078322 169 // create/destroy
claytong 0:82ff15078322 170 public:
claytong 0:82ff15078322 171 TBufferHandle() :
claytong 0:82ff15078322 172 pMyBuffer( NULL )
claytong 0:82ff15078322 173 {}
claytong 0:82ff15078322 174
claytong 0:82ff15078322 175 virtual ~TBufferHandle()
claytong 0:82ff15078322 176 { // release any attached buffer
claytong 0:82ff15078322 177 Release();
claytong 0:82ff15078322 178 }
claytong 0:82ff15078322 179
claytong 0:82ff15078322 180 // buffer attached/release
claytong 0:82ff15078322 181 public:
claytong 0:82ff15078322 182 // test if the handle has a buffer attached
claytong 0:82ff15078322 183 inline bool HasBuffer( void ) const
claytong 0:82ff15078322 184 {
claytong 0:82ff15078322 185 if ( pMyBuffer != NULL )
claytong 0:82ff15078322 186 return true;
claytong 0:82ff15078322 187 return false;
claytong 0:82ff15078322 188 }
claytong 0:82ff15078322 189
claytong 0:82ff15078322 190 protected:
claytong 0:82ff15078322 191 // attached a buffer to the handle
claytong 0:82ff15078322 192 bool Attach( TBufferData * pBuffer )
claytong 0:82ff15078322 193 {
claytong 0:82ff15078322 194 // release any old buffer
claytong 0:82ff15078322 195 Release();
claytong 0:82ff15078322 196
claytong 0:82ff15078322 197 // Attach the buffer to the handler
claytong 0:82ff15078322 198 if ( pBuffer != NULL )
claytong 0:82ff15078322 199 {
claytong 0:82ff15078322 200 pMyBuffer = pBuffer;
claytong 0:82ff15078322 201 // Increment the reference count of the buffer
claytong 0:82ff15078322 202 pMyBuffer->iRefCount++;
claytong 0:82ff15078322 203 return true;
claytong 0:82ff15078322 204 }
claytong 0:82ff15078322 205 return false;
claytong 0:82ff15078322 206 }
claytong 0:82ff15078322 207 // debug - check that a buffer is attached
claytong 0:82ff15078322 208 inline void CheckForBuffer( void ) const
claytong 0:82ff15078322 209 {
claytong 0:82ff15078322 210 if ( pMyBuffer == NULL )
claytong 0:82ff15078322 211 error( "TBufferHandle::CheckForBuffer Handle does not have a buffer attached\r\n" );
claytong 0:82ff15078322 212 }
claytong 0:82ff15078322 213
claytong 0:82ff15078322 214 public:
claytong 0:82ff15078322 215 // transfer a buffer from another handle
claytong 0:82ff15078322 216 bool TransferBuffer( TBufferHandle & Handle )
claytong 0:82ff15078322 217 {
claytong 0:82ff15078322 218 // attach buffer from other handle
claytong 0:82ff15078322 219 if ( !Attach(Handle.pMyBuffer) )
claytong 0:82ff15078322 220 return false;
claytong 0:82ff15078322 221 // release buffer from the other handle
claytong 0:82ff15078322 222 Handle.Release();
claytong 0:82ff15078322 223 return true;
claytong 0:82ff15078322 224 }
claytong 0:82ff15078322 225
claytong 0:82ff15078322 226 // release the buffer from the handle
claytong 0:82ff15078322 227 void Release( void );
claytong 0:82ff15078322 228
claytong 0:82ff15078322 229 // Set the timestamp
claytong 0:82ff15078322 230 void Timestamp( uint32_t uiTime )
claytong 0:82ff15078322 231 {
claytong 0:82ff15078322 232 if ( HasBuffer() )
claytong 0:82ff15078322 233 pMyBuffer->uiTimestamp = uiTime;
claytong 0:82ff15078322 234 }
claytong 0:82ff15078322 235
claytong 0:82ff15078322 236 // Read the timestamp
claytong 0:82ff15078322 237 uint32_t Timestamp()
claytong 0:82ff15078322 238 {
claytong 0:82ff15078322 239 if ( HasBuffer() )
claytong 0:82ff15078322 240 return pMyBuffer->uiTimestamp;
claytong 0:82ff15078322 241 return 0;
claytong 0:82ff15078322 242 }
claytong 0:82ff15078322 243
claytong 0:82ff15078322 244 // buffer manipulation
claytong 0:82ff15078322 245 public:
claytong 0:82ff15078322 246 // append a sample
claytong 0:82ff15078322 247 bool Append( const TDataSample &Sample )
claytong 0:82ff15078322 248 {
claytong 0:82ff15078322 249 CheckForBuffer();
claytong 0:82ff15078322 250 return pMyBuffer->Append( &Sample );
claytong 0:82ff15078322 251 }
claytong 0:82ff15078322 252
claytong 0:82ff15078322 253 // Remove characters form the end of the buffer
claytong 0:82ff15078322 254 // Fails if there are not enough bytes to remove
claytong 0:82ff15078322 255 bool Remove( int iBytes )
claytong 0:82ff15078322 256 {
claytong 0:82ff15078322 257 CheckForBuffer();
claytong 0:82ff15078322 258 return pMyBuffer->Remove( iBytes );
claytong 0:82ff15078322 259 }
claytong 0:82ff15078322 260
claytong 0:82ff15078322 261 // Clear the buffer
claytong 0:82ff15078322 262 void Clear( void )
claytong 0:82ff15078322 263 {
claytong 0:82ff15078322 264 CheckForBuffer();
claytong 0:82ff15078322 265 pMyBuffer->Clear();
claytong 0:82ff15078322 266 }
claytong 0:82ff15078322 267
claytong 0:82ff15078322 268 // set buffer length (after data has been manually added)
claytong 0:82ff15078322 269 void SetLength( int iLen )
claytong 0:82ff15078322 270 {
claytong 0:82ff15078322 271 if ( HasBuffer() )
claytong 0:82ff15078322 272 {
claytong 0:82ff15078322 273 if ( iLen<0 )
claytong 0:82ff15078322 274 iLen = 0;
claytong 0:82ff15078322 275 if ( iLen>BUFFERSYS_SIZE )
claytong 0:82ff15078322 276 iLen = BUFFERSYS_SIZE;
claytong 0:82ff15078322 277 pMyBuffer->iLength = iLen;
claytong 0:82ff15078322 278 }
claytong 0:82ff15078322 279 }
claytong 0:82ff15078322 280
claytong 0:82ff15078322 281 // buffer examination
claytong 0:82ff15078322 282 public:
claytong 0:82ff15078322 283 // get buffer length
claytong 0:82ff15078322 284 int Length( void ) const
claytong 0:82ff15078322 285 {
claytong 0:82ff15078322 286 if ( !HasBuffer() )
claytong 0:82ff15078322 287 return 0;
claytong 0:82ff15078322 288 return pMyBuffer->iLength;
claytong 0:82ff15078322 289 }
claytong 0:82ff15078322 290
claytong 0:82ff15078322 291 // get buffer size
claytong 0:82ff15078322 292 int Size( void ) const
claytong 0:82ff15078322 293 {
claytong 0:82ff15078322 294 if ( !HasBuffer() )
claytong 0:82ff15078322 295 return 0;
claytong 0:82ff15078322 296 return BUFFERSYS_SIZE;
claytong 0:82ff15078322 297 }
claytong 0:82ff15078322 298
claytong 0:82ff15078322 299 int Room( void ) const
claytong 0:82ff15078322 300 {
claytong 0:82ff15078322 301 if ( !HasBuffer() )
claytong 0:82ff15078322 302 return 0;
claytong 0:82ff15078322 303 return ( BUFFERSYS_SIZE - pMyBuffer->iLength );
claytong 0:82ff15078322 304 }
claytong 0:82ff15078322 305
claytong 0:82ff15078322 306 // get a pointer to the buffer data
claytong 0:82ff15078322 307 TDataSample * SamplePtr( int iIndex=0 )
claytong 0:82ff15078322 308 {
claytong 0:82ff15078322 309 if ( !HasBuffer() )
claytong 0:82ff15078322 310 return NULL; // no buffer
claytong 0:82ff15078322 311 if ( iIndex>pMyBuffer->iLength )
claytong 0:82ff15078322 312 return NULL; // index past end of buffer
claytong 0:82ff15078322 313 return &(pMyBuffer->asSamples[iIndex]);
claytong 0:82ff15078322 314 }
claytong 0:82ff15078322 315 // get buffer data (note that there is no way to detect failure)
claytong 0:82ff15078322 316 const TDataSample operator []( int iIndex ) const
claytong 0:82ff15078322 317 {
claytong 0:82ff15078322 318 if ( HasBuffer() && (iIndex<pMyBuffer->iLength) && (iIndex>=0) )
claytong 0:82ff15078322 319 return pMyBuffer->asSamples[iIndex];
claytong 0:82ff15078322 320 return NullSample; // otherwise return empty sample
claytong 0:82ff15078322 321 }
claytong 0:82ff15078322 322
claytong 0:82ff15078322 323 // data
claytong 0:82ff15078322 324 protected:
claytong 0:82ff15078322 325 // pointer to the buffer being references to
claytong 0:82ff15078322 326 TBufferData *pMyBuffer;
claytong 0:82ff15078322 327
claytong 0:82ff15078322 328 friend class TBufferQueue;
claytong 0:82ff15078322 329 friend class TBufferPool;
claytong 0:82ff15078322 330 };
claytong 0:82ff15078322 331
claytong 0:82ff15078322 332 //---------------------------------------------------------------------------
claytong 0:82ff15078322 333 //
claytong 0:82ff15078322 334 // A Buffer Queue
claytong 0:82ff15078322 335 // A queue of buffers
claytong 0:82ff15078322 336 //
claytong 0:82ff15078322 337 class TBufferQueue
claytong 0:82ff15078322 338 {
claytong 0:82ff15078322 339 // create/destroy
claytong 0:82ff15078322 340 public:
claytong 0:82ff15078322 341 TBufferQueue() :
claytong 0:82ff15078322 342 pFront(NULL),
claytong 0:82ff15078322 343 pBack(NULL),
claytong 0:82ff15078322 344 iCount(0)
claytong 0:82ff15078322 345 {}
claytong 0:82ff15078322 346
claytong 0:82ff15078322 347 virtual ~TBufferQueue()
claytong 0:82ff15078322 348 {
claytong 0:82ff15078322 349 // release all buffer
claytong 0:82ff15078322 350 Flush();
claytong 0:82ff15078322 351 }
claytong 0:82ff15078322 352
claytong 0:82ff15078322 353 // queue manipulation
claytong 0:82ff15078322 354 public:
claytong 0:82ff15078322 355 // peek at the front buffer on the queue, but still leave the buffer there
claytong 0:82ff15078322 356 // (buffer must not be editted)
claytong 0:82ff15078322 357 bool Peek( TBufferHandle &Handle ) const
claytong 0:82ff15078322 358 { // attached the buffer to the handle
claytong 0:82ff15078322 359 return Handle.Attach( pFront ); // Attach also inc ref count
claytong 0:82ff15078322 360 }
claytong 0:82ff15078322 361
claytong 0:82ff15078322 362 // remove the first buffer from the queue and return in the handle
claytong 0:82ff15078322 363 bool Read( TBufferHandle &Handle )
claytong 0:82ff15078322 364 {
claytong 0:82ff15078322 365 // release any old buffers
claytong 0:82ff15078322 366 Handle.Release();
claytong 0:82ff15078322 367 // check for any buffers
claytong 0:82ff15078322 368 if ( iCount<=0 )
claytong 0:82ff15078322 369 return false; //Nothing in queue
claytong 0:82ff15078322 370 // get the front buffer
claytong 0:82ff15078322 371 TBufferData * pRemovedBuffer = pFront;
claytong 0:82ff15078322 372 if ( pRemovedBuffer==NULL )
claytong 0:82ff15078322 373 error( "TBufferQueue::Read queue pFront pointer!\r\n" );
claytong 0:82ff15078322 374 // adjust the queue ptrs
claytong 0:82ff15078322 375 RemovePtrFromQueue();
claytong 0:82ff15078322 376 #ifdef BUFFER_DEBUG
claytong 0:82ff15078322 377 // reset queued flag
claytong 0:82ff15078322 378 pRemovedBuffer->bQueued = false;
claytong 0:82ff15078322 379 #endif
claytong 0:82ff15078322 380 // no RefCount adjustment needed - buffer is added to handle but release from the queue
claytong 0:82ff15078322 381 // Manually put the buffer into the (empty) handle
claytong 0:82ff15078322 382 Handle.pMyBuffer = pRemovedBuffer;
claytong 0:82ff15078322 383 return true;
claytong 0:82ff15078322 384 }
claytong 0:82ff15078322 385
claytong 0:82ff15078322 386 // Write a buffer into the queue, removing it from the handle
claytong 0:82ff15078322 387 bool Write( TBufferHandle &Handle )
claytong 0:82ff15078322 388 {
claytong 0:82ff15078322 389 // check there is a buffer
claytong 0:82ff15078322 390 if ( !Handle.HasBuffer() )
claytong 0:82ff15078322 391 return false;
claytong 0:82ff15078322 392 // Buffer is manually moved (Reference counter is untouched)
claytong 0:82ff15078322 393 // Add msg ptr to the queue (does not adjust the reference counter)
claytong 0:82ff15078322 394 AddPtrToQueue( Handle.pMyBuffer );
claytong 0:82ff15078322 395 // Flag the buffer as queued
claytong 0:82ff15078322 396 #ifdef BUFFER_DEBUG
claytong 0:82ff15078322 397 Handle.pMyBuffer->bQueued = true;
claytong 0:82ff15078322 398 #endif
claytong 0:82ff15078322 399 // no RefCount adjustment needed - buffer is added to queue but release from the handle
claytong 0:82ff15078322 400 // Manually remove the buffer from the handle
claytong 0:82ff15078322 401 Handle.pMyBuffer = NULL;
claytong 0:82ff15078322 402 return true;
claytong 0:82ff15078322 403 }
claytong 0:82ff15078322 404
claytong 0:82ff15078322 405 // Return number of queued buffers
claytong 0:82ff15078322 406 int Count() const
claytong 0:82ff15078322 407 { return iCount; }
claytong 0:82ff15078322 408
claytong 0:82ff15078322 409 // Test if empty
claytong 0:82ff15078322 410 bool Empty() const
claytong 0:82ff15078322 411 { return (iCount==0); }
claytong 0:82ff15078322 412
claytong 0:82ff15078322 413 // strip all buffers from the queue
claytong 0:82ff15078322 414 bool Flush( void )
claytong 0:82ff15078322 415 {
claytong 0:82ff15078322 416 // check for buffers to flush
claytong 0:82ff15078322 417 if ( iCount==0 )
claytong 0:82ff15078322 418 return false;
claytong 0:82ff15078322 419 // read and release buffers until no more to read
claytong 0:82ff15078322 420 TBufferHandle MsgHandle;
claytong 0:82ff15078322 421 while ( Read(MsgHandle) )
claytong 0:82ff15078322 422 { // release the buffers
claytong 0:82ff15078322 423 MsgHandle.Release();
claytong 0:82ff15078322 424 }
claytong 0:82ff15078322 425 return true;
claytong 0:82ff15078322 426 }
claytong 0:82ff15078322 427
claytong 0:82ff15078322 428 // internal methods
claytong 0:82ff15078322 429 protected:
claytong 0:82ff15078322 430 // Add the buffer to the end of the queue
claytong 0:82ff15078322 431 // Does not do any checks etc or adjust buffer reference count
claytong 0:82ff15078322 432 void AddPtrToQueue( TBufferData *pMsg )
claytong 0:82ff15078322 433 {
claytong 0:82ff15078322 434 pMsg->pNext = NULL;
claytong 0:82ff15078322 435 if ( iCount == 0 )
claytong 0:82ff15078322 436 { // Queue is currently empty
claytong 0:82ff15078322 437 // Front = back = buffer
claytong 0:82ff15078322 438 pFront = pMsg;
claytong 0:82ff15078322 439 pBack = pMsg;
claytong 0:82ff15078322 440 iCount = 1;
claytong 0:82ff15078322 441 }
claytong 0:82ff15078322 442 else
claytong 0:82ff15078322 443 { // Add the buffer to the back of the queue
claytong 0:82ff15078322 444 pBack->pNext = pMsg;
claytong 0:82ff15078322 445 pBack = pMsg;
claytong 0:82ff15078322 446 iCount++;
claytong 0:82ff15078322 447 }
claytong 0:82ff15078322 448 }
claytong 0:82ff15078322 449
claytong 0:82ff15078322 450 // Remove a pointer from the front of the queue
claytong 0:82ff15078322 451 // Does not do any checks etc or adjust buffer reference count - just removes pointer
claytong 0:82ff15078322 452 void RemovePtrFromQueue( void )
claytong 0:82ff15078322 453 {
claytong 0:82ff15078322 454 // adjust the queue
claytong 0:82ff15078322 455 if ( iCount<=1 )
claytong 0:82ff15078322 456 { // Empty queue
claytong 0:82ff15078322 457 pFront = NULL;
claytong 0:82ff15078322 458 pBack = NULL;
claytong 0:82ff15078322 459 iCount=0;
claytong 0:82ff15078322 460 }
claytong 0:82ff15078322 461 else
claytong 0:82ff15078322 462 {
claytong 0:82ff15078322 463 // Remove first item
claytong 0:82ff15078322 464 pFront = pFront->pNext;
claytong 0:82ff15078322 465 // Decrement the number of buffers in the queue
claytong 0:82ff15078322 466 iCount--;
claytong 0:82ff15078322 467 }
claytong 0:82ff15078322 468 }
claytong 0:82ff15078322 469
claytong 0:82ff15078322 470 // data
claytong 0:82ff15078322 471 protected:
claytong 0:82ff15078322 472 TBufferData *pFront; // front of the queue (out point)
claytong 0:82ff15078322 473 TBufferData *pBack; // back of the queue (in point)
claytong 0:82ff15078322 474 int iCount; // number of items in the queue
claytong 0:82ff15078322 475
claytong 0:82ff15078322 476 friend class TBufferHandle;
claytong 0:82ff15078322 477
claytong 0:82ff15078322 478
claytong 0:82ff15078322 479
claytong 0:82ff15078322 480
claytong 0:82ff15078322 481 };
claytong 0:82ff15078322 482
claytong 0:82ff15078322 483 //---------------------------------------------------------------------------
claytong 0:82ff15078322 484 //
claytong 0:82ff15078322 485 // A Buffer Pool
claytong 0:82ff15078322 486 // A pool of free buffers
claytong 0:82ff15078322 487 //
claytong 0:82ff15078322 488 class TBufferPool : protected TBufferQueue
claytong 0:82ff15078322 489 {
claytong 0:82ff15078322 490 // create/destroy
claytong 0:82ff15078322 491 public:
claytong 0:82ff15078322 492 // create an pool and optionally add buffers to it off the stack
claytong 0:82ff15078322 493 TBufferPool( int iNumMsgs=0 ) :
claytong 0:82ff15078322 494 iBuffCount(0)
claytong 0:82ff15078322 495 {
claytong 0:82ff15078322 496 if (iNumMsgs>0)
claytong 0:82ff15078322 497 CreateBuffers( iNumMsgs );
claytong 0:82ff15078322 498 }
claytong 0:82ff15078322 499 // destroy a pool and all of its internal methods
claytong 0:82ff15078322 500 virtual ~TBufferPool()
claytong 0:82ff15078322 501 {
claytong 0:82ff15078322 502 // delete all buffers
claytong 0:82ff15078322 503 TBufferHandle MsgHandle;
claytong 0:82ff15078322 504 while ( Read(MsgHandle) )
claytong 0:82ff15078322 505 {
claytong 0:82ff15078322 506 // delete the TBufferData
claytong 0:82ff15078322 507 delete MsgHandle.pMyBuffer;
claytong 0:82ff15078322 508 // clear the buffer handle
claytong 0:82ff15078322 509 MsgHandle.pMyBuffer = NULL;
claytong 0:82ff15078322 510 }
claytong 0:82ff15078322 511 }
claytong 0:82ff15078322 512
claytong 0:82ff15078322 513 // pool setup
claytong 0:82ff15078322 514 public:
claytong 0:82ff15078322 515 // Add buffers to the pool
claytong 0:82ff15078322 516 // Buffers are created off the heap
claytong 0:82ff15078322 517 bool CreateBuffers( int iNumMsgs )
claytong 0:82ff15078322 518 {
claytong 0:82ff15078322 519 TBufferData * pBuff;
claytong 0:82ff15078322 520 // Loop and create msgs
claytong 0:82ff15078322 521 while ( iNumMsgs>0 )
claytong 0:82ff15078322 522 {
claytong 0:82ff15078322 523 //printf( "Creating buffer %d\r\n", iBuffCount );
claytong 0:82ff15078322 524 // Create the new buffer
claytong 0:82ff15078322 525 pBuff = new TBufferData;
claytong 0:82ff15078322 526 if ( pBuff==NULL )
claytong 0:82ff15078322 527 return false;
claytong 0:82ff15078322 528 // add the buffer to the pool
claytong 0:82ff15078322 529 pBuff->pPool = this;
claytong 0:82ff15078322 530 ReturnToPool( pBuff );
claytong 0:82ff15078322 531 iBuffCount++;
claytong 0:82ff15078322 532 iNumMsgs--;
claytong 0:82ff15078322 533 }
claytong 0:82ff15078322 534 return true;
claytong 0:82ff15078322 535 }
claytong 0:82ff15078322 536
claytong 0:82ff15078322 537 // add a new buffer to the pool -
claytong 0:82ff15078322 538 // either as a buffer (with or without a data structure)
claytong 0:82ff15078322 539 // or as a data structure with a buffer
claytong 0:82ff15078322 540 void AddNewMsgToPool( TBufferData & Buffer )
claytong 0:82ff15078322 541 {
claytong 0:82ff15078322 542 Buffer.pPool = this;
claytong 0:82ff15078322 543 ReturnToPool( &Buffer );
claytong 0:82ff15078322 544 iBuffCount++;
claytong 0:82ff15078322 545 }
claytong 0:82ff15078322 546
claytong 0:82ff15078322 547 // add an array of buffers to the pool
claytong 0:82ff15078322 548 void AddNewMsgsToPool( TBufferData *pBuffer, int iCount )
claytong 0:82ff15078322 549 {
claytong 0:82ff15078322 550 while ( iCount>0 )
claytong 0:82ff15078322 551 {
claytong 0:82ff15078322 552 AddNewMsgToPool( *pBuffer );
claytong 0:82ff15078322 553 pBuffer++;
claytong 0:82ff15078322 554 iCount--;
claytong 0:82ff15078322 555 }
claytong 0:82ff15078322 556 }
claytong 0:82ff15078322 557
claytong 0:82ff15078322 558 // place or return a buffer in the pool
claytong 0:82ff15078322 559 void ReturnToPool( TBufferData * pBuffer )
claytong 0:82ff15078322 560 {
claytong 0:82ff15078322 561 // Add to the queue (does not adjust the reference counter)
claytong 0:82ff15078322 562 AddPtrToQueue( pBuffer );
claytong 0:82ff15078322 563 // zero reference (should already be the case)
claytong 0:82ff15078322 564 pBuffer->iRefCount = 0;
claytong 0:82ff15078322 565 #ifdef BUFFER_DEBUG
claytong 0:82ff15078322 566 // Flag the buffer as pooled
claytong 0:82ff15078322 567 pBuffer->bPooled = true;
claytong 0:82ff15078322 568 #endif
claytong 0:82ff15078322 569 }
claytong 0:82ff15078322 570
claytong 0:82ff15078322 571 // Message Handling
claytong 0:82ff15078322 572 public:
claytong 0:82ff15078322 573 // buffer creation - takes a msg from the pool
claytong 0:82ff15078322 574 bool Create( TBufferHandle &Handle )
claytong 0:82ff15078322 575 {
claytong 0:82ff15078322 576 // read the buffer from the queue
claytong 0:82ff15078322 577 if ( !Read(Handle) )
claytong 0:82ff15078322 578 return false;
claytong 0:82ff15078322 579 // inc ref count (RefCount is 0 in pool, and Read does not adjust it)
claytong 0:82ff15078322 580 Handle.pMyBuffer->iRefCount++;
claytong 0:82ff15078322 581 #ifdef BUFFER_DEBUG
claytong 0:82ff15078322 582 // reset pool flag
claytong 0:82ff15078322 583 Handle.pMyBuffer->bPooled = false;
claytong 0:82ff15078322 584 #endif
claytong 0:82ff15078322 585 // Initialise the buffer
claytong 0:82ff15078322 586 Handle.Clear();
claytong 0:82ff15078322 587 Handle.pMyBuffer->uiTimestamp = 0;
claytong 0:82ff15078322 588 return true;
claytong 0:82ff15078322 589 }
claytong 0:82ff15078322 590
claytong 0:82ff15078322 591 // Pool Status
claytong 0:82ff15078322 592 public:
claytong 0:82ff15078322 593 // return number of buffers available
claytong 0:82ff15078322 594 int Available() const
claytong 0:82ff15078322 595 { return iCount; }
claytong 0:82ff15078322 596
claytong 0:82ff15078322 597 // data
claytong 0:82ff15078322 598 protected:
claytong 0:82ff15078322 599 int iBuffCount; // number of buffers installed in the pool
claytong 0:82ff15078322 600
claytong 0:82ff15078322 601 friend class TBufferData;
claytong 0:82ff15078322 602 friend class TBufferHandle;
claytong 0:82ff15078322 603
claytong 0:82ff15078322 604 };
claytong 0:82ff15078322 605
claytong 0:82ff15078322 606
claytong 0:82ff15078322 607 #endif
claytong 0:82ff15078322 608
claytong 0:82ff15078322 609 //---------------------------------------------------------------------------
claytong 0:82ff15078322 610 // END
claytong 0:82ff15078322 611 //---------------------------------------------------------------------------
claytong 0:82ff15078322 612