diff --git a/src/ca/baseNMIU.cpp b/src/ca/baseNMIU.cpp index 84825f6d7..e42570c4a 100644 --- a/src/ca/baseNMIU.cpp +++ b/src/ca/baseNMIU.cpp @@ -23,12 +23,6 @@ baseNMIU::~baseNMIU () { } -void baseNMIU::cancel () -{ - this->chan.uninstallIO ( *this ); - delete this; -} - class netSubscription * baseNMIU::isSubscription () { return 0; diff --git a/src/ca/cac.cpp b/src/ca/cac.cpp index b47c66636..14bc9b925 100644 --- a/src/ca/cac.cpp +++ b/src/ca/cac.cpp @@ -22,9 +22,10 @@ #include "comQueSend_IL.h" #include "recvProcessThread_IL.h" #include "netiiu_IL.h" +#include "baseNMIU_IL.h" #include "netWriteNotifyIO_IL.h" #include "netReadNotifyIO_IL.h" -#include "baseNMIU_IL.h" +#include "netSubscription_IL.h" // // cac::cac () @@ -943,19 +944,20 @@ int cac::writeRequest ( nciu &chan, unsigned type, unsigned nElem, const void *p return chan.getPIIU()->writeRequest ( chan, type, nElem, pValue ); } -int cac::writeNotifyRequest ( nciu &chan, cacNotify ¬ify, unsigned type, unsigned nElem, const void *pValue ) +int cac::writeNotifyRequest ( nciu &chan, cacNotify ¬ify, + unsigned type, unsigned nElem, const void *pValue ) { epicsAutoMutex autoMutex ( this->defaultMutex ); - this->flushIfRequired ( chan ); - netWriteNotifyIO *pIO = new netWriteNotifyIO ( chan, notify ); + netWriteNotifyIO *pIO = netWriteNotifyIO::factory ( + this->freeListWriteNotifyIO, chan, notify ); if ( pIO ) { this->ioTable.add ( *pIO ); chan.cacPrivateListOfIO::eventq.add ( *pIO ); - int status = chan.getPIIU()->writeNotifyRequest ( chan, *pIO, type, nElem, pValue ); + this->flushIfRequired ( chan ); + int status = chan.getPIIU()->writeNotifyRequest ( + chan, *pIO, type, nElem, pValue ); if ( status != ECA_NORMAL ) { - this->ioTable.remove ( *pIO ); - chan.cacPrivateListOfIO::eventq.remove ( *pIO ); - delete static_cast < baseNMIU * > ( pIO ); + this->destroyWriteNotifyIO ( *pIO ); } return status; } @@ -967,16 +969,16 @@ int cac::writeNotifyRequest ( nciu &chan, cacNotify ¬ify, unsigned type, unsi int cac::readNotifyRequest ( nciu &chan, cacNotify ¬ify, unsigned type, unsigned nElem ) { epicsAutoMutex autoMutex ( this->defaultMutex ); - this->flushIfRequired ( chan ); - netReadNotifyIO *pIO = new netReadNotifyIO ( chan, notify ); + + netReadNotifyIO *pIO = netReadNotifyIO::factory ( + this->freeListReadNotifyIO, chan, notify ); if ( pIO ) { + this->flushIfRequired ( chan ); this->ioTable.add ( *pIO ); chan.cacPrivateListOfIO::eventq.add ( *pIO ); int status = chan.getPIIU()->readNotifyRequest ( chan, *pIO, type, nElem ); if ( status != ECA_NORMAL ) { - this->ioTable.remove ( *pIO ); - chan.cacPrivateListOfIO::eventq.remove ( *pIO ); - delete static_cast < baseNMIU * > ( pIO ); + this->destroyReadNotifyIO ( *pIO ); } return status; } @@ -991,7 +993,7 @@ bool cac::ioCompletionNotify ( unsigned id, unsigned type, epicsAutoMutex autoMutex ( this->defaultMutex ); baseNMIU * pmiu = this->ioTable.lookup ( id ); if ( pmiu ) { - pmiu->notify ().completionNotify ( pmiu->channel (), type, count, pData ); + pmiu->notify().completionNotify ( pmiu->channel(), type, count, pData ); return true; } else { @@ -1004,7 +1006,7 @@ bool cac::ioExceptionNotify ( unsigned id, int status, const char *pContext ) epicsAutoMutex autoMutex ( this->defaultMutex ); baseNMIU * pmiu = this->ioTable.lookup ( id ); if ( pmiu ) { - pmiu->notify ().exceptionNotify ( pmiu->channel (), status, pContext ); + pmiu->notify().exceptionNotify ( pmiu->channel(), status, pContext ); return true; } else { @@ -1018,7 +1020,7 @@ bool cac::ioExceptionNotify ( unsigned id, int status, epicsAutoMutex autoMutex ( this->defaultMutex ); baseNMIU * pmiu = this->ioTable.lookup ( id ); if ( pmiu ) { - pmiu->notify ().exceptionNotify ( pmiu->channel (), + pmiu->notify().exceptionNotify ( pmiu->channel(), status, pContext, type, count ); return true; } @@ -1029,19 +1031,12 @@ bool cac::ioExceptionNotify ( unsigned id, int status, bool cac::ioCompletionNotifyAndDestroy ( unsigned id ) { - baseNMIU * pmiu; - - { - epicsAutoMutex autoMutex ( this->defaultMutex ); - pmiu = this->ioTable.remove ( id ); - if ( pmiu ) { - pmiu->channel ().cacPrivateListOfIO::eventq.remove ( *pmiu ); - } - } - + epicsAutoMutex autoMutex ( this->defaultMutex ); + baseNMIU * pmiu = this->ioTable.remove ( id ); if ( pmiu ) { - pmiu->notify ().completionNotify ( pmiu->channel () ); - delete pmiu; + pmiu->channel().cacPrivateListOfIO::eventq.remove ( *pmiu ); + pmiu->notify().completionNotify ( pmiu->channel() ); + pmiu->destroy ( *this ); return true; } else { @@ -1050,21 +1045,14 @@ bool cac::ioCompletionNotifyAndDestroy ( unsigned id ) } bool cac::ioCompletionNotifyAndDestroy ( unsigned id, - unsigned type, unsigned long count, const void *pData ) + unsigned type, unsigned long count, const void *pData ) { - baseNMIU * pmiu; - - { - epicsAutoMutex autoMutex ( this->defaultMutex ); - pmiu = this->ioTable.remove ( id ); - if ( pmiu ) { - pmiu->channel ().cacPrivateListOfIO::eventq.remove ( *pmiu ); - } - } - + epicsAutoMutex autoMutex ( this->defaultMutex ); + baseNMIU * pmiu = this->ioTable.remove ( id ); if ( pmiu ) { - pmiu->notify ().completionNotify ( pmiu->channel (), type, count, pData ); - delete pmiu; + pmiu->channel().cacPrivateListOfIO::eventq.remove ( *pmiu ); + pmiu->notify().completionNotify ( pmiu->channel(), type, count, pData ); + pmiu->destroy ( *this ); return true; } else { @@ -1074,19 +1062,12 @@ bool cac::ioCompletionNotifyAndDestroy ( unsigned id, bool cac::ioExceptionNotifyAndDestroy ( unsigned id, int status, const char *pContext ) { - baseNMIU * pmiu; - - { - epicsAutoMutex autoMutex ( this->defaultMutex ); - pmiu = this->ioTable.remove ( id ); - if ( pmiu ) { - pmiu->channel ().cacPrivateListOfIO::eventq.remove ( *pmiu ); - } - } - + epicsAutoMutex autoMutex ( this->defaultMutex ); + baseNMIU * pmiu = this->ioTable.remove ( id ); if ( pmiu ) { - pmiu->notify ().exceptionNotify ( pmiu->channel (), status, pContext ); - delete pmiu; + pmiu->channel().cacPrivateListOfIO::eventq.remove ( *pmiu ); + pmiu->notify().exceptionNotify ( pmiu->channel (), status, pContext ); + pmiu->destroy ( *this ); return true; } else { @@ -1097,20 +1078,13 @@ bool cac::ioExceptionNotifyAndDestroy ( unsigned id, int status, const char *pCo bool cac::ioExceptionNotifyAndDestroy ( unsigned id, int status, const char *pContext, unsigned type, unsigned long count ) { - baseNMIU * pmiu; - - { - epicsAutoMutex autoMutex ( this->defaultMutex ); - pmiu = this->ioTable.remove ( id ); - if ( pmiu ) { - pmiu->channel ().cacPrivateListOfIO::eventq.remove ( *pmiu ); - } - } - + epicsAutoMutex autoMutex ( this->defaultMutex ); + baseNMIU * pmiu = this->ioTable.remove ( id ); if ( pmiu ) { - pmiu->notify ().exceptionNotify ( pmiu->channel (), status, + pmiu->channel().cacPrivateListOfIO::eventq.remove ( *pmiu ); + pmiu->notify().exceptionNotify ( pmiu->channel(), status, pContext, type, count ); - delete pmiu; + pmiu->destroy ( *this ); return true; } else { @@ -1136,7 +1110,7 @@ void cac::connectAllIO ( nciu &chan ) this->ioTable.remove ( *pNetIO ); chan.cacPrivateListOfIO::eventq.remove ( *pNetIO ); pNetIO->notify().exceptionNotify ( pNetIO->channel(), ECA_DISCONN, chan.pHostName() ); - delete pNetIO.pointer (); + pNetIO.pointer()->destroy ( *this ); } pNetIO = next; } @@ -1152,62 +1126,89 @@ void cac::disconnectAllIO ( nciu &chan ) while ( pNetIO.valid () ) { tsDLIterBD < baseNMIU > next = pNetIO; next++; - class netSubscription *pSubscr = pNetIO->isSubscription (); - this->ioTable.remove ( *pNetIO ); - if ( pSubscr ) { - chan.getPIIU()->subscriptionCancelRequest ( *pSubscr ); - } - else { + if ( ! pNetIO->isSubscription () ) { // no use after disconnected - so uninstall it + this->ioTable.remove ( *pNetIO ); chan.cacPrivateListOfIO::eventq.remove ( *pNetIO ); - pNetIO->notify ().exceptionNotify ( pNetIO->channel (), ECA_DISCONN, chan.pHostName () ); - delete pNetIO.pointer (); + pNetIO->notify().exceptionNotify ( pNetIO->channel(), ECA_DISCONN, chan.pHostName() ); + pNetIO.pointer()->destroy ( *this ); } pNetIO = next; } } -// -// care is taken to not hold the lock while deleting the -// IO so that subscription delete request (sent by the -// IO's destructor) do not deadlock -// void cac::destroyAllIO ( nciu &chan ) { - tsDLList < baseNMIU > eventQ; - { - epicsAutoMutex autoMutex ( this->defaultMutex ); - while ( baseNMIU *pIO = chan.cacPrivateListOfIO::eventq.get () ) { - this->ioTable.remove ( *pIO ); - eventQ.add ( *pIO ); + epicsAutoMutex autoMutex ( this->defaultMutex ); + while ( baseNMIU *pIO = chan.cacPrivateListOfIO::eventq.get() ) { + this->ioTable.remove ( *pIO ); + this->flushIfRequired ( chan ); + class netSubscription *pSubscr = pIO->isSubscription (); + if ( pSubscr ) { + pIO->channel().getPIIU()->subscriptionCancelRequest ( *pSubscr ); } - } - while ( baseNMIU *pIO = eventQ.get () ) { - delete pIO; + pIO->destroy ( *this ); } } -void cac::uninstallIO ( baseNMIU &io ) +void cac::destroyReadNotifyIO ( netReadNotifyIO &io ) { epicsAutoMutex autoMutex ( this->defaultMutex ); baseNMIU *pIO = this->ioTable.remove ( io ); - assert ( &io == pIO ); + assert ( static_cast < baseNMIU * > ( &io ) == pIO ); io.channel().cacPrivateListOfIO::eventq.remove ( io ); - netSubscription * pSubscr = io.isSubscription (); - if ( pSubscr ) { - this->flushIfRequired ( io.channel() ); - io.channel().getPIIU()->subscriptionCancelRequest ( *pSubscr ); - } + io.destroy ( *this ); } -void cac::installSubscription ( netSubscription &subscr ) +void cac::destroyWriteNotifyIO ( netWriteNotifyIO &io ) { epicsAutoMutex autoMutex ( this->defaultMutex ); - subscr.channel().cacPrivateListOfIO::eventq.add ( subscr ); - this->ioTable.add ( subscr ); - if ( subscr.channel().connected() ) { - this->flushIfRequired ( subscr.channel() ); - subscr.channel().getPIIU()->subscriptionRequest ( subscr ); - } + baseNMIU *pIO = this->ioTable.remove ( io ); + assert ( static_cast < baseNMIU * > ( &io ) == pIO ); + io.channel().cacPrivateListOfIO::eventq.remove ( io ); + io.destroy ( *this ); +} + +void cac::destroySubscription ( netSubscription &io ) +{ + epicsAutoMutex autoMutex ( this->defaultMutex ); + baseNMIU *pIO = this->ioTable.remove ( io ); + assert ( static_cast < baseNMIU * > ( &io ) == pIO ); + io.channel().cacPrivateListOfIO::eventq.remove ( io ); + this->flushIfRequired ( io.channel() ); + io.channel().getPIIU()->subscriptionCancelRequest ( io ); + io.destroy ( *this ); +} + +void cac::recycleReadNotifyIO ( netReadNotifyIO &io ) +{ + this->freeListReadNotifyIO.release ( &io, sizeof ( io ) ); +} + +void cac::recycleWriteNotifyIO ( netWriteNotifyIO &io ) +{ + this->freeListWriteNotifyIO.release ( &io, sizeof ( io ) ); +} + +void cac::recycleSubscription ( netSubscription &io ) +{ + this->freeListSubscription.release ( &io, sizeof ( io ) ); +} + +cacNotifyIO * cac::subscriptionRequest ( nciu &chan, unsigned type, + unsigned long nElem, unsigned mask, cacNotify ¬ify ) +{ + epicsAutoMutex autoMutex ( this->defaultMutex ); + netSubscription *pSubcr = netSubscription::factory ( + this->freeListSubscription, chan, type, nElem, mask, notify ); + if ( pSubcr ) { + pSubcr->channel().cacPrivateListOfIO::eventq.add ( *pSubcr ); + this->ioTable.add ( *pSubcr ); + if ( pSubcr->channel().connected() ) { + this->flushIfRequired ( pSubcr->channel() ); + pSubcr->channel().getPIIU()->subscriptionRequest ( *pSubcr ); + } + } + return pSubcr; } diff --git a/src/ca/cacIO.h b/src/ca/cacIO.h index 9185356c4..c9be02a9a 100644 --- a/src/ca/cacIO.h +++ b/src/ca/cacIO.h @@ -45,10 +45,8 @@ public: cacNotify & notify () const; virtual void cancel () = 0; virtual void show ( unsigned level ) const = 0; - // the following commits us to deleting the IO when the channel is deleted :-( virtual cacChannelIO & channelIO () const = 0; - protected: virtual ~cacNotifyIO () = 0; private: @@ -63,7 +61,6 @@ public: virtual void disconnectNotify ( cacChannelIO & ); virtual void accessRightsNotify ( cacChannelIO &, const caar & ); virtual void exceptionNotify ( cacChannelIO &, int status, const char *pContext ); - // not for public consumption virtual bool includeFirstConnectInCountOfOutstandingIO () const; virtual class oldChannelNotify * pOldChannelNotify (); diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index 742761d7a..a84215c61 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -69,6 +69,8 @@ #include "caProto.h" #include "net_convert.h" +#define NO_PLACEMENT_DELETE + #ifdef DEBUG # define debugPrintf(argsInParen) printf argsInParen #else @@ -250,6 +252,7 @@ public: ca_uint32_t getSID () const; ca_uint32_t getCID () const; netiiu * getPIIU (); + cac & getClient (); void searchReplySetUp ( netiiu &iiu, unsigned sidIn, unsigned typeIn, unsigned long countIn ); void show ( unsigned level ) const; @@ -259,7 +262,6 @@ public: const char * pHostName () const; // deprecated - please do not use unsigned long nativeElementCount () const; bool connected () const; - void uninstallIO ( baseNMIU &io ); protected: ~nciu (); // force pool allocation private: @@ -302,65 +304,85 @@ private: }; class baseNMIU : public cacNotifyIO, public tsDLNode < baseNMIU >, - public chronIntIdRes < baseNMIU > { + public chronIntIdRes < baseNMIU > { public: baseNMIU ( cacNotify ¬ifyIn, nciu &chan ); - virtual ~baseNMIU () = 0; virtual class netSubscription * isSubscription (); + virtual void destroy ( class cacRecycle & ) = 0; // only called by cac void show ( unsigned level ) const; ca_uint32_t getID () const; nciu & channel () const; cacChannelIO & channelIO () const; - void cancel (); protected: + virtual ~baseNMIU () = 0; nciu &chan; }; class netSubscription : public baseNMIU { public: - netSubscription ( nciu &chan, unsigned type, unsigned long count, + static netSubscription * factory ( + tsFreeList < class netSubscription, 1024 > &, + nciu &chan, unsigned type, unsigned long count, unsigned mask, cacNotify ¬ify ); void show ( unsigned level ) const; unsigned long getCount () const; unsigned getType () const; unsigned getMask () const; - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); + void destroy ( cacRecycle & ); protected: - ~netSubscription (); private: const unsigned long count; const unsigned type; const unsigned mask; + netSubscription ( nciu &chan, unsigned type, unsigned long count, + unsigned mask, cacNotify ¬ify ); + ~netSubscription (); + void cancel (); class netSubscription * isSubscription (); - static tsFreeList < class netSubscription, 1024 > freeList; - static epicsMutex freeListMutex; + void * operator new ( size_t, + tsFreeList < class netSubscription, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netSubscription, 1024 > & ); +# endif }; class netReadNotifyIO : public baseNMIU { public: - netReadNotifyIO ( nciu &chan, cacNotify ¬ify ); + static netReadNotifyIO * factory ( + tsFreeList < class netReadNotifyIO, 1024 > &, + nciu &chan, cacNotify ¬ify ); void show ( unsigned level ) const; - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); -protected: - ~netReadNotifyIO (); + void destroy ( cacRecycle & ); private: - static tsFreeList < class netReadNotifyIO, 1024 > freeList; - static epicsMutex freeListMutex; + netReadNotifyIO ( nciu &chan, cacNotify ¬ify ); + ~netReadNotifyIO (); + void cancel (); + void * operator new ( size_t, + tsFreeList < class netReadNotifyIO, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netReadNotifyIO, 1024 > & ); +# endif }; class netWriteNotifyIO : public baseNMIU { public: - netWriteNotifyIO ( nciu &chan, cacNotify ¬ify ); + static netWriteNotifyIO * factory ( + tsFreeList < class netWriteNotifyIO, 1024 > &, + nciu &chan, cacNotify ¬ify ); void show ( unsigned level ) const; - void * operator new ( size_t size ); - void operator delete ( void *pCadaver, size_t size ); -protected: - ~netWriteNotifyIO (); + void destroy ( cacRecycle & ); private: - static tsFreeList < class netWriteNotifyIO, 1024 > freeList; - static epicsMutex freeListMutex; + netWriteNotifyIO ( nciu &chan, cacNotify ¬ify ); + ~netWriteNotifyIO (); + void cancel (); + void * operator new ( size_t, + tsFreeList < class netWriteNotifyIO, 1024 > & ); +# if ! defined ( NO_PLACEMENT_DELETE ) + void operator delete ( void *, size_t, + tsFreeList < class netWriteNotifyIO, 1024 > & ); +# endif }; /* @@ -891,24 +913,24 @@ private: epicsEvent ioDone; }; +// used to control access to cac's recycle routines which +// should only be indirectly invoked by CAC whenits lock +// is applied +class cacRecycle { +public: + virtual void recycleReadNotifyIO ( netReadNotifyIO &io ) = 0; + virtual void recycleWriteNotifyIO ( netWriteNotifyIO &io ) = 0; + virtual void recycleSubscription ( netSubscription &io ) = 0; +}; + // -// mutex strategy -// 1) mutex hierarchy -// -// (if multiple lock are applied simultaneously then they -// must be applied in this order) +// If multiple lock are applied simultaneously then they +// must be applied in this order to avoid deadlocks // // cac::iiuListMutex // cac::defaultMutex: -// netiiu::mutex -// nciu::mutex -// baseNMIU::mutex // -// 2) channels can not be moved between netiiu derived classes -// w/o taking the defaultMutex in this class first -// -// -class cac : public caClient +class cac : public caClient, private cacRecycle { public: cac ( bool enablePreemptiveCallback = false ); @@ -933,7 +955,6 @@ public: void flushRequest (); int pendIO ( const double &timeout ); int pendEvent ( const double &timeout ); - void uninstallIO ( baseNMIU &io ); bool ioCompletionNotify ( unsigned id, unsigned type, unsigned long count, const void *pData ); bool ioExceptionNotify ( unsigned id, @@ -950,7 +971,9 @@ public: void connectAllIO ( nciu &chan ); void disconnectAllIO ( nciu &chan ); void destroyAllIO ( nciu &chan ); - void installSubscription ( netSubscription &subscr ); + void destroyReadNotifyIO ( netReadNotifyIO &io ); + void destroyWriteNotifyIO ( netWriteNotifyIO &io ); + void destroySubscription ( netSubscription &io ); // exception routines void exceptionNotify ( int status, const char *pContext, @@ -979,6 +1002,8 @@ public: int writeRequest ( nciu &, unsigned type, unsigned nElem, const void *pValue ); int writeNotifyRequest ( nciu &, cacNotify &, unsigned type, unsigned nElem, const void *pValue ); int readNotifyRequest ( nciu &, cacNotify &, unsigned type, unsigned nElem ); + cacNotifyIO * subscriptionRequest ( nciu &chan, unsigned type, unsigned long nElem, + unsigned mask, cacNotify ¬ify ); // sync group routines CASG * lookupCASG ( unsigned id ); @@ -1021,6 +1046,15 @@ private: < CASG > sgTable; resTable < bhe, inetAddrID > beaconTable; + tsFreeList + < class netReadNotifyIO, 1024 > + freeListReadNotifyIO; + tsFreeList + < class netWriteNotifyIO, 1024 > + freeListWriteNotifyIO; + tsFreeList + < class netSubscription, 1024 > + freeListSubscription; epicsTime programBeginTime; double connTMO; // defaultMutex can be applied if iiuListMutex is already applied @@ -1042,6 +1076,9 @@ private: bool enablePreemptiveCallback; bool setupUDP (); void flushIfRequired ( nciu & ); // lock must be applied + void recycleReadNotifyIO ( netReadNotifyIO &io ); + void recycleWriteNotifyIO ( netWriteNotifyIO &io ); + void recycleSubscription ( netSubscription &io ); }; /* diff --git a/src/ca/nciu.cpp b/src/ca/nciu.cpp index b13268e53..a267597c9 100644 --- a/src/ca/nciu.cpp +++ b/src/ca/nciu.cpp @@ -328,7 +328,7 @@ int nciu::subscribe ( unsigned type, unsigned long nElem, unsigned mask, cacNotify ¬ify, cacNotifyIO *&pNotifyIO ) { - if ( INVALID_DB_REQ (type) ) { + if ( INVALID_DB_REQ(type) ) { return ECA_BADTYPE; } @@ -336,11 +336,10 @@ int nciu::subscribe ( unsigned type, unsigned long nElem, return ECA_BADMASK; } - netSubscription *pSubcr = new netSubscription ( *this, - type, nElem, mask, notify ); - if ( pSubcr ) { - this->cacCtx.installSubscription ( *pSubcr ); - pNotifyIO = pSubcr; + cacNotifyIO * pIO = this->cacCtx.subscriptionRequest ( + *this, type, nElem, mask, notify ); + if ( pIO ) { + pNotifyIO = pIO; return ECA_NORMAL;; } else { diff --git a/src/ca/nciu_IL.h b/src/ca/nciu_IL.h index b4e403105..91751af58 100644 --- a/src/ca/nciu_IL.h +++ b/src/ca/nciu_IL.h @@ -100,9 +100,9 @@ inline netiiu * nciu::getPIIU () return this->piiu; } -inline void nciu::uninstallIO ( baseNMIU &io ) +inline cac & nciu::getClient () { - this->cacCtx.uninstallIO ( io ); + return this->cacCtx; } inline void nciu::connectTimeoutNotify () diff --git a/src/ca/netReadNotifyIO.cpp b/src/ca/netReadNotifyIO.cpp index 5fe76f19c..d11245d8f 100644 --- a/src/ca/netReadNotifyIO.cpp +++ b/src/ca/netReadNotifyIO.cpp @@ -15,15 +15,12 @@ #include "nciu_IL.h" #include "baseNMIU_IL.h" -tsFreeList < class netReadNotifyIO, 1024 > netReadNotifyIO::freeList; -epicsMutex netReadNotifyIO::freeListMutex; - netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacNotify ¬ifyIn ) : baseNMIU ( notifyIn, chan ) { } -netReadNotifyIO::~netReadNotifyIO () +netReadNotifyIO::~netReadNotifyIO () { } @@ -35,3 +32,16 @@ void netReadNotifyIO::show ( unsigned level ) const this->baseNMIU::show ( level - 1u ); } } + +void netReadNotifyIO::cancel () +{ + this->chan.getClient().destroyReadNotifyIO ( *this ); +} + +void netReadNotifyIO::destroy ( cacRecycle & recycle ) +{ + this->~netReadNotifyIO(); + recycle.recycleReadNotifyIO ( *this ); +} + + diff --git a/src/ca/netReadNotifyIO_IL.h b/src/ca/netReadNotifyIO_IL.h index cf12eec1b..c8ca4fa47 100644 --- a/src/ca/netReadNotifyIO_IL.h +++ b/src/ca/netReadNotifyIO_IL.h @@ -18,16 +18,29 @@ #ifndef netReadNotifyIO_ILh #define netReadNotifyIO_ILh -inline void * netReadNotifyIO::operator new ( size_t size ) -{ - epicsAutoMutex locker ( netReadNotifyIO::freeListMutex ); - return netReadNotifyIO::freeList.allocate ( size ); +inline netReadNotifyIO * netReadNotifyIO::factory ( + tsFreeList < class netReadNotifyIO, 1024 > &freeList, + nciu &chan, cacNotify ¬ify ) +{ + return new ( freeList ) netReadNotifyIO ( chan, notify ); } -inline void netReadNotifyIO::operator delete ( void *pCadaver, size_t size ) -{ - epicsAutoMutex locker ( netReadNotifyIO::freeListMutex ); - netReadNotifyIO::freeList.release ( pCadaver, size ); +inline void * netReadNotifyIO::operator new ( size_t size, + tsFreeList < class netReadNotifyIO, 1024 > &freeList ) +{ + return freeList.allocate ( size ); } +// NOTE: The constructor for netReadNotifyIO::netReadNotifyIO() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netReadNotifyIO when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netReadNotifyIO::netReadNotifyIO() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netReadNotifyIO::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netReadNotifyIO, 1024 > &freeList ) { + freeList.release ( pCadaver, size ); +} +#endif + #endif // netReadNotifyIO_ILh diff --git a/src/ca/netSubscription.cpp b/src/ca/netSubscription.cpp index 3aa70103d..10fafb7cc 100644 --- a/src/ca/netSubscription.cpp +++ b/src/ca/netSubscription.cpp @@ -15,9 +15,6 @@ #include "nciu_IL.h" #include "baseNMIU_IL.h" -tsFreeList < class netSubscription, 1024 > netSubscription::freeList; -epicsMutex netSubscription::freeListMutex; - netSubscription::netSubscription ( nciu &chan, unsigned typeIn, unsigned long countIn, unsigned maskIn, cacNotify ¬ifyIn ) : baseNMIU ( notifyIn, chan ), @@ -29,6 +26,17 @@ netSubscription::~netSubscription () { } +void netSubscription::cancel () +{ + this->chan.getClient().destroySubscription ( *this ); +} + +void netSubscription::destroy ( cacRecycle &recycle ) +{ + this->~netSubscription (); + recycle.recycleSubscription ( *this ); +} + class netSubscription * netSubscription::isSubscription () { return this; diff --git a/src/ca/netSubscription_IL.h b/src/ca/netSubscription_IL.h index 00e9d136f..b3b9b1e50 100644 --- a/src/ca/netSubscription_IL.h +++ b/src/ca/netSubscription_IL.h @@ -18,18 +18,34 @@ #ifndef netSubscription_ILh #define netSubscription_ILh -inline void * netSubscription::operator new ( size_t size ) -{ - epicsAutoMutex locker ( netSubscription::freeListMutex ); - return netSubscription::freeList.allocate ( size ); +inline netSubscription * netSubscription::factory ( + tsFreeList < class netSubscription, 1024 > &freeList, + nciu &chan, unsigned type, unsigned long count, + unsigned mask, cacNotify ¬ify ) +{ + return new ( freeList ) netSubscription ( chan, type, + count, mask, notify ); } -inline void netSubscription::operator delete ( void *pCadaver, size_t size ) -{ - epicsAutoMutex locker ( netSubscription::freeListMutex ); - netSubscription::freeList.release ( pCadaver, size ); +inline void * netSubscription::operator new ( size_t size, + tsFreeList < class netSubscription, 1024 > &freeList ) +{ + return freeList.allocate ( size ); } +// NOTE: The constructor for netSubscription::netSubscription() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netSubscription when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netSubscription::netSubscription() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netSubscription::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netSubscription, 1024 > &freeList ) +{ + freeList.release ( pCadaver, size ); +} +#endif + inline unsigned long netSubscription::getCount () const { unsigned long nativeCount = this->chan.nativeElementCount (); diff --git a/src/ca/netWriteNotifyIO.cpp b/src/ca/netWriteNotifyIO.cpp index e79c31ab3..5881dddc8 100644 --- a/src/ca/netWriteNotifyIO.cpp +++ b/src/ca/netWriteNotifyIO.cpp @@ -15,15 +15,12 @@ #include "nciu_IL.h" #include "baseNMIU_IL.h" -tsFreeList < class netWriteNotifyIO, 1024 > netWriteNotifyIO::freeList; -epicsMutex netWriteNotifyIO::freeListMutex; - netWriteNotifyIO::netWriteNotifyIO ( nciu &chan, cacNotify ¬ifyIn ) : baseNMIU ( notifyIn, chan ) { } -netWriteNotifyIO::~netWriteNotifyIO () +netWriteNotifyIO::~netWriteNotifyIO () { } @@ -35,3 +32,16 @@ void netWriteNotifyIO::show ( unsigned level ) const this->baseNMIU::show ( level - 1u ); } } + +void netWriteNotifyIO::cancel () +{ + this->chan.getClient().destroyWriteNotifyIO ( *this ); +} + +void netWriteNotifyIO::destroy ( cacRecycle & recycle ) +{ + this->~netWriteNotifyIO (); + recycle.recycleWriteNotifyIO ( *this ); +} + + diff --git a/src/ca/netWriteNotifyIO_IL.h b/src/ca/netWriteNotifyIO_IL.h index 1bea6cfe4..239171643 100644 --- a/src/ca/netWriteNotifyIO_IL.h +++ b/src/ca/netWriteNotifyIO_IL.h @@ -15,15 +15,28 @@ * 505 665 1831 */ -inline void * netWriteNotifyIO::operator new ( size_t size ) -{ - epicsAutoMutex locker ( netWriteNotifyIO::freeListMutex ); - return netWriteNotifyIO::freeList.allocate ( size ); +inline netWriteNotifyIO * netWriteNotifyIO::factory ( + tsFreeList < class netWriteNotifyIO, 1024 > &freeList, + nciu &chan, cacNotify ¬ify ) +{ + return new ( freeList ) netWriteNotifyIO ( chan, notify ); } -inline void netWriteNotifyIO::operator delete ( void *pCadaver, size_t size ) +inline void * netWriteNotifyIO::operator new ( size_t size, + tsFreeList < class netWriteNotifyIO, 1024 > &freeList ) { - epicsAutoMutex locker ( netWriteNotifyIO::freeListMutex ); - netWriteNotifyIO::freeList.release ( pCadaver, size ); + return freeList.allocate ( size ); } +// NOTE: The constructor for netWriteNotifyIO::netWriteNotifyIO() currently does +// not throw an exception, but we should eventually have placement delete +// defined for class netWriteNotifyIO when compilers support this so that +// there is no possibility of a leak if there was an exception in +// a future version of netWriteNotifyIO::netWriteNotifyIO() +#if ! defined ( NO_PLACEMENT_DELETE ) +inline void netWriteNotifyIO::operator delete ( void *pCadaver, size_t size, + tsFreeList < class netWriteNotifyIO, 1024 > &freeList ) +{ + freeList.release ( pCadaver, size ); +} +#endif