diff --git a/src/ca/CASG.cpp b/src/ca/CASG.cpp index e5f47653d..4e600c22f 100644 --- a/src/ca/CASG.cpp +++ b/src/ca/CASG.cpp @@ -14,6 +14,8 @@ * (505) 665 1831 */ +#include + #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #define epicsExportSharedSymbols @@ -24,19 +26,12 @@ #include "cac.h" #include "sgAutoPtr.h" -epicsSingleton < tsFreeList < struct CASG, 128 > > CASG::pFreeList; - CASG::CASG ( ca_client_context &cacIn ) : client ( cacIn ), magic ( CASG_MAGIC ) { client.installCASG ( *this ); } -void CASG::destroy () -{ - delete this; -} - CASG::~CASG () { if ( this->verify () ) { @@ -243,24 +238,14 @@ void CASG::completionNotify ( syncGroupNotify & notify ) } } -void CASG::recycleSyncGroupWriteNotify ( syncGroupWriteNotify &io ) +void CASG::recycleSyncGroupWriteNotify ( syncGroupWriteNotify & io ) { - this->freeListWriteOP.release ( &io, sizeof ( io ) ); + this->freeListWriteOP.release ( & io ); } -void CASG::recycleSyncGroupReadNotify ( syncGroupReadNotify &io ) +void CASG::recycleSyncGroupReadNotify ( syncGroupReadNotify & io ) { - this->freeListReadOP.release ( &io, sizeof ( io ) ); -} - -void * CASG::operator new (size_t size) -{ - return CASG::pFreeList->allocate ( size ); -} - -void CASG::operator delete (void *pCadaver, size_t size) -{ - CASG::pFreeList->release ( pCadaver, size ); + this->freeListReadOP.release ( & io ); } int CASG::printf ( const char *pformat, ... ) @@ -291,5 +276,11 @@ void CASG::exception ( int status, const char *pContext, lineNo, chan, type, count, op ); } +void CASG::operator delete ( void * pCadaver ) +{ + throw std::logic_error + ( "compiler is confused about placement delete" ); +} + diff --git a/src/ca/access.cpp b/src/ca/access.cpp index 768ddb330..9578bdc96 100644 --- a/src/ca/access.cpp +++ b/src/ca/access.cpp @@ -68,11 +68,9 @@ extern "C" void ca_init_client_context ( void * ) */ int fetchClientContext ( ca_client_context **ppcac ) { + epicsThreadOnce ( &caClientContextIdOnce, ca_init_client_context, 0 ); if ( caClientContextId == 0 ) { - epicsThreadOnce ( &caClientContextIdOnce, ca_init_client_context, 0 ); - if ( caClientContextId == 0 ) { - return ECA_ALLOCMEM; - } + return ECA_ALLOCMEM; } int status; @@ -233,18 +231,20 @@ int epicsShareAPI ca_search_and_connect ( // extern "C" int epicsShareAPI ca_create_channel ( - const char *name_str, caCh * conn_func, void * puser, + const char * name_str, caCh * conn_func, void * puser, capri priority, chid * chanptr ) { - ca_client_context *pcac; - int caStatus = fetchClientContext ( &pcac ); + ca_client_context * pcac; + int caStatus = fetchClientContext ( & pcac ); if ( caStatus != ECA_NORMAL ) { return caStatus; } try { - oldChannelNotify * pChanNotify = new oldChannelNotify ( - * pcac, name_str, conn_func, puser, priority ); + oldChannelNotify * pChanNotify = + new ( pcac->oldChannelNotifyFreeList ) + oldChannelNotify ( *pcac, name_str, + conn_func, puser, priority ); // make sure that their chan pointer is set prior to // calling connection call backs *chanptr = pChanNotify; @@ -272,9 +272,11 @@ int epicsShareAPI ca_create_channel ( // extern "C" int epicsShareAPI ca_clear_channel ( chid pChan ) { - pChan->destroy (); + ca_client_context & cac = pChan->getClientCtx (); + cac.destroyChannel ( *pChan ); return ECA_NORMAL; } +#include "autoPtrFreeList.h" /* * ca_array_get () @@ -283,24 +285,17 @@ int epicsShareAPI ca_clear_channel ( chid pChan ) int epicsShareAPI ca_array_get ( chtype type, arrayElementCount count, chid pChan, void *pValue ) { - ca_client_context *pcac; - int caStatus = fetchClientContext ( &pcac ); - if ( caStatus != ECA_NORMAL ) { - return caStatus; - } - - if ( type < 0 ) { - return ECA_BADTYPE; - } - unsigned tmpType = static_cast < unsigned > ( type ); - - autoPtrDestroy < getCopy > pNotify - ( new getCopy ( *pcac, *pChan, tmpType, count, pValue ) ); - if ( ! pNotify.get() ) { - return ECA_ALLOCMEM; - } - + int caStatus; try { + if ( type < 0 ) { + return ECA_BADTYPE; + } + unsigned tmpType = static_cast < unsigned > ( type ); + autoPtrFreeList < getCopy > pNotify + ( pChan->getClientCtx().getCopyFreeList, + new ( pChan->getClientCtx().getCopyFreeList ) + getCopy ( pChan->getClientCtx(), *pChan, + tmpType, count, pValue ) ); pChan->read ( type, count, *pNotify ); pNotify.release (); caStatus = ECA_NORMAL; @@ -355,19 +350,16 @@ int epicsShareAPI ca_array_get_callback ( chtype type, arrayElementCount count, chid pChan, caEventCallBackFunc *pfunc, void *arg ) { - if ( type < 0 ) { - return ECA_BADTYPE; - } - unsigned tmpType = static_cast < unsigned > ( type ); - - autoPtrDestroy < getCallback > pNotify - ( new getCallback ( *pChan, pfunc, arg ) ); - if ( ! pNotify.get() ) { - return ECA_ALLOCMEM; - } - int caStatus; try { + if ( type < 0 ) { + return ECA_BADTYPE; + } + unsigned tmpType = static_cast < unsigned > ( type ); + + autoPtrDestroy < getCallback > pNotify + ( new ( pChan->getClientCtx().getCallbackFreeList ) + getCallback ( *pChan, pfunc, arg ) ); pChan->read ( tmpType, count, *pNotify ); pNotify.release (); caStatus = ECA_NORMAL; @@ -421,19 +413,16 @@ int epicsShareAPI ca_array_get_callback ( chtype type, int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count, chid pChan, const void *pValue, caEventCallBackFunc *pfunc, void *usrarg ) { - if ( type < 0 ) { - return ECA_BADTYPE; - } - unsigned tmpType = static_cast < unsigned > ( type ); - - autoPtrDestroy < putCallback > pNotify - ( new putCallback ( *pChan, pfunc, usrarg ) ); - if ( ! pNotify.get() ) { - return ECA_ALLOCMEM; - } - int caStatus; try { + if ( type < 0 ) { + return ECA_BADTYPE; + } + unsigned tmpType = static_cast < unsigned > ( type ); + autoPtrFreeList < putCallback > pNotify + ( pChan->getClientCtx().putCallbackFreeList, + new ( pChan->getClientCtx().putCallbackFreeList ) + putCallback ( *pChan, pfunc, usrarg ) ); pChan->write ( tmpType, count, pValue, *pNotify ); pNotify.release (); caStatus = ECA_NORMAL; @@ -601,21 +590,19 @@ int epicsShareAPI ca_add_masked_array_event ( } try { - autoPtrDestroy < oldSubscription > pSubsr - ( new oldSubscription ( *pChan, pCallBack, pCallBackArg ) ); - if ( pSubsr.get () ) { - evid pTmp = pSubsr.release (); - if ( monixptr ) { - *monixptr = pTmp; - } - pTmp->begin ( tmpType, count, mask ); - // dont touch pTmp after this because - // the first callback might have canceled it - return ECA_NORMAL; - } - else { - return ECA_ALLOCMEM; + autoPtrFreeList < oldSubscription > pSubsr + ( pChan->getClientCtx().subscriptionFreeList, + new ( pChan->getClientCtx().subscriptionFreeList ) + oldSubscription ( *pChan, + pCallBack, pCallBackArg ) ); + evid pTmp = pSubsr.release (); + if ( monixptr ) { + *monixptr = pTmp; } + pTmp->begin ( tmpType, count, mask ); + // dont touch pTmp after this because + // the first callback might have canceled it + return ECA_NORMAL; } catch ( cacChannel::badType & ) { @@ -656,7 +643,10 @@ int epicsShareAPI ca_add_masked_array_event ( // extern "C" int epicsShareAPI ca_clear_event ( evid pMon ) { - pMon->destroy (); + oldChannelNotify & chan = pMon->channel (); + ca_client_context & cac = chan.getClientCtx (); + pMon->ioCancel (); + cac.destroySubscription ( *pMon ); return ECA_NORMAL; } diff --git a/src/ca/bhe.cpp b/src/ca/bhe.cpp index c7aae430e..a035f748f 100644 --- a/src/ca/bhe.cpp +++ b/src/ca/bhe.cpp @@ -19,7 +19,7 @@ * Author: Jeff Hill */ - +#include #include #include @@ -30,18 +30,6 @@ #include "virtualCircuit.h" #include "bhe.h" -epicsSingleton < tsFreeList < class bhe, 1024 > > bhe::pFreeList; - -void * bhe::operator new ( size_t size ) -{ - return bhe::pFreeList->allocate ( size ); -} - -void bhe::operator delete ( void *pCadaver, size_t size ) -{ - bhe::pFreeList->release ( pCadaver, size ); -} - /* * set average to -1.0 so that when the next beacon * occurs we can distinguish between: @@ -236,12 +224,7 @@ void bhe::show ( unsigned /* level */ ) const static_cast ( this ), this->averagePeriod ); } -void bhe::destroy () -{ - delete this; -} - -double bhe::period () const +double bhe::period () const throw () { return this->averagePeriod; } @@ -263,3 +246,22 @@ void bhe::unregisterIIU ( tcpiiu & iiu ) this->averagePeriod = - DBL_MAX; } +void bhe::operator delete ( void * ) +{ + throw std::logic_error + ( "compiler is confused about placement delete?" ); +} + +void * bheFreeStore::allocate ( size_t size ) +{ + return freeList.allocate ( size ); +} + +void bheFreeStore::release ( void * pCadaver ) +{ + freeList.release ( pCadaver ); +} + +epicsShareFunc bheMemoryManager::~bheMemoryManager () {} + + diff --git a/src/ca/bhe.h b/src/ca/bhe.h index 33591e71f..2317c22a7 100644 --- a/src/ca/bhe.h +++ b/src/ca/bhe.h @@ -30,8 +30,8 @@ #include "tsDLList.h" #include "tsFreeList.h" -#include "epicsSingleton.h" #include "epicsTime.h" +#include "cxxCompilerDepPlacementDelete.h" #ifdef bhehEpicsExportSharedSymbols # define epicsExportSharedSymbols @@ -42,34 +42,75 @@ #include "caProto.h" class tcpiiu; +class bheMemoryManager; + +// using a pure abstract wrapper class around the free list avoids +// Tornado 2.0.1 GNU compiler bugs +class bheMemoryManager { +public: + epicsShareFunc virtual ~bheMemoryManager (); + virtual void * allocate ( size_t ) = 0; + virtual void release ( void * ) = 0; +}; class bhe : public tsSLNode < bhe >, public inetAddrID { public: - epicsShareFunc bhe ( const epicsTime &initialTimeStamp, - unsigned initialBeaconNumber, const inetAddrID &addr ); + epicsShareFunc bhe ( const epicsTime & initialTimeStamp, + unsigned initialBeaconNumber, const inetAddrID & addr ) throw (); epicsShareFunc ~bhe (); - epicsShareFunc void destroy (); - epicsShareFunc bool updatePeriod ( const epicsTime & programBeginTime, - const epicsTime & currentTime, ca_uint32_t beaconNumber, - unsigned protocolRevision ); - epicsShareFunc double period () const; + epicsShareFunc bool updatePeriod ( + const epicsTime & programBeginTime, + const epicsTime & currentTime, ca_uint32_t beaconNumber, + unsigned protocolRevision ); + epicsShareFunc double period () const throw (); epicsShareFunc epicsTime updateTime () const; epicsShareFunc void show ( unsigned level) const; epicsShareFunc void registerIIU ( tcpiiu & ); epicsShareFunc void unregisterIIU ( tcpiiu & ); - epicsShareFunc void * operator new ( size_t size ); - epicsShareFunc void operator delete ( void *pCadaver, size_t size ); + epicsShareFunc void * operator new ( size_t size, + bheMemoryManager & ); +#ifdef CXX_PLACEMENT_DELETE + epicsShareFunc void operator delete ( void *, + bheMemoryManager & ); +#endif private: tsDLList < tcpiiu > iiuList; epicsTime timeStamp; double averagePeriod; ca_uint32_t lastBeaconNumber; void beaconAnomalyNotify (); - static epicsSingleton < tsFreeList < class bhe, 1024 > > pFreeList; bhe ( const bhe & ); bhe & operator = ( const bhe & ); + void * operator new ( size_t size ); + epicsShareFunc void operator delete ( void * ); + void * operator new [] ( size_t size ); + void operator delete [] ( void * ); }; +// using a wrapper class around the free list avoids +// Tornado 2.0.1 GNU compiler bugs +class bheFreeStore : public bheMemoryManager { +public: + void * allocate ( size_t ); + void release ( void * ); +private: + tsFreeList < class bhe, 0x100 > freeList; +}; + +inline void * bhe::operator new ( size_t size, + bheMemoryManager & mgr ) +{ + return mgr.allocate ( size ); +} + +#ifdef CXX_PLACEMENT_DELETE +inline void bhe::operator delete ( void * pCadaver, + bheMemoryManager & mgr ) +{ + mgr.release ( pCadaver ); +} +#endif + #endif // ifdef bheh diff --git a/src/ca/ca_client_context.cpp b/src/ca/ca_client_context.cpp index 8bde57641..a54d2879c 100644 --- a/src/ca/ca_client_context.cpp +++ b/src/ca/ca_client_context.cpp @@ -46,6 +46,56 @@ ca_client_context::~ca_client_context () delete & this->clientCtx; } +void ca_client_context::destroyChannel ( oldChannelNotify & chan ) +{ + chan.~oldChannelNotify (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + oldChannelNotify::operator delete ( & chan, this->oldChannelNotifyFreeList ); +# else + this->oldChannelNotifyFreeList.release ( & chan ); +# endif +} + +void ca_client_context::destroyGetCopy ( getCopy & gc ) +{ + gc.~getCopy (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + getCopy::operator delete ( & gc, this->getCopyFreeList ); +# else + this->getCopyFreeList.release ( & gc ); +# endif +} + +void ca_client_context::destroyGetCallback ( getCallback & gcb ) +{ + gcb.~getCallback (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + getCallback::operator delete ( & gcb, this->getCallbackFreeList ); +# else + this->getCallbackFreeList.release ( & gcb ); +# endif +} + +void ca_client_context::destroyPutCallback ( putCallback & pcb ) +{ + pcb.~putCallback (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + putCallback::operator delete ( & pcb, this->putCallbackFreeList ); +# else + this->putCallbackFreeList.release ( & pcb ); +# endif +} + +void ca_client_context::destroySubscription ( oldSubscription & os ) +{ + os.~oldSubscription (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + oldSubscription::operator delete ( & os, this->subscriptionFreeList ); +# else + this->subscriptionFreeList.release ( & os ); +# endif +} + void ca_client_context::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg ) { epicsGuard < ca_client_context_mutex > guard ( this->mutex ); @@ -225,21 +275,15 @@ void ca_client_context::attachToClientCtx () void ca_client_context::incrementOutstandingIO ( unsigned ioSeqNoIn ) { + epicsGuard < ca_client_context_mutex > guard ( this->mutex ); if ( this->ioSeqNo == ioSeqNoIn ) { - epicsGuard < ca_client_context_mutex > guard ( this->mutex ); - if ( this->ioSeqNo == ioSeqNoIn ) { - assert ( this->pndRecvCnt < UINT_MAX ); - this->pndRecvCnt++; - } + assert ( this->pndRecvCnt < UINT_MAX ); + this->pndRecvCnt++; } } void ca_client_context::decrementOutstandingIO ( unsigned ioSeqNoIn ) { - if ( this->ioSeqNo != ioSeqNoIn ) { - return; - } - bool signalNeeded; { epicsGuard < ca_client_context_mutex > guard ( this->mutex ); diff --git a/src/ca/cac.cpp b/src/ca/cac.cpp index 28c3f616b..f8827d587 100644 --- a/src/ca/cac.cpp +++ b/src/ca/cac.cpp @@ -23,11 +23,10 @@ #include -#include "epicsMemory.h" #include "epicsGuard.h" #include "epicsVersion.h" #include "osiProcess.h" -#include "osiSigPipeIgnore.h" +#include "epicsSignal.h" #include "envDefs.h" #define epicsExportSharedSymbols @@ -43,6 +42,7 @@ #include "udpiiu.h" #include "bhe.h" #include "net_convert.h" +#include "autoPtrDestroy.h" static const char *id = "@(#) " EPICS_VERSION_STRING ", CA Portable Server Library" __DATE__; @@ -137,6 +137,7 @@ cac::cac ( cacNotify & notifyIn, bool enablePreemptiveCallbackIn ) : programBeginTime ( epicsTime::getCurrent() ), connTMO ( CA_CONN_VERIFY_PERIOD ), cbMutex ( ! enablePreemptiveCallbackIn ), + globalServiceList ( globalServiceListCAC ), timerQueue ( epicsTimerQueueActive::allocate ( false, lowestPriorityLevelAbove(epicsThreadGetPrioritySelf()) ) ), pUserName ( 0 ), @@ -158,7 +159,7 @@ cac::cac ( cacNotify & notifyIn, bool enablePreemptiveCallbackIn ) : try { long status; - installSigPipeIgnore (); + epicsSignalInstallSigPipeIgnore (); { char tmp[256]; @@ -272,7 +273,16 @@ cac::~cac () delete [] this->pUserName; - this->beaconTable.traverse ( &bhe::destroy ); + tsSLList < bhe > tmpBeaconList; + this->beaconTable.removeAll ( tmpBeaconList ); + while ( bhe * pBHE = tmpBeaconList.get() ) { + pBHE->~bhe (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + bhe::operator delete ( pBHE, this->bheFreeList ); +# else + this->bheFreeList.release ( pBHE ); +# endif + } osiSockRelease (); @@ -401,10 +411,16 @@ void cac::beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime, * time that we have seen a server's beacon * shortly after the program started up) */ - pBHE = new bhe ( currentTime, beaconNumber, addr ); + pBHE = new ( this->bheFreeList ) + bhe ( currentTime, beaconNumber, addr ); if ( pBHE ) { if ( this->beaconTable.add ( *pBHE ) < 0 ) { - pBHE->destroy (); + pBHE->~bhe (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + bhe::operator delete ( pBHE, this->bheFreeList ); +# else + this->bheFreeList.release ( pBHE ); +# endif } } return; @@ -453,8 +469,6 @@ void cac::registerService ( cacService & service ) cacChannel & cac::createChannel ( const char * pName, cacChannelNotify & chan, cacChannel::priLev pri ) { - cacChannel *pIO; - if ( pri > cacChannel::priorityMax ) { throw cacChannel::badPriority (); } @@ -463,24 +477,23 @@ cacChannel & cac::createChannel ( const char * pName, throw cacChannel::badString (); } - pIO = this->services.createChannel ( pName, chan, pri ); - if ( ! pIO ) { - pIO = pGlobalServiceListCAC->createChannel ( pName, chan, pri ); - if ( ! pIO ) { - if ( ! this->pudpiiu ) { - epicsGuard < cacMutex > guard ( this->mutex ); - if ( ! this->pudpiiu ) { - this->pudpiiu = new udpiiu ( this->timerQueue, this->cbMutex, *this ); - } - } + autoPtrDestroy < cacChannel > + pIO ( this->services.createChannel ( pName, chan, pri ) ); + if ( pIO.get() == 0 ) { + pIO = this->globalServiceList->createChannel ( pName, chan, pri ); + if ( pIO.get() == 0 ) { epicsGuard < cacMutex > guard ( this->mutex ); - epics_auto_ptr < nciu > pNetChan - ( new nciu ( *this, *this->pudpiiu, chan, pName, pri ) ); + if ( ! this->pudpiiu ) { + this->pudpiiu = new udpiiu ( this->timerQueue, this->cbMutex, *this ); + } + autoPtrDestroy < nciu > pNetChan + ( new ( this->channelFreeList ) + nciu ( *this, *this->pudpiiu, chan, pName, pri ) ); this->chanTable.add ( *pNetChan ); - return *pNetChan.release (); + return * pNetChan.release (); } } - return *pIO; + return * pIO.release (); } void cac::repeaterSubscribeConfirmNotify () @@ -524,11 +537,10 @@ bool cac::lookupChannelAndTransferToTCP ( if ( ! sockAddrAreIdentical ( &addr, &chanAddr ) ) { char acc[64]; pChan->getPIIU()->hostName ( acc, sizeof ( acc ) ); - msgForMultiplyDefinedPV *pMsg = new msgForMultiplyDefinedPV ( - this->cbMutex, *this, pChan->pName (), acc, addr ); - if ( pMsg ) { - this->ipAddrToAsciiAsynchronousRequestInstall ( *pMsg ); - } + msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList ) + msgForMultiplyDefinedPV ( + this->cbMutex, *this, pChan->pName (), acc, addr ); + this->ipAddrToAsciiAsynchronousRequestInstall ( *pMsg ); } return true; } @@ -547,23 +559,13 @@ bool cac::lookupChannelAndTransferToTCP ( try { epics_auto_ptr < tcpiiu > pnewiiu ( new tcpiiu ( *this, this->cbMutex, this->connTMO, this->timerQueue, - addr, minorVersionNumber, this->ipToAEngine, - pChan->getPriority() ) ); - if ( pnewiiu.get() == 0 ) { - return true; - } + addr, this->comBufMemMgr, minorVersionNumber, + this->ipToAEngine, pChan->getPriority() ) ); bhe * pBHE = this->beaconTable.lookup ( addr.ia ); if ( ! pBHE ) { - epics_auto_ptr < bhe > pNewBHE ( new bhe ( epicsTime (), 0u, addr.ia ) ); - if ( pNewBHE.get () ) { - if ( this->beaconTable.add ( *pNewBHE ) >= 0 ) { - pBHE = pNewBHE.release (); - } - else { - return true; - } - } - else { + pBHE = new ( this->bheFreeList ) + bhe ( epicsTime (), 0u, addr.ia ); + if ( this->beaconTable.add ( *pBHE ) < 0 ) { return true; } } @@ -572,8 +574,11 @@ bool cac::lookupChannelAndTransferToTCP ( piiu = pnewiiu.release (); newIIU = true; } + catch ( std::bad_alloc & ) { + return true; + } catch ( ... ) { - this->printf ( "CAC: Exception during virtual circuit creation\n" ); + this->printf ( "CAC: Unexpected exception during virtual circuit creation\n" ); return true; } } @@ -625,7 +630,7 @@ bool cac::lookupChannelAndTransferToTCP ( return true; } -void cac::uninstallChannel ( nciu & chan ) +void cac::destroyChannel ( nciu & chan ) { tsDLList < baseNMIU > tmpList; @@ -707,6 +712,14 @@ void cac::uninstallChannel ( nciu & chan ) chan.getPIIU()->uninstallChan ( guard, chan ); } } + + // run channel's destructor and return it to the free list + chan.~nciu (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + nciu::operator delete ( & chan, this->channelFreeList ); +# else + this->channelFreeList.release ( & chan ); +# endif } int cac::printf ( const char *pformat, ... ) const @@ -1043,17 +1056,17 @@ void cac::disconnectAllIO ( epicsGuard < cacMutex > &locker, nciu & chan, bool e void cac::recycleReadNotifyIO ( netReadNotifyIO &io ) { - this->freeListReadNotifyIO.release ( &io, sizeof ( io ) ); + this->freeListReadNotifyIO.release ( & io ); } void cac::recycleWriteNotifyIO ( netWriteNotifyIO &io ) { - this->freeListWriteNotifyIO.release ( &io, sizeof ( io ) ); + this->freeListWriteNotifyIO.release ( & io ); } void cac::recycleSubscription ( netSubscription &io ) { - this->freeListSubscription.release ( &io, sizeof ( io ) ); + this->freeListSubscription.release ( & io ); } cacChannel::ioid @@ -1574,3 +1587,13 @@ void cac::initiateConnect ( nciu & chan ) this->pudpiiu->installChannel ( chan ); } +void *cacComBufMemoryManager::allocate ( size_t size ) throw ( std::bad_alloc ) +{ + return this->freeList.allocate ( size ); +} + +void cacComBufMemoryManager::release ( void * pCadaver ) throw () +{ + return this->freeList.release ( pCadaver ); +} + diff --git a/src/ca/cac.h b/src/ca/cac.h index bd87fcbc8..bc33edd95 100644 --- a/src/ca/cac.h +++ b/src/ca/cac.h @@ -41,11 +41,12 @@ # include "shareLib.h" #endif - #include "nciu.h" +#include "comBuf.h" #include "bhe.h" #include "cacIO.h" #include "netIO.h" +#include "localHostName.h" class netWriteNotifyIO; class netReadNotifyIO; @@ -94,6 +95,15 @@ private: epicsMutex mutex; }; +class cacComBufMemoryManager : public comBufMemoryManager +{ +public: + void * allocate ( size_t ) throw ( std::bad_alloc ); + void release ( void * ) throw (); +private: + tsFreeList < class comBuf, 0x20 > freeList; +}; + class cacDisconnectChannelPrivate { // X aCC 655 public: virtual void disconnectChannel ( epicsGuard < callbackMutex > &, @@ -128,7 +138,7 @@ public: unsigned minorVersionNumber, const osiSockAddr &, const epicsTime & currentTime ); - void uninstallChannel ( nciu & ); + void destroyChannel ( nciu & ); cacChannel & createChannel ( const char *name_str, cacChannelNotify &chan, cacChannel::priLev pri ); void registerService ( cacService &service ); @@ -188,10 +198,10 @@ public: void uninstallIIU ( tcpiiu & ); private: - ipAddrToAsciiEngine ipToAEngine; - cacServiceList services; - chronIntIdResTable - < nciu > chanTable; + localHostName hostNameCache; + ipAddrToAsciiEngine ipToAEngine; + cacServiceList services; + chronIntIdResTable < nciu > chanTable; // // !!!! There is at this point no good reason // !!!! to maintain one IO table for all types of @@ -204,41 +214,46 @@ private: // !!!! approach would also probably be safer in // !!!! terms of detecting damaged protocol. // - chronIntIdResTable - < baseNMIU > ioTable; - chronIntIdResTable - < CASG > sgTable; - resTable - < bhe, inetAddrID > beaconTable; - resTable - < tcpiiu, caServerID > serverTable; + chronIntIdResTable < baseNMIU > ioTable; + chronIntIdResTable < CASG > sgTable; + resTable < bhe, inetAddrID > beaconTable; + resTable < tcpiiu, caServerID > serverTable; tsFreeList < class netReadNotifyIO, 1024, epicsMutexNOOP > - freeListReadNotifyIO; + freeListReadNotifyIO; tsFreeList < class netWriteNotifyIO, 1024, epicsMutexNOOP > - freeListWriteNotifyIO; + freeListWriteNotifyIO; tsFreeList < class netSubscription, 1024, epicsMutexNOOP > - freeListSubscription; - epicsTime programBeginTime; - double connTMO; + freeListSubscription; + tsFreeList < class nciu, 1024 > channelFreeList; + tsFreeList + < class msgForMultiplyDefinedPV, 16 > + mdpvFreeList; + cacComBufMemoryManager comBufMemMgr; + bheFreeStore bheFreeList; + epicsTime programBeginTime; + double connTMO; // **** lock hierarchy **** // callback lock must always be acquired before // the primary mutex if both locks are needed - callbackMutex cbMutex; - mutable cacMutex mutex; - epicsEvent iiuUninstall; - epicsTimerQueueActive & timerQueue; - char * pUserName; - class udpiiu * pudpiiu; - void * tcpSmallRecvBufFreeList; - void * tcpLargeRecvBufFreeList; - cacNotify & notify; - epicsThreadId initializingThreadsId; - unsigned initializingThreadsPriority; - unsigned maxRecvBytesTCP; - bool preemptiveCallbackEnabled; + callbackMutex cbMutex; + mutable cacMutex mutex; + epicsEvent iiuUninstall; + epicsSingleton + < cacServiceList >::reference + globalServiceList; + epicsTimerQueueActive & timerQueue; + char * pUserName; + class udpiiu * pudpiiu; + void * tcpSmallRecvBufFreeList; + void * tcpLargeRecvBufFreeList; + cacNotify & notify; + epicsThreadId initializingThreadsId; + unsigned initializingThreadsPriority; + unsigned maxRecvBytesTCP; + bool preemptiveCallbackEnabled; void privateUninstallIIU ( epicsGuard < callbackMutex > &, tcpiiu &iiu ); void run (); diff --git a/src/ca/cacChannel.cpp b/src/ca/cacChannel.cpp index 49ab07f5f..1746dae56 100644 --- a/src/ca/cacChannel.cpp +++ b/src/ca/cacChannel.cpp @@ -20,6 +20,7 @@ * Author: Jeff Hill */ +#include #include #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" @@ -72,7 +73,9 @@ bool cacChannel::connected () const void cacChannel::hostName ( char *pBuf, unsigned bufLength ) const { if ( bufLength ) { - pLocalHostNameAtLoadTime->copy ( pBuf, bufLength ); + epicsSingleton < localHostName >::reference + ref ( localHostNameAtLoadTime ); + ref->copy ( pBuf, bufLength ); } } @@ -80,7 +83,22 @@ void cacChannel::hostName ( char *pBuf, unsigned bufLength ) const // the default is to assume that it is a locally hosted channel const char * cacChannel::pHostName () const { - return pLocalHostNameAtLoadTime->pointer (); + epicsSingleton < localHostName >::reference + ref ( localHostNameAtLoadTime ); + return ref->pointer (); +} + +// ms visual c++ 7.0 appears to require these when they +// are not called? +void cacChannel::operator delete ( void * ) +{ + throw std::logic_error ( + "why is the compiler calling cacChannel::operator delete?" ); +} +void cacChannel::operator delete [] ( void * ) +{ + throw std::logic_error ( + "why is the compiler calling cacChannel::operator delete?" ); } diff --git a/src/ca/cacIO.h b/src/ca/cacIO.h index 102b5a745..ff03f70f2 100644 --- a/src/ca/cacIO.h +++ b/src/ca/cacIO.h @@ -159,8 +159,8 @@ public: cacChannel ( cacChannelNotify & ); cacChannelNotify & notify () const; - virtual ~cacChannel () = 0; - virtual const char *pName () const = 0; + virtual void destroy () = 0; + virtual const char * pName () const = 0; // not thread safe virtual void show ( unsigned level ) const = 0; virtual void initiateConnect () = 0; virtual ioStatus read ( unsigned type, arrayElementCount count, @@ -181,8 +181,7 @@ public: virtual bool ca_v42_ok () const; // defaults to true virtual bool connected () const; // defaults to true virtual void hostName ( - char *pBuf, unsigned bufLength ) const; // defaults to local host name - + char * pBuf, unsigned bufLength ) const; // defaults to local host name virtual const char * pHostName () const; // exceptions @@ -198,10 +197,17 @@ public: class msgBodyCacheTooSmall {}; // hopefully this one goes away in the future class requestTimedOut {}; +protected: + virtual ~cacChannel () = 0; + private: cacChannelNotify & callback; cacChannel ( const cacChannel & ); cacChannel & operator = ( const cacChannel & ); + void * operator new ( size_t ); + void * operator new [] ( size_t ); + void operator delete ( void * ); + void operator delete [] ( void * ); }; class cacNotify { // X aCC 655 @@ -244,7 +250,7 @@ private: }; template < class T > class epicsSingleton; -epicsShareExtern epicsSingleton < cacServiceList > pGlobalServiceListCAC; +epicsShareExtern epicsSingleton < cacServiceList > globalServiceListCAC; epicsShareFunc int epicsShareAPI ca_register_service ( cacService *pService ); diff --git a/src/ca/cacServiceList.cpp b/src/ca/cacServiceList.cpp index 66eb9bc82..90a57a308 100644 --- a/src/ca/cacServiceList.cpp +++ b/src/ca/cacServiceList.cpp @@ -30,7 +30,7 @@ #include "epicsGuard.h" #include "cacIO.h" -epicsShareDef epicsSingleton < cacServiceList > pGlobalServiceListCAC; +epicsShareDef epicsSingleton < cacServiceList > globalServiceListCAC; cacServiceList::cacServiceList () { diff --git a/src/ca/casw.cpp b/src/ca/casw.cpp index e719bbce4..aa652b1c0 100644 --- a/src/ca/casw.cpp +++ b/src/ca/casw.cpp @@ -31,8 +31,29 @@ #include "udpiiu.h" #include "inetAddrID.h" +// using a wrapper class around the free list avoids +// Tornado 2.0.1 GNU compiler bugs +class bheFreeStoreMgr : public bheMemoryManager { +public: + void * allocate ( size_t ); + void release ( void * ); +private: + tsFreeList < class bhe, 0x100 > freeList; +}; + +void * bheFreeStoreMgr::allocate ( size_t size ) +{ + return freeList.allocate ( size ); +} + +void bheFreeStoreMgr::release ( void * pCadaver ) +{ + freeList.release ( pCadaver ); +} + int main ( int argc, char ** argv ) { + bheFreeStoreMgr bheFreeList; epicsTime programBeginTime = epicsTime::getCurrent (); bool validCommandLine = false; unsigned interest = 0u; @@ -230,10 +251,12 @@ int main ( int argc, char ** argv ) * time that we have seen a server's beacon * shortly after the program started up) */ - pBHE = new bhe ( currentTime, beaconNumber, ina ); + pBHE = new ( bheFreeList ) + bhe ( currentTime, beaconNumber, ina ); if ( pBHE ) { if ( beaconTable.add ( *pBHE ) < 0 ) { - pBHE->destroy (); + pBHE->~bhe (); + bheFreeList.release ( pBHE ); } } } diff --git a/src/ca/comBuf.cpp b/src/ca/comBuf.cpp index f2cb04ae2..e4aae6a85 100644 --- a/src/ca/comBuf.cpp +++ b/src/ca/comBuf.cpp @@ -22,14 +22,14 @@ * johill@lanl.gov */ +#include + #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #include "iocinf.h" #include "comBuf.h" -epicsSingleton < tsFreeList < class comBuf, 0x20 > > comBuf::pFreeList; - -bool comBuf::flushToWire ( wireSendAdapter & wire ) +bool comBuf::flushToWire ( wireSendAdapter & wire ) throw () { unsigned occupied = this->occupiedBytes (); while ( occupied ) { @@ -44,7 +44,7 @@ bool comBuf::flushToWire ( wireSendAdapter & wire ) return true; } -unsigned comBuf::push ( const epicsInt16 * pValue, unsigned nElem ) +unsigned comBuf::push ( const epicsInt16 * pValue, unsigned nElem ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -56,7 +56,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 ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -68,7 +68,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 ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -84,7 +84,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 ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -100,7 +100,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 ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -111,7 +111,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 ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); for ( unsigned i = 0u; i < nElem; i++ ) { @@ -124,7 +124,17 @@ unsigned comBuf::push ( const epicsFloat64 * pValue, unsigned nElem ) // throwing the exception from a function that isnt inline // shrinks the GNU compiled object code -void comBuf::throwInsufficentBytesException () +void comBuf::throwInsufficentBytesException () + throw ( insufficentBytesAvailable ) { throw insufficentBytesAvailable (); } + +void comBuf::operator delete ( void *pCadaver ) + throw ( std::logic_error ) +{ + throw std::logic_error + ( "compiler is confused about placement delete" ); +} + +comBufMemoryManager::~comBufMemoryManager () {} diff --git a/src/ca/comBuf.h b/src/ca/comBuf.h index fdc1a0b6a..73bfb858e 100644 --- a/src/ca/comBuf.h +++ b/src/ca/comBuf.h @@ -32,148 +32,164 @@ #include "epicsAssert.h" #include "epicsTypes.h" #include "tsFreeList.h" -#include "epicsSingleton.h" #include "tsDLList.h" #include "osiWireFormat.h" +#include "cxxCompilerDepPlacementDelete.h" static const unsigned comBufSize = 0x4000; -class wireSendAdapter { // X aCC 655 +// this wrapper avoids Tornado 2.0.1 compiler bugs +class comBufMemoryManager { public: - virtual unsigned sendBytes ( const void *pBuf, - unsigned nBytesInBuf ) = 0; + virtual ~comBufMemoryManager (); + virtual void * allocate ( size_t ) + throw ( std::bad_alloc ) = 0; + virtual void release ( void * ) + throw () = 0; }; -class wireRecvAdapter { // X aCC 655 +class wireSendAdapter { // X aCC 655 +public: + virtual unsigned sendBytes ( const void *pBuf, + unsigned nBytesInBuf ) throw () = 0; +}; + +class wireRecvAdapter { // X aCC 655 public: virtual unsigned recvBytes ( void *pBuf, - unsigned nBytesInBuf ) = 0; + unsigned nBytesInBuf ) throw () = 0; }; class comBuf : public tsDLNode < comBuf > { public: - comBuf (); - void destroy (); - unsigned unoccupiedBytes () const; - unsigned occupiedBytes () const; - unsigned uncommittedBytes () const; - static unsigned capacityBytes (); - void clear (); - unsigned copyInBytes ( const void *pBuf, unsigned nBytes ); - unsigned push ( comBuf & ); - bool push ( const epicsInt8 & value ); - bool push ( const epicsUInt8 & value ); - bool push ( const epicsInt16 & value ); - bool push ( const epicsUInt16 & value ); - bool push ( const epicsInt32 & value ); - bool push ( const epicsUInt32 & value ); - bool push ( const epicsFloat32 & value ); - bool push ( const epicsFloat64 & value ); - bool push ( const epicsOldString & value ); - unsigned push ( const epicsInt8 *pValue, unsigned nElem ); - unsigned push ( const epicsUInt8 *pValue, unsigned nElem ); - unsigned push ( const epicsInt16 *pValue, unsigned nElem ); - unsigned push ( const epicsUInt16 *pValue, unsigned nElem ); - unsigned push ( const epicsInt32 *pValue, unsigned nElem ); - unsigned push ( const epicsUInt32 *pValue, unsigned nElem ); - unsigned push ( const epicsFloat32 *pValue, unsigned nElem ); - unsigned push ( const epicsFloat64 *pValue, unsigned nElem ); - unsigned push ( const epicsOldString *pValue, unsigned nElem ); - void commitIncomming (); - void clearUncommittedIncomming (); - bool copyInAllBytes ( const void *pBuf, unsigned nBytes ); - unsigned copyOutBytes ( void *pBuf, unsigned nBytes ); - bool copyOutAllBytes ( void *pBuf, unsigned nBytes ); - unsigned removeBytes ( unsigned nBytes ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); - bool flushToWire ( wireSendAdapter & ); - unsigned fillFromWire ( wireRecvAdapter & ); - epicsUInt8 popUInt8 (); - epicsUInt16 popUInt16 (); - epicsUInt32 popUInt32 (); - static void throwInsufficentBytesException (); class insufficentBytesAvailable {}; -protected: - ~comBuf (); + comBuf () throw(); + unsigned unoccupiedBytes () const throw(); + unsigned occupiedBytes () const throw(); + unsigned uncommittedBytes () const throw(); + static unsigned capacityBytes () throw(); + void clear () throw (); + unsigned copyInBytes ( const void *pBuf, unsigned nBytes ) throw(); + unsigned push ( comBuf & ) throw(); + bool push ( const epicsInt8 & value ) throw(); + bool push ( const epicsUInt8 & value ) throw(); + bool push ( const epicsInt16 & value ) throw(); + bool push ( const epicsUInt16 & value ) throw(); + bool push ( const epicsInt32 & value ) throw(); + bool push ( const epicsUInt32 & value ) throw(); + bool push ( const epicsFloat32 & value ) throw(); + bool push ( const epicsFloat64 & value ) throw(); + bool push ( const epicsOldString & value ) throw(); + unsigned push ( const epicsInt8 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsUInt8 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsInt16 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsUInt16 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsInt32 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsUInt32 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsFloat32 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsFloat64 *pValue, unsigned nElem ) throw(); + unsigned push ( const epicsOldString *pValue, unsigned nElem ) throw(); + void commitIncomming () throw(); + void clearUncommittedIncomming () throw(); + bool copyInAllBytes ( const void *pBuf, unsigned nBytes ) throw(); + unsigned copyOutBytes ( void *pBuf, unsigned nBytes ) throw(); + bool copyOutAllBytes ( void *pBuf, unsigned nBytes ) throw(); + unsigned removeBytes ( unsigned nBytes ) throw(); + bool flushToWire ( wireSendAdapter & ) throw (); + unsigned fillFromWire ( wireRecvAdapter & ) throw (); + epicsUInt8 popUInt8 () + throw ( comBuf::insufficentBytesAvailable ); + epicsUInt16 popUInt16 () + throw ( comBuf::insufficentBytesAvailable ); + epicsUInt32 popUInt32 () + throw ( comBuf::insufficentBytesAvailable ); + static void throwInsufficentBytesException () + throw ( comBuf::insufficentBytesAvailable ); + void * operator new ( size_t size, + comBufMemoryManager & ) throw ( std::bad_alloc ); +# ifdef CXX_PLACEMENT_DELETE + void operator delete ( void *, + comBufMemoryManager & ) throw (); +# endif private: unsigned commitIndex; unsigned nextWriteIndex; unsigned nextReadIndex; epicsUInt8 buf [ comBufSize ]; - unsigned unoccupiedElem ( unsigned elemSize, unsigned nElem ); - unsigned occupiedElem ( unsigned elemSize, unsigned nElem ); - static epicsSingleton < tsFreeList < class comBuf, 0x20 > > pFreeList; + unsigned unoccupiedElem ( unsigned elemSize, unsigned nElem ) throw (); + unsigned occupiedElem ( unsigned elemSize, unsigned nElem ) throw (); + void * operator new ( size_t size ) throw ( std::bad_alloc ); + void operator delete ( void * ) throw ( std::logic_error ); + void * operator new [] ( size_t size ) throw ( std::bad_alloc ); + void operator delete [] ( void * ) throw ( std::logic_error ); }; -inline comBuf::comBuf () : commitIndex ( 0u ), +inline void * comBuf::operator new ( size_t size, + comBufMemoryManager & mgr ) + throw ( std::bad_alloc ) +{ + return mgr.allocate ( size ); +} + +#ifdef CXX_PLACEMENT_DELETE +inline void comBuf::operator delete ( void * pCadaver, + comBufMemoryManager & mgr ) throw () +{ + mgr.release ( pCadaver ); +} +#endif + +inline comBuf::comBuf () throw () : commitIndex ( 0u ), nextWriteIndex ( 0u ), nextReadIndex ( 0u ) { } -inline comBuf::~comBuf () -{ -} - -inline void comBuf::destroy () -{ - delete this; -} - -inline void comBuf::clear () +inline void comBuf::clear () throw () { this->commitIndex = 0u; this->nextWriteIndex = 0u; this->nextReadIndex = 0u; } -inline void * comBuf::operator new ( size_t size ) -{ - return comBuf::pFreeList->allocate ( size ); -} - -inline void comBuf::operator delete ( void *pCadaver, size_t size ) -{ - comBuf::pFreeList->release ( pCadaver, size ); -} - -inline unsigned comBuf::unoccupiedBytes () const +inline unsigned comBuf::unoccupiedBytes () const throw () { return sizeof ( this->buf ) - this->nextWriteIndex; } -inline unsigned comBuf::occupiedBytes () const +inline unsigned comBuf::occupiedBytes () const throw () { return this->commitIndex - this->nextReadIndex; } -inline unsigned comBuf::uncommittedBytes () const +inline unsigned comBuf::uncommittedBytes () const throw () { return this->nextWriteIndex - this->commitIndex; } -inline unsigned comBuf::push ( comBuf & bufIn ) +inline unsigned comBuf::push ( comBuf & bufIn ) throw () { - unsigned nBytes = this->copyInBytes ( &bufIn.buf[bufIn.nextReadIndex], - bufIn.commitIndex - bufIn.nextReadIndex ); + unsigned nBytes = this->copyInBytes ( + & bufIn.buf[ bufIn.nextReadIndex ], + bufIn.commitIndex - bufIn.nextReadIndex ); bufIn.nextReadIndex += nBytes; return nBytes; } -inline unsigned comBuf::capacityBytes () +inline unsigned comBuf::capacityBytes () throw () { return comBufSize; } -inline unsigned comBuf::fillFromWire ( wireRecvAdapter & wire ) +inline unsigned comBuf::fillFromWire ( wireRecvAdapter & wire ) throw () { - unsigned nNewBytes = wire.recvBytes ( &this->buf[this->nextWriteIndex], - sizeof ( this->buf ) - this->nextWriteIndex ); + unsigned nNewBytes = wire.recvBytes ( + & this->buf[this->nextWriteIndex], + sizeof ( this->buf ) - this->nextWriteIndex ); this->nextWriteIndex += nNewBytes; return nNewBytes; } -inline unsigned comBuf::unoccupiedElem ( unsigned elemSize, unsigned nElem ) +inline unsigned comBuf::unoccupiedElem ( unsigned elemSize, unsigned nElem ) throw () { unsigned avail = this->unoccupiedBytes (); if ( elemSize * nElem > avail ) { @@ -182,7 +198,7 @@ inline unsigned comBuf::unoccupiedElem ( unsigned elemSize, unsigned nElem ) return nElem; } -inline bool comBuf::push ( const epicsInt8 & value ) +inline bool comBuf::push ( const epicsInt8 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -192,7 +208,7 @@ inline bool comBuf::push ( const epicsInt8 & value ) return true; } -inline bool comBuf::push ( const epicsUInt8 & value ) +inline bool comBuf::push ( const epicsUInt8 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -201,7 +217,7 @@ inline bool comBuf::push ( const epicsUInt8 & value ) return true; } -inline bool comBuf::push ( const epicsInt16 & value ) +inline bool comBuf::push ( const epicsInt16 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -213,7 +229,7 @@ inline bool comBuf::push ( const epicsInt16 & value ) return true; } -inline bool comBuf::push ( const epicsUInt16 & value ) +inline bool comBuf::push ( const epicsUInt16 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -225,7 +241,7 @@ inline bool comBuf::push ( const epicsUInt16 & value ) return true; } -inline bool comBuf::push ( const epicsInt32 & value ) +inline bool comBuf::push ( const epicsInt32 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -241,7 +257,7 @@ inline bool comBuf::push ( const epicsInt32 & value ) return true; } -inline bool comBuf::push ( const epicsUInt32 & value ) +inline bool comBuf::push ( const epicsUInt32 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -257,7 +273,7 @@ inline bool comBuf::push ( const epicsUInt32 & value ) return true; } -inline bool comBuf::push ( const epicsFloat32 & value ) +inline bool comBuf::push ( const epicsFloat32 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -268,7 +284,7 @@ inline bool comBuf::push ( const epicsFloat32 & value ) return true; } -inline bool comBuf::push ( const epicsFloat64 & value ) +inline bool comBuf::push ( const epicsFloat64 & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -279,7 +295,7 @@ inline bool comBuf::push ( const epicsFloat64 & value ) return true; } -inline bool comBuf::push ( const epicsOldString & value ) +inline bool comBuf::push ( const epicsOldString & value ) throw () { if ( this->unoccupiedBytes () < sizeof ( value ) ) { return false; @@ -289,17 +305,17 @@ inline bool comBuf::push ( const epicsOldString & value ) return true; } -inline unsigned comBuf::push ( const epicsInt8 *pValue, unsigned nElem ) +inline unsigned comBuf::push ( const epicsInt8 *pValue, unsigned nElem ) throw () { return copyInBytes ( pValue, nElem ); } -inline unsigned comBuf::push ( const epicsUInt8 *pValue, unsigned nElem ) +inline unsigned comBuf::push ( const epicsUInt8 *pValue, unsigned nElem ) throw () { return copyInBytes ( pValue, nElem ); } -inline unsigned comBuf::push ( const epicsOldString *pValue, unsigned nElem ) +inline unsigned comBuf::push ( const epicsOldString *pValue, unsigned nElem ) throw () { nElem = this->unoccupiedElem ( sizeof (*pValue), nElem ); unsigned size = nElem * sizeof ( *pValue ); @@ -308,7 +324,7 @@ inline unsigned comBuf::push ( const epicsOldString *pValue, unsigned nElem ) return nElem; } -inline unsigned comBuf::occupiedElem ( unsigned elemSize, unsigned nElem ) +inline unsigned comBuf::occupiedElem ( unsigned elemSize, unsigned nElem ) throw () { unsigned avail = this->occupiedBytes (); if ( elemSize * nElem > avail ) { @@ -317,17 +333,17 @@ inline unsigned comBuf::occupiedElem ( unsigned elemSize, unsigned nElem ) return nElem; } -inline void comBuf::commitIncomming () +inline void comBuf::commitIncomming () throw () { this->commitIndex = this->nextWriteIndex; } -inline void comBuf::clearUncommittedIncomming () +inline void comBuf::clearUncommittedIncomming () throw () { this->nextWriteIndex = this->commitIndex; } -inline bool comBuf::copyInAllBytes ( const void *pBuf, unsigned nBytes ) +inline bool comBuf::copyInAllBytes ( const void *pBuf, unsigned nBytes ) throw () { if ( nBytes <= this->unoccupiedBytes () ) { memcpy ( & this->buf[this->nextWriteIndex], pBuf, nBytes ); @@ -337,7 +353,7 @@ inline bool comBuf::copyInAllBytes ( const void *pBuf, unsigned nBytes ) return false; } -inline unsigned comBuf::copyInBytes ( const void *pBuf, unsigned nBytes ) +inline unsigned comBuf::copyInBytes ( const void *pBuf, unsigned nBytes ) throw () { if ( nBytes > 0u ) { unsigned available = this->unoccupiedBytes (); @@ -350,7 +366,7 @@ inline unsigned comBuf::copyInBytes ( const void *pBuf, unsigned nBytes ) return nBytes; } -inline bool comBuf::copyOutAllBytes ( void * pBuf, unsigned nBytes ) +inline bool comBuf::copyOutAllBytes ( void * pBuf, unsigned nBytes ) throw () { if ( nBytes <= this->occupiedBytes () ) { memcpy ( pBuf, &this->buf[this->nextReadIndex], nBytes); @@ -360,7 +376,7 @@ inline bool comBuf::copyOutAllBytes ( void * pBuf, unsigned nBytes ) return false; } -inline unsigned comBuf::copyOutBytes ( void *pBuf, unsigned nBytes ) +inline unsigned comBuf::copyOutBytes ( void *pBuf, unsigned nBytes ) throw () { unsigned occupied = this->occupiedBytes (); if ( nBytes > occupied ) { @@ -371,7 +387,7 @@ inline unsigned comBuf::copyOutBytes ( void *pBuf, unsigned nBytes ) return nBytes; } -inline unsigned comBuf::removeBytes ( unsigned nBytes ) +inline unsigned comBuf::removeBytes ( unsigned nBytes ) throw () { unsigned occupied = this->occupiedBytes (); if ( nBytes > occupied ) { @@ -382,6 +398,7 @@ inline unsigned comBuf::removeBytes ( unsigned nBytes ) } inline epicsUInt8 comBuf::popUInt8 () + throw ( comBuf::insufficentBytesAvailable ) { if ( this->occupiedBytes () < 1u ) { comBuf::throwInsufficentBytesException (); @@ -390,6 +407,7 @@ inline epicsUInt8 comBuf::popUInt8 () } inline epicsUInt16 comBuf::popUInt16 () + throw ( comBuf::insufficentBytesAvailable ) { if ( this->occupiedBytes () < 2u ) { comBuf::throwInsufficentBytesException (); @@ -399,7 +417,8 @@ inline epicsUInt16 comBuf::popUInt16 () return static_cast < epicsUInt16 > ( byte1 << 8u | byte2 ); } -inline epicsUInt32 comBuf::popUInt32 () +inline epicsUInt32 comBuf::popUInt32 () + throw ( comBuf::insufficentBytesAvailable ) { if ( this->occupiedBytes () < 4u ) { comBuf::throwInsufficentBytesException (); diff --git a/src/ca/comQueRecv.cpp b/src/ca/comQueRecv.cpp index dc740ab09..86f1c058d 100644 --- a/src/ca/comQueRecv.cpp +++ b/src/ca/comQueRecv.cpp @@ -27,25 +27,27 @@ #include "iocinf.h" #include "virtualCircuit.h" -comQueRecv::comQueRecv (): nBytesPending ( 0u ) +comQueRecv::comQueRecv ( comBufMemoryManager & comBufMemoryManagerIn ) throw () : + comBufMemMgr ( comBufMemoryManagerIn ), nBytesPending ( 0u ) { } -comQueRecv::~comQueRecv () +comQueRecv::~comQueRecv () throw () { this->clear (); } -void comQueRecv::clear () +void comQueRecv::clear () throw () { comBuf *pBuf; while ( ( pBuf = this->bufs.get () ) ) { - pBuf->destroy (); + pBuf->~comBuf (); + this->comBufMemMgr.release ( pBuf ); } this->nBytesPending = 0u; } -unsigned comQueRecv::copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ) +unsigned comQueRecv::copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ) throw () { unsigned totalBytes = 0u; do { @@ -57,7 +59,8 @@ unsigned comQueRecv::copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ) totalBytes += pComBuf->copyOutBytes ( &pBuf[totalBytes], nBytes - totalBytes ); if ( pComBuf->occupiedBytes () == 0u ) { this->bufs.remove ( *pComBuf ); - pComBuf->destroy (); + pComBuf->~comBuf (); + this->comBufMemMgr.release ( pComBuf ); } } while ( totalBytes < nBytes ); @@ -65,7 +68,7 @@ unsigned comQueRecv::copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ) return totalBytes; } -unsigned comQueRecv::removeBytes ( unsigned nBytes ) +unsigned comQueRecv::removeBytes ( unsigned nBytes ) throw () { unsigned totalBytes = 0u; unsigned bytesLeft = nBytes; @@ -78,7 +81,8 @@ unsigned comQueRecv::removeBytes ( unsigned nBytes ) unsigned nBytesThisTime = pComBuf->removeBytes ( bytesLeft ); if ( pComBuf->occupiedBytes () == 0u ) { this->bufs.remove ( *pComBuf ); - pComBuf->destroy (); + pComBuf->~comBuf (); + this->comBufMemMgr.release ( pComBuf ); } if ( nBytesThisTime == 0u) { break; @@ -91,6 +95,7 @@ unsigned comQueRecv::removeBytes ( unsigned nBytes ) } void comQueRecv::popString ( epicsOldString *pStr ) + throw ( comBuf::insufficentBytesAvailable ) { for ( unsigned i = 0u; i < sizeof ( *pStr ); i++ ) { pStr[0][i] = this->popInt8 (); @@ -98,6 +103,7 @@ void comQueRecv::popString ( epicsOldString *pStr ) } void comQueRecv::pushLastComBufReceived ( comBuf & bufIn ) + throw () { bufIn.commitIncomming (); comBuf * pComBuf = this->bufs.last (); @@ -113,7 +119,8 @@ void comQueRecv::pushLastComBufReceived ( comBuf & bufIn ) this->bufs.add ( bufIn ); } else { - bufIn.destroy (); + bufIn.~comBuf (); + this->comBufMemMgr.release ( & bufIn ); } } @@ -121,6 +128,7 @@ void comQueRecv::pushLastComBufReceived ( comBuf & bufIn ) // 2) using canonical unsigned tmp avoids ANSI C conversions to int // 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) epicsUInt16 comQueRecv::multiBufferPopUInt16 () + throw ( comBuf::insufficentBytesAvailable ) { epicsUInt16 tmp; if ( this->occupiedBytes() >= sizeof (tmp) ) { @@ -139,6 +147,7 @@ epicsUInt16 comQueRecv::multiBufferPopUInt16 () // 2) using canonical unsigned temporary avoids ANSI C conversions to int // 3) cast required because sizeof(unsigned) >= sizeof(epicsUInt32) epicsUInt32 comQueRecv::multiBufferPopUInt32 () + throw ( comBuf::insufficentBytesAvailable ) { epicsUInt32 tmp; if ( this->occupiedBytes() >= sizeof (tmp) ) { @@ -159,8 +168,9 @@ epicsUInt32 comQueRecv::multiBufferPopUInt32 () return tmp; } -void comQueRecv::removeAndDestroyBuf ( comBuf & buf ) +void comQueRecv::removeAndDestroyBuf ( comBuf & buf ) throw () { this->bufs.remove ( buf ); - buf.destroy (); + buf.~comBuf (); + this->comBufMemMgr.release ( & buf ); } diff --git a/src/ca/comQueRecv.h b/src/ca/comQueRecv.h index a338fb2d9..e24ca6b26 100644 --- a/src/ca/comQueRecv.h +++ b/src/ca/comQueRecv.h @@ -29,50 +29,54 @@ class comQueRecv { public: - comQueRecv (); - ~comQueRecv (); - unsigned occupiedBytes () const; - unsigned copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ); - unsigned removeBytes ( unsigned nBytes ); - void pushLastComBufReceived ( comBuf & ); - void clear (); - epicsInt8 popInt8 (); - epicsUInt8 popUInt8 (); - epicsInt16 popInt16 (); - epicsUInt16 popUInt16 (); - epicsInt32 popInt32 (); - epicsUInt32 popUInt32 (); - epicsFloat32 popFloat32 (); - epicsFloat64 popFloat64 (); - void popString ( epicsOldString * ); - class insufficentBytesAvailable {}; + comQueRecv ( comBufMemoryManager & ) throw (); + ~comQueRecv () throw (); + unsigned occupiedBytes () const throw (); + unsigned copyOutBytes ( epicsInt8 *pBuf, unsigned nBytes ) throw (); + unsigned removeBytes ( unsigned nBytes ) throw (); + void pushLastComBufReceived ( comBuf & ) throw (); + void clear () throw (); + epicsInt8 popInt8 () throw ( comBuf::insufficentBytesAvailable ); + epicsUInt8 popUInt8 () throw ( comBuf::insufficentBytesAvailable ); + epicsInt16 popInt16 () throw ( comBuf::insufficentBytesAvailable ); + epicsUInt16 popUInt16 () throw ( comBuf::insufficentBytesAvailable ); + epicsInt32 popInt32 () throw ( comBuf::insufficentBytesAvailable ); + epicsUInt32 popUInt32 () throw ( comBuf::insufficentBytesAvailable ); + epicsFloat32 popFloat32 () throw ( comBuf::insufficentBytesAvailable ); + epicsFloat64 popFloat64 () throw ( comBuf::insufficentBytesAvailable ); + void popString ( epicsOldString * ) throw ( comBuf::insufficentBytesAvailable ); private: tsDLList < comBuf > bufs; + comBufMemoryManager & comBufMemMgr; unsigned nBytesPending; - epicsUInt16 multiBufferPopUInt16 (); - epicsUInt32 multiBufferPopUInt32 (); - void removeAndDestroyBuf ( comBuf & ); - comQueRecv ( const comQueRecv & ); - comQueRecv & operator = ( const comQueRecv & ); + epicsUInt16 multiBufferPopUInt16 () throw ( comBuf::insufficentBytesAvailable ); + epicsUInt32 multiBufferPopUInt32 () throw ( comBuf::insufficentBytesAvailable ); + void removeAndDestroyBuf ( comBuf & ) throw (); + comQueRecv ( const comQueRecv & ) throw (); + comQueRecv & operator = ( const comQueRecv & ) throw (); }; inline unsigned comQueRecv::occupiedBytes () const + throw () { return this->nBytesPending; } inline epicsInt8 comQueRecv::popInt8 () + throw ( comBuf::insufficentBytesAvailable ) { return static_cast < epicsInt8 > ( this->popUInt8() ); } inline epicsInt16 comQueRecv::popInt16 () + throw ( comBuf::insufficentBytesAvailable ) { return static_cast < epicsInt16 > ( this->popInt8() << 8u | this->popInt8() << 0u ); } inline epicsInt32 comQueRecv::popInt32 () + throw ( comBuf::insufficentBytesAvailable ) { epicsInt32 tmp ; tmp = this->popInt8() << 24u; @@ -83,6 +87,7 @@ inline epicsInt32 comQueRecv::popInt32 () } inline epicsFloat32 comQueRecv::popFloat32 () + throw ( comBuf::insufficentBytesAvailable ) { epicsFloat32 tmp; epicsUInt8 wire[ sizeof ( tmp ) ]; @@ -95,6 +100,7 @@ inline epicsFloat32 comQueRecv::popFloat32 () } inline epicsFloat64 comQueRecv::popFloat64 () + throw ( comBuf::insufficentBytesAvailable ) { epicsFloat64 tmp; epicsUInt8 wire[ sizeof ( tmp ) ]; @@ -106,7 +112,8 @@ inline epicsFloat64 comQueRecv::popFloat64 () return tmp; } -inline epicsUInt8 comQueRecv::popUInt8 () +inline epicsUInt8 comQueRecv::popUInt8 () + throw ( comBuf::insufficentBytesAvailable ) { comBuf * pComBuf = this->bufs.first (); if ( ! pComBuf ) { @@ -122,6 +129,7 @@ inline epicsUInt8 comQueRecv::popUInt8 () // optimization here complicates this function somewhat inline epicsUInt16 comQueRecv::popUInt16 () + throw ( comBuf::insufficentBytesAvailable ) { comBuf *pComBuf = this->bufs.first (); if ( ! pComBuf ) { @@ -147,6 +155,7 @@ inline epicsUInt16 comQueRecv::popUInt16 () // optimization here complicates this function somewhat inline epicsUInt32 comQueRecv::popUInt32 () + throw ( comBuf::insufficentBytesAvailable ) { comBuf *pComBuf = this->bufs.first (); if ( ! pComBuf ) { diff --git a/src/ca/comQueSend.cpp b/src/ca/comQueSend.cpp index 6ddd4c2f6..7a8ae98eb 100644 --- a/src/ca/comQueSend.cpp +++ b/src/ca/comQueSend.cpp @@ -80,29 +80,36 @@ const char cacNillBytes [] = 0, 0, 0, 0 }; -comQueSend::comQueSend ( wireSendAdapter & wireIn ) : - wire ( wireIn ), nBytesPending ( 0u ) +comQueSend::comQueSend ( wireSendAdapter & wireIn, + comBufMemoryManager & comBufMemMgrIn ) throw () : + comBufMemMgr ( comBufMemMgrIn ), wire ( wireIn ), + nBytesPending ( 0u ) { } -comQueSend::~comQueSend () +comQueSend::~comQueSend () throw () { this->clear (); } -void comQueSend::clear () +void comQueSend::clear () throw () { comBuf *pBuf; while ( ( pBuf = this->bufs.get () ) ) { this->nBytesPending -= pBuf->occupiedBytes (); - pBuf->destroy (); + pBuf->~comBuf (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + comBuf::operator delete ( pBuf, this->comBufMemMgr ); +# else + this->comBufMemMgr.release ( pBuf ); +# endif } this->pFirstUncommited = tsDLIter < comBuf > (); assert ( this->nBytesPending == 0 ); } -void comQueSend::clearUncommitted () +void comQueSend::clearUncommitted () throw () { while ( this->pFirstUncommited.valid() ) { tsDLIter < comBuf > next = this->pFirstUncommited; @@ -110,38 +117,44 @@ void comQueSend::clearUncommitted () this->pFirstUncommited->clearUncommittedIncomming (); if ( this->pFirstUncommited->occupiedBytes() == 0u ) { this->bufs.remove ( *this->pFirstUncommited ); - this->pFirstUncommited->destroy (); + this->pFirstUncommited->~comBuf (); +# if defined ( CXX_PLACEMENT_DELETE ) && 0 + comBuf::operator delete + ( this->pFirstUncommited.pointer(), this->comBufMemMgr ); +# else + this->comBufMemMgr.release ( this->pFirstUncommited.pointer() ); +# endif } this->pFirstUncommited = next; } } -void comQueSend::copy_dbr_string ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_string ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } -void comQueSend::copy_dbr_short ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_short ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } -void comQueSend::copy_dbr_float ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_float ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } -void comQueSend::copy_dbr_char ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_char ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } -void comQueSend::copy_dbr_long ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_long ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } -void comQueSend::copy_dbr_double ( const void *pValue, unsigned nElem ) +void comQueSend::copy_dbr_double ( const void *pValue, unsigned nElem ) throw () { this->push ( static_cast ( pValue ), nElem ); } @@ -188,7 +201,7 @@ const comQueSend::copyFunc_t comQueSend::dbrCopyVector [39] = { 0 // DBR_CLASS_NAME }; -comBuf * comQueSend::popNextComBufToSend () +comBuf * comQueSend::popNextComBufToSend () throw () { comBuf *pBuf = this->bufs.get (); if ( pBuf ) { @@ -211,7 +224,8 @@ comBuf * comQueSend::popNextComBufToSend () void comQueSend::insertRequestHeader ( ca_uint16_t request, ca_uint32_t payloadSize, ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, - ca_uint32_t requestDependent, bool v49Ok ) + ca_uint32_t requestDependent, bool v49Ok ) + throw ( cacChannel::outOfBounds ) { this->beginMsg (); if ( payloadSize < 0xffff && nElem < 0xffff ) { @@ -240,7 +254,7 @@ void comQueSend::insertRequestHeader ( void comQueSend::insertRequestWithPayLoad ( ca_uint16_t request, unsigned dataType, ca_uint32_t nElem, ca_uint32_t cid, ca_uint32_t requestDependent, const void * pPayload, - bool v49Ok ) + bool v49Ok ) throw ( cacChannel::outOfBounds ) { if ( ! this->dbr_type_ok ( dataType ) ) { throw cacChannel::badType(); @@ -285,7 +299,7 @@ void comQueSend::insertRequestWithPayLoad ( this->commitMsg (); } -void comQueSend::commitMsg () +void comQueSend::commitMsg () throw () { while ( this->pFirstUncommited.valid() ) { this->nBytesPending += this->pFirstUncommited->uncommittedBytes (); diff --git a/src/ca/comQueSend.h b/src/ca/comQueSend.h index f2f1aeecb..a30bd71c0 100644 --- a/src/ca/comQueSend.h +++ b/src/ca/comQueSend.h @@ -40,53 +40,56 @@ // class comQueSend { public: - comQueSend ( wireSendAdapter & ); - ~comQueSend (); - void clear (); - void beginMsg (); - void commitMsg (); - unsigned occupiedBytes () const; - bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const; - bool flushBlockThreshold ( unsigned nBytesThisMsg ) const; - bool dbr_type_ok ( unsigned type ); - void pushUInt16 ( const ca_uint16_t value ); - void pushUInt32 ( const ca_uint32_t value ); - void pushFloat32 ( const ca_float32_t value ); - void pushString ( const char *pVal, unsigned nChar ); + comQueSend ( wireSendAdapter &, comBufMemoryManager & ) throw (); + ~comQueSend () throw (); + void clear () throw (); + void beginMsg () throw (); + void commitMsg () throw (); + unsigned occupiedBytes () const throw (); + bool flushEarlyThreshold ( unsigned nBytesThisMsg ) const throw (); + bool flushBlockThreshold ( unsigned nBytesThisMsg ) const throw (); + bool dbr_type_ok ( unsigned type ) throw (); + void pushUInt16 ( const ca_uint16_t value ) throw (); + void pushUInt32 ( const ca_uint32_t value ) throw (); + void pushFloat32 ( const ca_float32_t value ) throw (); + void pushString ( const char *pVal, unsigned nChar ) throw (); void insertRequestHeader ( ca_uint16_t request, ca_uint32_t payloadSize, ca_uint16_t dataType, ca_uint32_t nElem, ca_uint32_t cid, - ca_uint32_t requestDependent, bool v49Ok ); + ca_uint32_t requestDependent, bool v49Ok ) + throw ( cacChannel::outOfBounds ); void insertRequestWithPayLoad ( ca_uint16_t request, unsigned dataType, ca_uint32_t nElem, - ca_uint32_t cid, ca_uint32_t requestDependent, const void * pPayload, - bool v49Ok ); - void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ); - comBuf * popNextComBufToSend (); + ca_uint32_t cid, ca_uint32_t requestDependent, + const void * pPayload, bool v49Ok ) + throw ( cacChannel::outOfBounds ); + void push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ) throw (); + comBuf * popNextComBufToSend () throw (); private: + comBufMemoryManager & comBufMemMgr; tsDLList < comBuf > bufs; tsDLIter < comBuf > pFirstUncommited; wireSendAdapter & wire; unsigned nBytesPending; - void copy_dbr_string ( const void *pValue, unsigned nElem ); - void copy_dbr_short ( const void *pValue, unsigned nElem ); - void copy_dbr_float ( const void *pValue, unsigned nElem ); - 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 & ); + void copy_dbr_string ( const void *pValue, unsigned nElem ) throw (); + void copy_dbr_short ( const void *pValue, unsigned nElem ) throw (); + void copy_dbr_float ( const void *pValue, unsigned nElem ) throw (); + void copy_dbr_char ( const void *pValue, unsigned nElem ) throw (); + void copy_dbr_long ( const void *pValue, unsigned nElem ) throw (); + void copy_dbr_double ( const void *pValue, unsigned nElem ) throw (); + void pushComBuf ( comBuf & ) throw (); typedef void ( comQueSend::*copyFunc_t ) ( const void *pValue, unsigned nElem ); static const copyFunc_t dbrCopyVector [39]; - void clearUncommitted (); + void clearUncommitted () throw (); // - // visual C++ version 6.0 does not allow out of + // visual C++ versions 6 & 7 do not allow out of // class member template function definition // template < class T > - inline void push ( const T *pVal, const unsigned nElem ) + inline void push ( const T *pVal, const unsigned nElem ) throw () { comBuf * pLastBuf = this->bufs.last (); unsigned nCopied; @@ -97,36 +100,37 @@ private: nCopied = 0u; } while ( nElem > nCopied ) { - comBuf * pComBuf = new comBuf; - unsigned nNew = pComBuf->push ( &pVal[nCopied], nElem - nCopied ); + comBuf * pComBuf = new ( this->comBufMemMgr ) comBuf; + unsigned nNew = pComBuf->push + ( &pVal[nCopied], nElem - nCopied ); nCopied += nNew; this->pushComBuf ( *pComBuf ); } } // - // visual C++ version 6.0 does not allow out of + // visual C++ versions 6 and 7 do not allow out of // class member template function definition // template < class T > - inline void push ( const T & val ) + inline void push ( const T & val ) throw () { - register comBuf * pComBuf = this->bufs.last (); + comBuf * pComBuf = this->bufs.last (); if ( pComBuf && pComBuf->push ( val ) ) { return; } - pComBuf = new comBuf; + pComBuf = new ( this->comBufMemMgr ) comBuf; assert ( pComBuf->push ( val ) ); this->pushComBuf ( *pComBuf ); } - comQueSend ( const comQueSend & ); - comQueSend & operator = ( const comQueSend & ); + comQueSend ( const comQueSend & ) throw (); + comQueSend & operator = ( const comQueSend & ) throw (); }; extern const char cacNillBytes[]; -inline bool comQueSend::dbr_type_ok ( unsigned type ) +inline bool comQueSend::dbr_type_ok ( unsigned type ) throw () { if ( type >= ( sizeof ( this->dbrCopyVector ) / sizeof ( this->dbrCopyVector[0] ) ) ) { return false; @@ -137,34 +141,34 @@ inline bool comQueSend::dbr_type_ok ( unsigned type ) return true; } -inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) +inline void comQueSend::pushUInt16 ( const ca_uint16_t value ) throw () { this->push ( value ); } -inline void comQueSend::pushUInt32 ( const ca_uint32_t value ) +inline void comQueSend::pushUInt32 ( const ca_uint32_t value ) throw () { this->push ( value ); } -inline void comQueSend::pushFloat32 ( const ca_float32_t value ) +inline void comQueSend::pushFloat32 ( const ca_float32_t value ) throw () { this->push ( value ); } -inline void comQueSend::pushString ( const char *pVal, unsigned nChar ) +inline void comQueSend::pushString ( const char *pVal, unsigned nChar ) throw () { this->push ( pVal, nChar ); } // it is assumed that dbr_type_ok() was called prior to calling this routine // to check the type code -inline void comQueSend::push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ) +inline void comQueSend::push_dbr_type ( unsigned type, const void *pVal, unsigned nElem ) throw () { ( this->*dbrCopyVector [type] ) ( pVal, nElem ); } -inline void comQueSend::pushComBuf ( comBuf & cb ) +inline void comQueSend::pushComBuf ( comBuf & cb ) throw () { this->bufs.add ( cb ); if ( ! this->pFirstUncommited.valid() ) { @@ -172,22 +176,22 @@ inline void comQueSend::pushComBuf ( comBuf & cb ) } } -inline unsigned comQueSend::occupiedBytes () const +inline unsigned comQueSend::occupiedBytes () const throw () { return this->nBytesPending; } -inline bool comQueSend::flushBlockThreshold ( unsigned nBytesThisMsg ) const +inline bool comQueSend::flushBlockThreshold ( unsigned nBytesThisMsg ) const throw () { return ( this->nBytesPending + nBytesThisMsg > 16 * comBuf::capacityBytes () ); } -inline bool comQueSend::flushEarlyThreshold ( unsigned nBytesThisMsg ) const +inline bool comQueSend::flushEarlyThreshold ( unsigned nBytesThisMsg ) const throw () { return ( this->nBytesPending + nBytesThisMsg > 4 * comBuf::capacityBytes () ); } -inline void comQueSend::beginMsg () +inline void comQueSend::beginMsg () throw () { if ( this->pFirstUncommited.valid() ) { this->clearUncommitted (); diff --git a/src/ca/getCallback.cpp b/src/ca/getCallback.cpp index 078e3c785..24957cbf7 100644 --- a/src/ca/getCallback.cpp +++ b/src/ca/getCallback.cpp @@ -24,12 +24,12 @@ * 505 665 1831 */ +#include + #define epicsExportSharedSymbols #include "iocinf.h" #include "oldAccess.h" -epicsSingleton < tsFreeList < class getCallback, 1024 > > getCallback::pFreeList; - getCallback::getCallback ( oldChannelNotify &chanIn, caEventCallBackFunc *pFuncIn, void *pPrivateIn ) : chan ( chanIn ), pFunc ( pFuncIn ), pPrivate ( pPrivateIn ) @@ -43,7 +43,7 @@ getCallback::~getCallback () void getCallback::completion ( unsigned type, arrayElementCount count, const void *pData ) { - struct event_handler_args args; + struct event_handler_args args; args.usr = this->pPrivate; args.chid = &this->chan; args.type = type; @@ -51,7 +51,7 @@ void getCallback::completion ( args.status = ECA_NORMAL; args.dbr = pData; ( *this->pFunc ) ( args ); - delete this; + this->chan.getClientCtx().destroyGetCallback ( *this ); } void getCallback::exception ( @@ -59,7 +59,7 @@ void getCallback::exception ( unsigned type, arrayElementCount count ) { if ( status != ECA_CHANDESTROY ) { - struct event_handler_args args; + struct event_handler_args args; args.usr = this->pPrivate; args.chid = &this->chan; args.type = type; @@ -68,6 +68,13 @@ void getCallback::exception ( args.dbr = 0; ( *this->pFunc ) ( args ); } - delete this; + this->chan.getClientCtx().destroyGetCallback ( *this ); } +void getCallback::operator delete ( void *pCadaver ) +{ + throw std::logic_error + ( "compiler is confused about placement delete" ); +} + + diff --git a/src/ca/getCopy.cpp b/src/ca/getCopy.cpp index 32133b273..e7cf8c837 100644 --- a/src/ca/getCopy.cpp +++ b/src/ca/getCopy.cpp @@ -24,6 +24,8 @@ * 505 665 1831 */ +#include + #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #define epicsExportSharedSymbols @@ -31,8 +33,6 @@ #include "oldAccess.h" #include "cac.h" -epicsSingleton < tsFreeList < class getCopy, 1024 > > getCopy::pFreeList; - getCopy::getCopy ( ca_client_context &cacCtxIn, oldChannelNotify &chanIn, unsigned typeIn, arrayElementCount countIn, void *pValueIn ) : count ( countIn ), cacCtx ( cacCtxIn ), chan ( chanIn ), pValue ( pValueIn ), @@ -50,11 +50,6 @@ void getCopy::cancel () this->cacCtx.decrementOutstandingIO ( this->ioSeqNo ); } -void getCopy::destroy () -{ - delete this; -} - void getCopy::completion ( unsigned typeIn, arrayElementCount countIn, const void *pDataIn ) { @@ -68,7 +63,7 @@ void getCopy::completion ( unsigned typeIn, "bad data type match in get copy back response", typeIn, countIn); } - delete this; + this->cacCtx.destroyGetCopy ( *this ); } void getCopy::exception ( @@ -79,7 +74,7 @@ void getCopy::exception ( __FILE__, __LINE__, this->chan, this->type, this->count, CA_OP_GET ); } - delete this; + this->cacCtx.destroyGetCopy ( *this ); } void getCopy::show ( unsigned level ) const @@ -92,3 +87,10 @@ void getCopy::show ( unsigned level ) const this->ioSeqNo, static_cast ( this->pValue ) ); } } + +void getCopy::operator delete ( void *pCadaver ) +{ + throw std::logic_error + ( "compiler is confused about placement delete" ); +} + diff --git a/src/ca/msgForMultiplyDefinedPV.cpp b/src/ca/msgForMultiplyDefinedPV.cpp index d34183427..87e970d54 100644 --- a/src/ca/msgForMultiplyDefinedPV.cpp +++ b/src/ca/msgForMultiplyDefinedPV.cpp @@ -24,6 +24,8 @@ * 505 665 1831 */ +#include + #define epicsAssertAuthor "Jeff Hill johill@lanl.gov" #include "iocinf.h" @@ -34,9 +36,6 @@ #include "caerr.h" // for ECA_DBLCHNL #undef epicsExportSharedSymbols -epicsSingleton < tsFreeList < class msgForMultiplyDefinedPV, 16 > > - msgForMultiplyDefinedPV::pFreeList; - msgForMultiplyDefinedPV::msgForMultiplyDefinedPV ( callbackMutex & mutexIn, cac & cacRefIn, const char * pChannelName, const char * pAcc, const osiSockAddr &rej ) : @@ -60,3 +59,10 @@ void msgForMultiplyDefinedPV::ioCompletionNotify ( const char * pHostNameRej ) } delete this; } + +void msgForMultiplyDefinedPV::operator delete ( void *pCadaver ) +{ + throw std::logic_error + ( "compiler is confused about placement delete" ); +} + diff --git a/src/ca/msgForMultiplyDefinedPV.h b/src/ca/msgForMultiplyDefinedPV.h index 043e0a8f3..0aa03acaf 100644 --- a/src/ca/msgForMultiplyDefinedPV.h +++ b/src/ca/msgForMultiplyDefinedPV.h @@ -29,8 +29,8 @@ #include "ipAddrToAsciiAsynchronous.h" #include "tsFreeList.h" -#include "epicsSingleton.h" #include "epicsMutex.h" +#include "cxxCompilerDepPlacementDelete.h" class cac; class callbackMutex; @@ -41,28 +41,35 @@ public: cac & cacRefIn, const char * pChannelName, const char * pAcc, const osiSockAddr & rej ); msgForMultiplyDefinedPV ( const osiSockAddr &addr, ipAddrToAsciiEngine &engine ); - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); + void * operator new ( size_t size, tsFreeList < class msgForMultiplyDefinedPV, 16 > & ); +# ifdef CXX_PLACEMENT_DELETE + void operator delete ( void *, tsFreeList < class msgForMultiplyDefinedPV, 16 > & ); +# endif private: void ioCompletionNotify ( const char *pHostName ); char acc[64]; char channel[64]; cac & cacRef; callbackMutex & mutex; - static epicsSingleton < tsFreeList < class msgForMultiplyDefinedPV, 16 > > pFreeList; msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & ); msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & ); + void * operator new ( size_t size ); + void operator delete ( void * ); }; -inline void * msgForMultiplyDefinedPV::operator new ( size_t size ) +inline void * msgForMultiplyDefinedPV::operator new ( size_t size, + tsFreeList < class msgForMultiplyDefinedPV, 16 > & freeList ) { - return msgForMultiplyDefinedPV::pFreeList->allocate ( size ); + return freeList.allocate ( size ); } -inline void msgForMultiplyDefinedPV::operator delete ( void *pCadaver, size_t size ) +#ifdef CXX_PLACEMENT_DELETE +inline void msgForMultiplyDefinedPV::operator delete ( void *pCadaver, + tsFreeList < class msgForMultiplyDefinedPV, 16 > & freeList ) { - msgForMultiplyDefinedPV::pFreeList->release ( pCadaver, size ); + freeList.release ( pCadaver, sizeof ( msgForMultiplyDefinedPV ) ); } +#endif #endif // ifdef msgForMultiplyDefinedPVh diff --git a/src/ca/virtualCircuit.h b/src/ca/virtualCircuit.h index 3f678e88b..1588a9438 100644 --- a/src/ca/virtualCircuit.h +++ b/src/ca/virtualCircuit.h @@ -36,6 +36,7 @@ #include "comQueRecv.h" #include "tcpRecvWatchdog.h" #include "tcpSendWatchdog.h" +#include "hostNameCache.h" // a modified ca header with capacity for large arrays struct caHdrLargeArray { @@ -58,6 +59,7 @@ public: virtual ~tcpRecvThread (); void start (); void exitWait (); + void interruptSocketRecv (); private: epicsThread thread; class tcpiiu & iiu; @@ -73,6 +75,7 @@ public: void start (); void exitWait (); void exitWaitRelease (); + void interruptSocketSend (); private: class tcpiiu & iiu; epicsThread thread; @@ -84,9 +87,9 @@ class tcpiiu : public tsSLNode < tcpiiu >, public caServerID, private wireSendAdapter, private wireRecvAdapter { public: - tcpiiu ( cac &cac, callbackMutex & cbMutex, double connectionTimeout, + tcpiiu ( cac & cac, callbackMutex & cbMutex, double connectionTimeout, epicsTimerQueue & timerQueue, const osiSockAddr & addrIn, - unsigned minorVersion, ipAddrToAsciiEngine & engineIn, + comBufMemoryManager &, unsigned minorVersion, ipAddrToAsciiEngine & engineIn, const cacChannel::priLev & priorityIn ); ~tcpiiu (); void start ( epicsGuard < callbackMutex > & ); @@ -126,7 +129,10 @@ public: void uninstallChan ( epicsGuard < cacMutex > &, nciu & chan ); void initiateCleanShutdown ( epicsGuard < cacMutex > & ); + bool bytesArePendingInOS () const; + private: + hostNameCache hostNameCacheInstance; tcpRecvThread recvThread; tcpSendThread sendThread; tcpRecvWatchdog recvDog; @@ -137,7 +143,7 @@ private: caHdrLargeArray curMsg; arrayElementCount curDataMax; arrayElementCount curDataBytes; - epics_auto_ptr < hostNameCache > pHostNameCache; + comBufMemoryManager & comBufMemMgr; cac & cacRef; char * pCurData; unsigned minorProtocolVersion; @@ -235,5 +241,15 @@ inline unsigned tcpiiu::channelCount () return this->channelList.count (); } +inline void tcpRecvThread::interruptSocketRecv () +{ + epicsSocketInterruptSystemCall ( this->thread.getId() ); +} + +inline void tcpSendThread::interruptSocketSend () +{ + epicsSocketInterruptSystemCall ( this->thread.getId() ); +} + #endif // ifdef virtualCircuith