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
BufferSys.h@0:82ff15078322, 2012-01-25 (annotated)
- 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?
User | Revision | Line number | New 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 |