optimized free list locking
This commit is contained in:
@@ -23,12 +23,6 @@ baseNMIU::~baseNMIU ()
|
||||
{
|
||||
}
|
||||
|
||||
void baseNMIU::cancel ()
|
||||
{
|
||||
this->chan.uninstallIO ( *this );
|
||||
delete this;
|
||||
}
|
||||
|
||||
class netSubscription * baseNMIU::isSubscription ()
|
||||
{
|
||||
return 0;
|
||||
|
||||
+102
-101
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
+76
-39
@@ -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 );
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+5
-6
@@ -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 {
|
||||
|
||||
+2
-2
@@ -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 ()
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user