From b056f542aaa81a9d4216cada320e4c0285bafb92 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 9 May 2002 00:32:00 +0000 Subject: [PATCH] optimized --- src/ca/comBuf.cpp | 12 ++--- src/ca/comBuf.h | 14 +++--- src/ca/comQueRecv.cpp | 112 +++++++++++++++++------------------------- src/ca/comQueRecv.h | 67 +++++++++++++++++++++++++ src/ca/comQueSend.cpp | 24 +++------ src/ca/comQueSend.h | 28 ++++++----- 6 files changed, 148 insertions(+), 109 deletions(-) diff --git a/src/ca/comBuf.cpp b/src/ca/comBuf.cpp index 60c24c9b6..f1f1a093c 100644 --- a/src/ca/comBuf.cpp +++ b/src/ca/comBuf.cpp @@ -35,7 +35,7 @@ bool comBuf::flushToWire ( wireSendAdapter & wire ) return true; } -unsigned comBuf::push ( const epicsInt16 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsInt16 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -47,7 +47,7 @@ unsigned comBuf::push ( const epicsInt16 *pValue, unsigned nElem ) return nElem; } -unsigned comBuf::push ( const epicsUInt16 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsUInt16 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -59,7 +59,7 @@ unsigned comBuf::push ( const epicsUInt16 *pValue, unsigned nElem ) return nElem; } -unsigned comBuf::push ( const epicsInt32 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsInt32 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -75,7 +75,7 @@ unsigned comBuf::push ( const epicsInt32 *pValue, unsigned nElem ) return nElem; } -unsigned comBuf::push ( const epicsUInt32 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsUInt32 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -91,7 +91,7 @@ unsigned comBuf::push ( const epicsUInt32 *pValue, unsigned nElem ) return nElem; } -unsigned comBuf::push ( const epicsFloat32 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsFloat32 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -102,7 +102,7 @@ unsigned comBuf::push ( const epicsFloat32 *pValue, unsigned nElem ) return nElem; } -unsigned comBuf::push ( const epicsFloat64 *pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsFloat64 * pValue, unsigned nElem ) { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { diff --git a/src/ca/comBuf.h b/src/ca/comBuf.h index 3a5d03211..26ea43219 100644 --- a/src/ca/comBuf.h +++ b/src/ca/comBuf.h @@ -83,6 +83,7 @@ public: epicsUInt8 popUInt8 (); epicsUInt16 popUInt16 (); epicsUInt32 popUInt32 (); + static void throwInsufficentBytesException (); class insufficentBytesAvailable {}; protected: ~comBuf (); @@ -93,7 +94,6 @@ private: epicsUInt8 buf [ comBufSize ]; unsigned unoccupiedElem ( unsigned elemSize, unsigned nElem ); unsigned occupiedElem ( unsigned elemSize, unsigned nElem ); - void throwInsufficentBytesException (); static epicsSingleton < tsFreeList < class comBuf, 0x20 > > pFreeList; }; @@ -374,8 +374,8 @@ inline unsigned comBuf::removeBytes ( unsigned nBytes ) inline epicsUInt8 comBuf::popUInt8 () { - if ( this->occupiedBytes () == 0u ) { - this->throwInsufficentBytesException (); + if ( this->occupiedBytes () < 1u ) { + comBuf::throwInsufficentBytesException (); } return this->buf[ this->nextReadIndex++ ]; } @@ -383,7 +383,7 @@ inline epicsUInt8 comBuf::popUInt8 () inline epicsUInt16 comBuf::popUInt16 () { if ( this->occupiedBytes () < 2u ) { - this->throwInsufficentBytesException (); + comBuf::throwInsufficentBytesException (); } unsigned byte1 = this->buf[ this->nextReadIndex++ ]; unsigned byte2 = this->buf[ this->nextReadIndex++ ]; @@ -393,14 +393,14 @@ inline epicsUInt16 comBuf::popUInt16 () inline epicsUInt32 comBuf::popUInt32 () { if ( this->occupiedBytes () < 4u ) { - this->throwInsufficentBytesException (); + comBuf::throwInsufficentBytesException (); } unsigned byte1 = this->buf[ this->nextReadIndex++ ]; unsigned byte2 = this->buf[ this->nextReadIndex++ ]; unsigned byte3 = this->buf[ this->nextReadIndex++ ]; unsigned byte4 = this->buf[ this->nextReadIndex++ ]; - return static_cast < epicsUInt32 > - ( byte1 << 24u | byte2 << 16u | byte3 << 8u | byte4 ); //X aCC 392 } + return static_cast < epicsUInt32 > + ( byte1 << 24u | byte2 << 16u | byte3 << 8u | byte4 ); //X aCC 392 } #endif // ifndef comBufh diff --git a/src/ca/comQueRecv.cpp b/src/ca/comQueRecv.cpp index 414fd4522..5fd0fceaa 100644 --- a/src/ca/comQueRecv.cpp +++ b/src/ca/comQueRecv.cpp @@ -81,6 +81,13 @@ unsigned comQueRecv::removeBytes ( unsigned nBytes ) return totalBytes; } +void comQueRecv::popString ( epicsOldString *pStr ) +{ + for ( unsigned i = 0u; i < sizeof ( *pStr ); i++ ) { + pStr[0][i] = this->popInt8 (); + } +} + void comQueRecv::pushLastComBufReceived ( comBuf & bufIn ) { bufIn.commitIncomming (); @@ -101,79 +108,50 @@ void comQueRecv::pushLastComBufReceived ( comBuf & bufIn ) } } -epicsUInt8 comQueRecv::popUInt8 () +// 1) split between buffers expected to run slower +// 2) using canonical unsigned tmp avoids ANSI C conversions to int +// 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) +epicsUInt16 comQueRecv::multiBufferPopUInt16 () { - comBuf *pComBuf = this->bufs.first (); - if ( pComBuf ) { - epicsUInt8 tmp = pComBuf->popUInt8 (); - if ( pComBuf->occupiedBytes() == 0u ) { - this->bufs.remove ( *pComBuf ); - pComBuf->destroy (); - } - this->nBytesPending--; - return tmp; + epicsUInt16 tmp; + if ( this->occupiedBytes() >= sizeof (tmp) ) { + unsigned byte1 = this->popUInt8(); + unsigned byte2 = this->popUInt8(); + tmp = static_cast ( byte1 << 8u | byte2 ); } - throw insufficentBytesAvailable (); - return 0; // make compiler happy + else { + comBuf::throwInsufficentBytesException (); + tmp = 0u; + } + return tmp; } -// optimization here complicates this function somewhat -epicsUInt16 comQueRecv::popUInt16 () +// 1) split between buffers expected to run slower +// 2) using canonical unsigned temporary avoids ANSI C conversions to int +// 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) +epicsUInt32 comQueRecv::multiBufferPopUInt32 () { - comBuf *pComBuf = this->bufs.first (); - if ( pComBuf ) { - epicsUInt16 tmp; - try { - // try first for all in one buffer efficent version - tmp = pComBuf->popUInt16 (); - if ( pComBuf->occupiedBytes() == 0u ) { - this->bufs.remove ( *pComBuf ); - pComBuf->destroy (); - } - this->nBytesPending -= sizeof( tmp ); - } - catch ( insufficentBytesAvailable & ) { - // 1) split between buffers expected to run slower - // 2) using canonical unsigned tmp avoids ANSI C conversions to int - // 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) - unsigned byte1 = this->popUInt8(); - unsigned byte2 = this->popUInt8(); - tmp = static_cast ( byte1 << 8u | byte2 ); - } - return tmp; + epicsUInt32 tmp; + if ( this->occupiedBytes() >= sizeof (tmp) ) { + // 1) split between buffers expected to run slower + // 2) using canonical unsigned temporary avoids ANSI C conversions to int + // 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) + unsigned byte1 = this->popUInt8(); + unsigned byte2 = this->popUInt8(); + unsigned byte3 = this->popUInt8(); + unsigned byte4 = this->popUInt8(); + tmp = static_cast + ( byte1 << 24u | byte2 << 16u | byte3 << 8u | byte4 ); //X aCC 392 } - throw insufficentBytesAvailable (); - return 0; // make compiler happy + else { + comBuf::throwInsufficentBytesException (); + tmp = 0u; // avoid compiler warnings + } + return tmp; } -// optimization here complicates this function somewhat -epicsUInt32 comQueRecv::popUInt32 () +void comQueRecv::removeAndDestroyBuf ( comBuf & buf ) { - comBuf *pComBuf = this->bufs.first (); - if ( pComBuf ) { - epicsUInt32 tmp; - try { - // try first for all in one buffer efficent version - tmp = pComBuf->popUInt32 (); - if ( pComBuf->occupiedBytes() == 0u ) { - this->bufs.remove ( *pComBuf ); - pComBuf->destroy (); - } - this->nBytesPending -= sizeof ( tmp ); - } - catch ( insufficentBytesAvailable & ) { - // 1) split between buffers expected to run slower - // 2) using canonical unsigned temporary avoids ANSI C conversions to int - // 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) - unsigned byte1 = this->popUInt8(); - unsigned byte2 = this->popUInt8(); - unsigned byte3 = this->popUInt8(); - unsigned byte4 = this->popUInt8(); - tmp = static_cast - ( byte1 << 24u | byte2 << 16u | byte3 << 8u | byte4 ); //X aCC 392 - } - return tmp; - } - throw insufficentBytesAvailable (); - return 0; // make compiler happy -} + this->bufs.remove ( buf ); + buf.destroy (); +} \ No newline at end of file diff --git a/src/ca/comQueRecv.h b/src/ca/comQueRecv.h index e2b43c0dd..80161c2f2 100644 --- a/src/ca/comQueRecv.h +++ b/src/ca/comQueRecv.h @@ -40,6 +40,9 @@ public: private: tsDLList < comBuf > bufs; unsigned nBytesPending; + epicsUInt16 multiBufferPopUInt16 (); + epicsUInt32 multiBufferPopUInt32 (); + void removeAndDestroyBuf ( comBuf & ); comQueRecv ( const comQueRecv & ); comQueRecv & operator = ( const comQueRecv & ); }; @@ -94,4 +97,68 @@ inline epicsFloat64 comQueRecv::popFloat64 () return tmp; } +inline epicsUInt8 comQueRecv::popUInt8 () +{ + comBuf * pComBuf = this->bufs.first (); + if ( ! pComBuf ) { + comBuf::throwInsufficentBytesException (); + } + epicsUInt8 tmp = pComBuf->popUInt8 (); + if ( pComBuf->occupiedBytes() == 0u ) { + this->removeAndDestroyBuf ( *pComBuf ); + } + this->nBytesPending--; + return tmp; +} + +// optimization here complicates this function somewhat +inline epicsUInt16 comQueRecv::popUInt16 () +{ + comBuf *pComBuf = this->bufs.first (); + if ( ! pComBuf ) { + comBuf::throwInsufficentBytesException (); + } + // try first for all in one buffer efficent version + // (double check here avoids slow C++ exception) + // (hopefully optimizer removes inside check) + epicsUInt16 tmp; + unsigned bytesAvailable = pComBuf->occupiedBytes(); + if ( bytesAvailable >= sizeof (tmp) ) { + tmp = pComBuf->popUInt16 (); + if ( bytesAvailable == sizeof (tmp) ) { + this->removeAndDestroyBuf ( *pComBuf ); + } + this->nBytesPending -= sizeof( tmp ); + } + else { + tmp = this->multiBufferPopUInt16 (); + } + return tmp; +} + +// optimization here complicates this function somewhat +inline epicsUInt32 comQueRecv::popUInt32 () +{ + comBuf *pComBuf = this->bufs.first (); + if ( ! pComBuf ) { + comBuf::throwInsufficentBytesException (); + } + epicsUInt32 tmp; + // try first for all in one buffer efficent version + // (double check here avoids slow C++ exception) + // (hopefully optimizer removes inside check) + unsigned bytesAvailable = pComBuf->occupiedBytes(); + if ( pComBuf->occupiedBytes() >= sizeof (tmp) ) { + tmp = pComBuf->popUInt32 (); + if ( bytesAvailable == sizeof (tmp) ) { + this->removeAndDestroyBuf ( *pComBuf ); + } + this->nBytesPending -= sizeof ( tmp ); + } + else { + tmp = this->multiBufferPopUInt32 (); + } + return tmp; +} + #endif // ifndef comQueRecvh diff --git a/src/ca/comQueSend.cpp b/src/ca/comQueSend.cpp index 32422b93c..8ed27b1d3 100644 --- a/src/ca/comQueSend.cpp +++ b/src/ca/comQueSend.cpp @@ -199,22 +199,6 @@ comBuf * comQueSend::popNextComBufToSend () return pBuf; } -void comQueRecv::popString ( epicsOldString *pStr ) -{ - for ( unsigned i = 0u; i < sizeof ( *pStr ); i++ ) { - pStr[0][i] = this->popInt8 (); - } -} - -void comQueSend::commitMsg () -{ - while ( this->pFirstUncommited.valid() ) { - this->nBytesPending += this->pFirstUncommited->uncommittedBytes (); - this->pFirstUncommited->commitIncomming (); - this->pFirstUncommited++; - } -} - void comQueSend::insertRequestHeader ( ca_uint16_t request, ca_uint32_t payloadSize, ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, @@ -292,3 +276,11 @@ void comQueSend::insertRequestWithPayLoad ( this->commitMsg (); } +void comQueSend::commitMsg () +{ + while ( this->pFirstUncommited.valid() ) { + this->nBytesPending += this->pFirstUncommited->uncommittedBytes (); + this->pFirstUncommited->commitIncomming (); + this->pFirstUncommited++; + } +} diff --git a/src/ca/comQueSend.h b/src/ca/comQueSend.h index 7f294cd5f..426340e39 100644 --- a/src/ca/comQueSend.h +++ b/src/ca/comQueSend.h @@ -65,6 +65,7 @@ private: void copy_dbr_char ( const void *pValue, unsigned nElem ); void copy_dbr_long ( const void *pValue, unsigned nElem ); void copy_dbr_double ( const void *pValue, unsigned nElem ); + void pushComBuf ( comBuf & ); typedef void ( comQueSend::*copyFunc_t ) ( const void *pValue, unsigned nElem ); static const copyFunc_t dbrCopyVector [39]; @@ -90,10 +91,7 @@ private: comBuf * pComBuf = new comBuf; unsigned nNew = pComBuf->push ( &pVal[nCopied], nElem - nCopied ); nCopied += nNew; - this->bufs.add ( *pComBuf ); - if ( ! this->pFirstUncommited.valid() ) { - this->pFirstUncommited = this->bufs.lastIter (); - } + this->pushComBuf ( *pComBuf ); } } @@ -104,19 +102,15 @@ private: template < class T > inline void push ( const T & val ) { - comBuf * pComBuf = this->bufs.last (); - if ( pComBuf ) { - if ( pComBuf->push ( val ) ) { - return; - } + register comBuf * pComBuf = this->bufs.last (); + if ( pComBuf && pComBuf->push ( val ) ) { + return; } pComBuf = new comBuf; assert ( pComBuf->push ( val ) ); - this->bufs.add ( *pComBuf ); - if ( ! this->pFirstUncommited.valid() ) { - this->pFirstUncommited = this->bufs.lastIter (); - } + this->pushComBuf ( *pComBuf ); } + comQueSend ( const comQueSend & ); comQueSend & operator = ( const comQueSend & ); }; @@ -161,6 +155,14 @@ inline void comQueSend::push_dbr_type ( unsigned type, const void *pVal, unsigne ( this->*dbrCopyVector [type] ) ( pVal, nElem ); } +inline void comQueSend::pushComBuf ( comBuf & cb ) +{ + this->bufs.add ( cb ); + if ( ! this->pFirstUncommited.valid() ) { + this->pFirstUncommited = this->bufs.lastIter (); + } +} + inline unsigned comQueSend::occupiedBytes () const { return this->nBytesPending;