redesigned class hierarchy

This commit is contained in:
Jeff Hill
2001-02-09 17:38:00 +00:00
parent cebb5854cf
commit a1fbe85e7b
25 changed files with 819 additions and 879 deletions

View File

@@ -49,7 +49,7 @@ CASG::~CASG ()
this->mutex.lock ();
tsDLIterBD <syncGroupNotify> notify ( this->ioList.first () );
while ( notify.valid () ) {
notify->destroy ();
notify->release ();
notify = this->ioList.first ();
}
this->mutex.unlock ();
@@ -85,12 +85,12 @@ int CASG::block ( double timeout )
/*
* dont allow recursion
*/
void *p = epicsThreadPrivateGet (cacRecursionLock);
void *p = epicsThreadPrivateGet ( cacRecursionLock );
if ( p ) {
return ECA_EVDISALLOW;
}
epicsThreadPrivateSet (cacRecursionLock, &cacRecursionLock);
epicsThreadPrivateSet ( cacRecursionLock, &cacRecursionLock );
cur_time = epicsTime::getCurrent ();
@@ -189,7 +189,11 @@ int CASG::put (chid pChan, unsigned type, unsigned long count, const void *pValu
if ( ! pNotify ) {
return ECA_ALLOCMEM;
}
return pChan->write ( type, count, pValue, *pNotify );
int status = pChan->write ( type, count, pValue, *pNotify );
if ( status != ECA_NORMAL ) {
pNotify->release ();
}
return status;
}
int CASG::get (chid pChan, unsigned type, unsigned long count, void *pValue)
@@ -198,6 +202,10 @@ int CASG::get (chid pChan, unsigned type, unsigned long count, void *pValue)
if ( ! pNotify ) {
return ECA_ALLOCMEM;
}
return pChan->read ( type, count, *pNotify );
int status = pChan->read ( type, count, *pNotify );
if ( status != ECA_NORMAL ) {
pNotify->release ();
}
return status;
}

View File

@@ -14,8 +14,8 @@ INC += db_access.h
INC += addrList.h
INC += cacIO.h
LIBSRCS += cacChannel.cpp
LIBSRCS += cacChannelIO.cpp
LIBSRCS += cacChannelNotify.cpp
LIBSRCS += cacNotify.cpp
LIBSRCS += cacNotifyIO.cpp
LIBSRCS += cacServiceList.cpp
@@ -40,7 +40,7 @@ LIBSRCS += cac.cpp
LIBSRCS += tcpSendWatchdog.cpp
LIBSRCS += tcpRecvWatchdog.cpp
LIBSRCS += bhe.cpp
LIBSRCS += oldChannel.cpp
LIBSRCS += oldChannelNotify.cpp
LIBSRCS += oldSubscription.cpp
LIBSRCS += getCallback.cpp
LIBSRCS += putCallback.cpp
@@ -79,6 +79,7 @@ caRepeater_SRCS = caRepeater.cpp
PROD += caRepeater
PROD_DEFAULT += catime acctst caConnTest casw caEventRate
OBJS_IOC += catime acctst caConnTest casw caEventRate
catime_SRCS = catimeMain.c catime.c
acctst_SRCS = acctstMain.c acctst.c
caEventRate_SRCS = caEventRateMain.cpp caEventRate.cpp

View File

@@ -15,47 +15,8 @@
#include "iocinf.h"
cacChannelIO::cacChannelIO ( cacChannel &chanIn ) :
chan ( chanIn )
{
}
cacChannelIO::~cacChannelIO ()
{
this->chan.pChannelIO = 0;
}
cacLocalChannelIO::cacLocalChannelIO ( cac &cacCtxIn, cacChannel &chan ) :
cacChannelIO ( chan ), cacCtx ( cacCtxIn ) {};
cacLocalChannelIO::~cacLocalChannelIO ()
{
this->cacCtx.uninstallLocalChannel ( *this );
}
void cacChannelIO::connectNotify ()
{
this->chan.connectNotify ();
}
void cacChannelIO::disconnectNotify ()
{
this->chan.disconnectNotify ();
}
void cacChannelIO::connectTimeoutNotify ()
{
this->chan.connectTimeoutNotify ();
}
void cacChannelIO::accessRightsNotify ( caar ar )
{
this->chan.accessRightsNotify ( ar );
}
void cacChannelIO::ioReleaseNotify ()
{
this->chan.ioReleaseNotify ();
}
channel_state cacChannelIO::state () const
@@ -71,6 +32,10 @@ caar cacChannelIO::accessRights () const
return ar;
}
void cacChannelIO::notifyStateChangeFirstConnectInCountOfOutstandingIO ()
{
}
unsigned cacChannelIO::searchAttempts () const
{
return 0u;
@@ -91,15 +56,10 @@ bool cacChannelIO::connected () const
return true;
}
unsigned cacChannelIO::readSequence () const
{
return 0u;
}
void cacChannelIO::hostName ( char *pBuf, unsigned bufLength ) const
{
if ( bufLength ) {
localHostNameAtLoadTime.copy (pBuf, bufLength );
localHostNameAtLoadTime.copy ( pBuf, bufLength );
}
}
@@ -109,20 +69,4 @@ const char * cacChannelIO::pHostName () const
return localHostNameAtLoadTime.pointer ();
}
void cacChannelIO::incrementOutstandingIO ()
{
}
void cacChannelIO::decrementOutstandingIO ()
{
}
void cacChannelIO::lockOutstandingIO () const
{
}
void cacChannelIO::unlockOutstandingIO () const
{
}

View File

@@ -15,147 +15,105 @@
* 505 665 1831
*/
//
// Notes
// 1) these routines should be changed to throw exceptions and not return
// ECA_XXXX style status in the future.
//
#include "tsDLList.h"
#include "epicsMutex.h"
#include "shareLib.h"
class cacNotifyIO;
class cac;
struct cacChannelIO;
struct cacNotifyIO;
class epicsShareClass cacNotify {
class cacNotify {
public:
cacNotify ();
virtual ~cacNotify () = 0;
virtual void destroy () = 0;
virtual void completionNotify ();
virtual void completionNotify ( unsigned type, unsigned long count, const void *pData );
virtual void exceptionNotify ( int status, const char *pContext );
virtual void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
private:
cacNotifyIO *pIO;
friend class cacNotifyIO;
};
class epicsShareClass cacNotifyIO {
public:
cacNotifyIO ( cacNotify & );
virtual ~cacNotifyIO () = 0;
virtual void uninstall () = 0;
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
private:
cacNotify &notify;
friend class cacNotify;
};
class epicsShareClass cacChannel {
public:
cacChannel ();
virtual ~cacChannel () = 0;
virtual void destroy () = 0;
void attachIO ( class cacChannelIO &io );
int read ( unsigned type, unsigned long count, void *pValue );
int read ( unsigned type, unsigned long count, cacNotify & );
int write ( unsigned type, unsigned long count, const void *pvalue );
int write ( unsigned type, unsigned long count, const void *pvalue, cacNotify &notify );
int subscribe ( unsigned type, unsigned long count, unsigned mask, cacNotify &notify );
void hostName ( char *pBuf, unsigned bufLength ) const;
short nativeType () const;
unsigned long nativeElementCount () const;
channel_state state () const;
bool readAccess () const;
bool writeAccess () const;
const char *pName () const;
unsigned searchAttempts () const;
double beaconPeriod () const;
bool ca_v42_ok () const;
bool connected () const;
caar accessRights () const;
unsigned readSequence () const;
void incrementOutstandingIO ();
void decrementOutstandingIO ();
void decrementOutstandingIO ( unsigned seqNumber );
const char * pHostName () const; // deprecated - please do not use
epicsShareFunc virtual void release () = 0;
epicsShareFunc virtual void completionNotify ( cacChannelIO & );
epicsShareFunc virtual void completionNotify ( cacChannelIO &, unsigned type,
unsigned long count, const void *pData );
epicsShareFunc virtual void exceptionNotify ( cacChannelIO &,
int status, const char *pContext );
epicsShareFunc virtual void exceptionNotify ( cacChannelIO &,
int status, const char *pContext, unsigned type, unsigned long count );
protected:
class cacChannelIO *pChannelIO;
void lockOutstandingIO () const;
void unlockOutstandingIO () const;
private:
virtual void ioAttachNotify ();
virtual void ioReleaseNotify ();
virtual void connectNotify ();
virtual void disconnectNotify ();
virtual void accessRightsNotify ( caar );
virtual void exceptionNotify ( int status, const char *pContext );
virtual void connectTimeoutNotify ();
friend class cacChannelIO;
epicsShareFunc virtual ~cacNotify () = 0;
};
class epicsShareClass cacChannelIO {
struct cacNotifyIO {
public:
cacChannelIO ( cacChannel &chan );
virtual ~cacChannelIO () = 0;
virtual void destroy () = 0;
void connectNotify ();
void disconnectNotify ();
void connectTimeoutNotify ();
void accessRightsNotify ( caar );
void ioReleaseNotify ();
virtual const char *pName () const = 0;
virtual void lockOutstandingIO () const = 0;
virtual void unlockOutstandingIO () const = 0;
virtual void show ( unsigned level ) const = 0;
epicsShareFunc cacNotifyIO ( cacNotify & );
epicsShareFunc cacNotify & notify () const;
epicsShareFunc virtual void destroy () = 0; // also uninstalls
epicsShareFunc virtual cacChannelIO & channelIO () const = 0;
protected:
epicsShareFunc virtual ~cacNotifyIO () = 0;
private:
virtual int read ( unsigned type, unsigned long count, void *pValue) = 0;
virtual int read ( unsigned type, unsigned long count, cacNotify &notify ) = 0;
virtual int write ( unsigned type, unsigned long count, const void *pValue ) = 0;
virtual int write ( unsigned type, unsigned long count, const void *pValue, cacNotify &notify ) = 0;
virtual int subscribe ( unsigned type, unsigned long count, unsigned mask, cacNotify &notify ) = 0;
virtual short nativeType () const = 0;
virtual unsigned long nativeElementCount () const = 0;
virtual void hostName (char *pBuf, unsigned bufLength) const; // defaults to local host name
virtual channel_state state () const; // defaults to always connected
virtual caar accessRights () const; // defaults to unrestricted access
virtual unsigned searchAttempts () const; // defaults to zero
virtual double beaconPeriod () const; // defaults to negative DBL_MAX
virtual bool ca_v42_ok () const; // defaults to true
virtual bool connected () const; // defaults to true
virtual unsigned readSequence () const; // defaults to always zero
virtual void incrementOutstandingIO ();
virtual void decrementOutstandingIO ();
virtual const char * pHostName () const; // deprecated - please do not use
cacChannel &chan;
friend class cacChannel;
cacNotify &callback;
};
class cacLocalChannelIO :
public cacChannelIO, public tsDLNode < cacLocalChannelIO > {
class cacChannelNotify {
public:
epicsShareFunc cacLocalChannelIO ( cac&, cacChannel &chan );
epicsShareFunc virtual ~cacLocalChannelIO ();
private:
cac &cacCtx;
epicsShareFunc virtual void release () = 0;
epicsShareFunc virtual void connectNotify ( cacChannelIO & );
epicsShareFunc virtual void disconnectNotify ( cacChannelIO & );
epicsShareFunc virtual void accessRightsNotify ( cacChannelIO &, const caar & );
epicsShareFunc virtual void exceptionNotify ( cacChannelIO &, int status, const char *pContext );
// not for public consumption
epicsShareFunc virtual bool includeFirstConnectInCountOfOutstandingIO () const;
epicsShareFunc virtual class oldChannelNotify * pOldChannelNotify ();
protected:
epicsShareFunc virtual ~cacChannelNotify () = 0;
};
struct cacChannelIO {
public:
epicsShareFunc cacChannelIO ( cacChannelNotify &chan );
epicsShareFunc cacChannelNotify & notify () const;
epicsShareFunc virtual void destroy () = 0;
epicsShareFunc virtual const char *pName () const = 0;
epicsShareFunc virtual void show ( unsigned level ) const = 0;
epicsShareFunc virtual void initiateConnect () = 0;
epicsShareFunc virtual int read ( unsigned type,
unsigned long count, void *pValue) = 0;
epicsShareFunc virtual int read ( unsigned type,
unsigned long count, cacNotify &notify ) = 0;
epicsShareFunc virtual int write ( unsigned type,
unsigned long count, const void *pValue ) = 0;
epicsShareFunc virtual int write ( unsigned type,
unsigned long count, const void *pValue,
cacNotify &notify ) = 0;
epicsShareFunc virtual int subscribe ( unsigned type,
unsigned long count, unsigned mask,
cacNotify &notify, cacNotifyIO *& ) = 0;
epicsShareFunc virtual short nativeType () const = 0;
epicsShareFunc virtual unsigned long nativeElementCount () const = 0;
epicsShareFunc virtual channel_state state () const; // defaults to always connected
epicsShareFunc virtual caar accessRights () const; // defaults to unrestricted access
epicsShareFunc virtual unsigned searchAttempts () const; // defaults to zero
epicsShareFunc virtual double beaconPeriod () const; // defaults to negative DBL_MAX
epicsShareFunc virtual bool ca_v42_ok () const; // defaults to true
epicsShareFunc virtual bool connected () const; // defaults to true
epicsShareFunc virtual void hostName (char *pBuf, unsigned bufLength) const; // defaults to local host name
epicsShareFunc virtual const char * pHostName () const; // deprecated - please do not use
epicsShareFunc virtual void notifyStateChangeFirstConnectInCountOfOutstandingIO ();
protected:
epicsShareFunc virtual ~cacChannelIO () = 0;
private:
cacChannelNotify &chan;
};
class cac;
struct cacServiceIO : public tsDLNode < cacServiceIO > {
public:
epicsShareFunc virtual cacLocalChannelIO *createChannelIO ( const char *pName, cac &, cacChannel & ) = 0;
epicsShareFunc virtual cacChannelIO *createChannelIO (
const char *pName, cac &, cacChannelNotify & ) = 0;
epicsShareFunc virtual void show ( unsigned level ) const = 0;
private:
};
@@ -164,7 +122,8 @@ class cacServiceList : private epicsMutex {
public:
epicsShareFunc cacServiceList ();
epicsShareFunc void registerService ( cacServiceIO &service );
epicsShareFunc cacLocalChannelIO * createChannelIO ( const char *pName, cac &, cacChannel & );
epicsShareFunc cacChannelIO * createChannelIO (
const char *pName, cac &, cacChannelNotify & );
epicsShareFunc void show ( unsigned level ) const;
private:
tsDLList < cacServiceIO > services;
@@ -174,23 +133,21 @@ epicsShareExtern cacServiceList cacGlobalServiceList;
epicsShareFunc int epicsShareAPI ca_register_service ( struct cacServiceIO *pService );
inline void cacNotifyIO::completionNotify ()
inline cacNotifyIO::cacNotifyIO ( cacNotify &notifyIn ) : callback ( notifyIn )
{
this->notify.completionNotify ();
}
inline void cacNotifyIO::completionNotify ( unsigned type, unsigned long count, const void *pData )
inline cacNotify & cacNotifyIO::notify () const
{
this->notify.completionNotify ( type, count, pData );
return this->callback;
}
inline void cacNotifyIO::exceptionNotify ( int status, const char *pContext )
inline cacChannelIO::cacChannelIO ( cacChannelNotify &chanIn ) : chan ( chanIn )
{
this->notify.exceptionNotify ( status, pContext );
}
inline void cacNotifyIO::exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count )
inline cacChannelNotify & cacChannelIO::notify () const
{
this->notify.exceptionNotify ( status, pContext, type, count );
return this->chan;
}

View File

@@ -12,40 +12,32 @@
#include "iocinf.h"
cacNotify::cacNotify () : pIO (0)
{
}
cacNotify::~cacNotify ()
{
cacNotifyIO *pTmpIO = this->pIO;
if ( pTmpIO ) {
this->pIO = 0;
// the code fits together better in iother places
// if the delete and the uninstall are speparate steps
pTmpIO->uninstall ();
delete pTmpIO;
}
}
void cacNotify::completionNotify ()
void cacNotify::completionNotify ( cacChannelIO &chan )
{
ca_printf ("CAC: IO completion with no handler installed?\n");
ca_printf ( "CAC: IO completion for channel %s with no handler installed?\n",
chan.pName () );
}
void cacNotify::completionNotify ( unsigned type, unsigned long count, const void *pData )
void cacNotify::completionNotify ( cacChannelIO &chan,
unsigned type, unsigned long count, const void *pData )
{
ca_printf ("CAC: IO completion with no handler installed? type=%u count=%u data pointer=%p\n",
type, count, pData);
ca_printf ( "CAC: IO completion with no handler installed? channel=%s type=%u count=%u data pointer=%p\n",
chan.pName (), type, count, pData );
}
void cacNotify::exceptionNotify ( int status, const char *pContext )
void cacNotify::exceptionNotify ( cacChannelIO &chan, int status, const char *pContext )
{
ca_signal (status, pContext);
ca_signal_formated ( status, __FILE__, __LINE__, "%s channel=%s\n",
pContext, chan.pName () );
}
void cacNotify::exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count )
void cacNotify::exceptionNotify ( cacChannelIO &chan, int status,
const char *pContext, unsigned type, unsigned long count )
{
ca_signal_formated (status, __FILE__, __LINE__, "%s type=%d count=%ld\n",
pContext, type, count);
ca_signal_formated ( status, __FILE__, __LINE__, "%s channel=%s type=%d count=%ld\n",
chan.pName (), pContext, type, count );
}

View File

@@ -12,17 +12,8 @@
#include "iocinf.h"
cacNotifyIO::cacNotifyIO ( cacNotify &notifyIn ) : notify ( notifyIn )
{
assert ( ! this->notify.pIO );
this->notify.pIO = this;
}
cacNotifyIO::~cacNotifyIO ()
{
if ( this->notify.pIO == this ) {
this->notify.pIO = 0;
this->notify.destroy ();
}
this->callback.release ();
}

View File

@@ -30,12 +30,13 @@ void cacServiceList::registerService ( cacServiceIO &service )
this->unlock ();
}
cacLocalChannelIO * cacServiceList::createChannelIO (const char *pName, cac &cacCtx, cacChannel &chan)
cacChannelIO * cacServiceList::createChannelIO ( const char *pName,
cac &cacCtx, cacChannelNotify &chan )
{
cacLocalChannelIO *pChanIO = 0;
cacChannelIO *pChanIO = 0;
this->lock ();
tsDLIterBD <cacServiceIO> iter ( this->services.first () );
tsDLIterBD < cacServiceIO > iter ( this->services.first () );
while ( iter.valid () ) {
pChanIO = iter->createChannelIO ( pName, cacCtx, chan );
if ( pChanIO ) {

View File

@@ -47,10 +47,10 @@
extern "C" {
#endif
typedef struct oldChannel *chid;
typedef struct cacChannelIO *chid;
typedef chid chanId; /* for when the structures field name is "chid" */
typedef long chtype;
typedef struct oldSubscription *evid;
typedef struct cacNotifyIO *evid;
typedef double ca_real;
/* Format for the arguments to user connection handlers */
@@ -869,26 +869,6 @@ ca_sg_array_put (gid, type, 1u, chan, pValue)
*/
epicsShareFunc int epicsShareAPI ca_sg_stat (CA_SYNC_GID gid);
/*
* ca_modify_user_name()
*
* Modify or override the default
* client user name.
*
* pUserName R new user name string copied from this location
*/
epicsShareFunc int epicsShareAPI ca_modify_user_name ( const char *pUserName );
/*
* CA_MODIFY_HOST_NAME()
*
* Modify or override the default
* client host name.
*
* pHostName R new host name string copied from this location
*/
epicsShareFunc int epicsShareAPI ca_modify_host_name ( const char *pHostName );
/*
* ca_v42_ok()
*
@@ -950,6 +930,11 @@ epicsShareFunc int epicsShareAPI ca_client_status (unsigned level);
epicsShareFunc int epicsShareAPI ca_import (epicsThreadId tid);
epicsShareFunc int epicsShareAPI ca_import_cancel (epicsThreadId tid);
/*
* defunct
*/
epicsShareFunc int epicsShareAPI ca_modify_user_name ( const char *pUserName );
epicsShareFunc int epicsShareAPI ca_modify_host_name ( const char *pHostName );
#else /* CAC_ANSI_FUNC_PROTO */
epicsShareFunc short epicsShareAPI ca_get_field_type ();

View File

@@ -20,61 +20,52 @@
tsFreeList < class getCallback, 1024 > getCallback::freeList;
getCallback::getCallback (oldChannel &chanIn, caEventCallBackFunc *pFuncIn, void *pPrivateIn) :
chan (chanIn), pFunc (pFuncIn), pPrivate (pPrivateIn)
{
}
getCallback::~getCallback ()
{
}
void getCallback::destroy ()
void getCallback::release ()
{
delete this;
}
void getCallback::completionNotify ()
{
cacNotify::completionNotify ();
}
void getCallback::completionNotify ( unsigned type, unsigned long count, const void *pData )
void getCallback::completionNotify ( cacChannelIO &io,
unsigned type, unsigned long count, const void *pData )
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.chid = & io;
args.type = type;
args.count = count;
args.status = ECA_NORMAL;
args.dbr = pData;
(*this->pFunc) (args);
( *this->pFunc ) ( args );
}
void getCallback::exceptionNotify (int status, const char * /* pContext */)
void getCallback::exceptionNotify ( cacChannelIO &io, int status,
const char * /* pContext */)
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.type = 0;
args.chid = & io;
args.type = TYPENOTCONN;
args.count = 0;
args.status = status;
args.dbr = 0;
(*this->pFunc) (args);
( *this->pFunc ) ( args );
}
void getCallback::exceptionNotify ( int status, const char *pContext,
void getCallback::exceptionNotify ( cacChannelIO &io,
int status, const char *pContext,
unsigned type, unsigned long count )
{
cacNotify::exceptionNotify ( status, pContext, type, count);
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = & io;
args.type = type;
args.count = count;
args.status = status;
args.dbr = 0;
( *this->pFunc ) ( args );
}
void * getCallback::operator new ( size_t size )
{
return getCallback::freeList.allocate ( size );
}
void getCallback::operator delete ( void *pCadaver, size_t size )
{
getCallback::freeList.release ( pCadaver, size );
}

View File

@@ -16,6 +16,9 @@
* 505 665 1831
*/
#ifndef ioCounter_ILh
#define ioCounter_ILh
inline ioCounter::ioCounter () : pndrecvcnt ( 0u ), readSeq ( 0u )
{
}
@@ -26,16 +29,23 @@ inline void ioCounter::incrementOutstandingIO ()
if ( this->pndrecvcnt < UINT_MAX ) {
this->pndrecvcnt++;
}
else {
throwWithLocation ( caErrorCode (ECA_INTERNAL) );
}
this->mutex.unlock ();
}
inline void ioCounter::lockOutstandingIO () const
inline void ioCounter::incrementOutstandingIO ( unsigned readSeqIn )
{
this->mutex.lock ();
}
inline void ioCounter::unlockOutstandingIO () const
{
if ( readSeqIn == this->readSeq ) {
if ( this->pndrecvcnt < UINT_MAX ) {
this->pndrecvcnt++;
}
else {
throwWithLocation ( caErrorCode (ECA_INTERNAL) );
}
}
this->mutex.unlock ();
}
@@ -64,4 +74,4 @@ inline void ioCounter::cleanUpOutstandingIO ()
this->mutex.unlock ();
}
#endif // ioCounter_ILh

View File

@@ -28,7 +28,7 @@
#include <limits.h>
#include <stdarg.h>
#if defined (epicsExportSharedSymbols)
#if defined ( epicsExportSharedSymbols )
# error suspect that libCom was not imported
#endif
@@ -48,7 +48,6 @@
#include "epicsThread.h"
#include "osiTimer.h"
#include "epicsMutex.h"
#include "epicsEvent.h"
#include "resourceLib.h"
#include "localHostName.h"
#include "ipAddrToAsciiAsynchronous.h"
@@ -108,9 +107,6 @@
static const unsigned comBufSize = 0x4000;
class gnuWarningEliminate {
};
class wireSendAdapter {
public:
virtual unsigned sendBytes ( const void *pBuf,
@@ -150,16 +146,14 @@ public:
void operator delete ( void *pCadaver, size_t size );
bool flushToWire ( wireSendAdapter & );
unsigned fillFromWire ( wireRecvAdapter & );
private:
static tsFreeList < class comBuf, 0x20 > freeList;
protected:
~comBuf ();
private:
unsigned nextWriteIndex;
unsigned nextReadIndex;
unsigned char buf [ comBufSize ]; // optimal for 100 Mb Ethernet LAN MTU
unsigned clipNElem ( unsigned elemSize, unsigned nElem );
friend class gnuWarningEliminate;
static tsFreeList < class comBuf, 0x20 > freeList;
};
struct msgDescriptor {
@@ -262,14 +256,15 @@ class nciu : public cacChannelIO, public tsDLNode < nciu >,
public chronIntIdRes < nciu >, public tcpiiuPrivateListOfIO {
public:
nciu ( class cac &, netiiu &,
cacChannel &, const char *pNameIn );
cacChannelNotify &, const char *pNameIn );
bool fullyConstructed () const;
void destroy ();
void cacDestroy ();
void connect ( unsigned nativeType,
unsigned long nativeCount, unsigned sid );
void connect ();
void disconnect ( netiiu &newiiu );
int createChannelRequest ();
void initiateConnect ();
int read ( unsigned type,
unsigned long count, void *pValue );
int read ( unsigned type,
@@ -278,8 +273,9 @@ public:
unsigned long count, const void *pValue );
int write ( unsigned type,
unsigned long count, const void *pValue, cacNotify & );
int subscribe ( unsigned type,
unsigned long count, unsigned mask, cacNotify &notify );
int subscribe ( unsigned type, unsigned long nElem,
unsigned mask, cacNotify &notify,
cacNotifyIO *&pNotifyIO );
void hostName ( char *pBuf, unsigned bufLength ) const;
bool ca_v42_ok () const;
short nativeType () const;
@@ -291,13 +287,8 @@ public:
unsigned searchAttempts () const;
double beaconPeriod () const;
bool connected () const;
unsigned readSequence () const;
void incrementOutstandingIO ();
void decrementOutstandingIO ();
void decrementOutstandingIO ( unsigned seqNumber );
bool searchMsg ( unsigned short retrySeqNumber,
unsigned &retryNoForThisChannel );
bool fullyConstructed () const;
bool isAttachedToVirtaulCircuit ( const osiSockAddr & );
bool identifierEquivelence ( unsigned idToMatch );
void * operator new ( size_t size );
@@ -308,12 +299,17 @@ public:
ca_uint32_t getSID () const;
ca_uint32_t getCID () const;
netiiu * getPIIU ();
cac & getCAC ();
void searchReplySetUp ( netiiu &iiu, unsigned sidIn,
unsigned typeIn, unsigned long countIn );
void show ( unsigned level ) const;
bool verifyIIU ( netiiu & );
bool verifyConnected ( netiiu & );
void decrementOutstandingIO ( unsigned seqNumber );
void incrementOutstandingIO ( unsigned seqNumber );
void connectTimeoutNotify ();
protected:
~nciu (); // force pool allocation
private:
cac &cacCtx;
caar ar; // access rights
@@ -329,16 +325,13 @@ private:
unsigned f_fullyConstructed:1;
unsigned f_previousConn:1; // T if connected in the past
unsigned f_claimSent:1;
static tsFreeList < class nciu, 1024 > freeList;
~nciu (); // force pool allocation
unsigned f_firstConnectDecrementsOutstandingIO:1;
unsigned f_connectTimeOutSeen:1;
void lock () const;
void unlock () const;
void lockOutstandingIO () const;
void unlockOutstandingIO () const;
const char * pHostName () const; // deprecated - please do not use
friend class gnuWarningEliminate;
void notifyStateChangeFirstConnectInCountOfOutstandingIO ();
static tsFreeList < class nciu, 1024 > freeList;
};
class baseNMIU : public tsDLNode < baseNMIU >,
@@ -347,12 +340,15 @@ public:
baseNMIU ( nciu &chan );
virtual ~baseNMIU () = 0;
virtual void completionNotify () = 0;
virtual void completionNotify ( unsigned type, unsigned long count, const void *pData ) = 0;
virtual void exceptionNotify ( int status, const char *pContext ) = 0;
virtual void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count ) = 0;
virtual void completionNotify ( unsigned type,
unsigned long count, const void *pData ) = 0;
virtual void exceptionNotify ( int status,
const char *pContext ) = 0;
virtual void exceptionNotify ( int status,
const char *pContext, unsigned type,
unsigned long count ) = 0;
virtual class netSubscription * isSubscription ();
virtual void show ( unsigned level ) const;
virtual void uninstall () = 0;
ca_uint32_t getID () const;
nciu & channel () const;
void destroy ();
@@ -360,30 +356,36 @@ protected:
nciu &chan;
};
class netSubscription : private cacNotifyIO, public baseNMIU {
class netSubscription : public cacNotifyIO, public baseNMIU {
public:
netSubscription ( nciu &chan, unsigned type, unsigned long count,
unsigned mask, cacNotify &notify );
void destroy ();
void show ( unsigned level ) const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
unsigned long getCount () const;
unsigned getType () const;
unsigned getMask () const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~netSubscription ();
private:
unsigned long count;
unsigned type;
unsigned mask;
void uninstall ();
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
void completionNotify ( unsigned type,
unsigned long count, const void *pData );
void exceptionNotify ( int status,
const char *pContext );
void exceptionNotify ( int status,
const char *pContext, unsigned type, unsigned long count );
cacChannelIO & channelIO () const;
class netSubscription * isSubscription ();
~netSubscription ();
static tsFreeList < class netSubscription, 1024 > freeList;
friend class gnuWarningEliminate;
};
class netReadCopyIO : public baseNMIU {
@@ -393,53 +395,61 @@ public:
void show ( unsigned level ) const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~netReadCopyIO (); // must be allocated from pool
private:
unsigned type;
unsigned long count;
void *pValue;
unsigned seqNumber;
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void completionNotify ( );
void completionNotify ( unsigned type,
unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
void uninstall ();
~netReadCopyIO (); // must be allocated from pool
void exceptionNotify ( int status,
const char *pContext, unsigned type, unsigned long count );
cacChannelIO & channelIO () const;
static tsFreeList < class netReadCopyIO, 1024 > freeList;
friend class gnuWarningEliminate;
};
class netReadNotifyIO : public cacNotifyIO, public baseNMIU {
public:
netReadNotifyIO ( nciu &chan, cacNotify &notify );
void destroy ();
void show ( unsigned level ) const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
private:
void uninstall ();
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
protected:
~netReadNotifyIO ();
private:
void completionNotify ();
void completionNotify ( unsigned type,
unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status,
const char *pContext, unsigned type, unsigned long count );
cacChannelIO & channelIO () const;
static tsFreeList < class netReadNotifyIO, 1024 > freeList;
friend class gnuWarningEliminate;
};
class netWriteNotifyIO : public cacNotifyIO, public baseNMIU {
public:
netWriteNotifyIO ( nciu &chan, cacNotify &notify );
void destroy ();
void show ( unsigned level ) const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
private:
void uninstall ();
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
protected:
~netWriteNotifyIO ();
private:
void completionNotify ();
void completionNotify ( unsigned type,
unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status,
const char *pContext, unsigned type, unsigned long count );
cacChannelIO & channelIO () const;
static tsFreeList < class netWriteNotifyIO, 1024 > freeList;
friend class gnuWarningEliminate;
};
/*
@@ -497,7 +507,6 @@ public:
void show ( unsigned level ) const;
unsigned channelCount () const;
void disconnectAllChan ( netiiu & newiiu );
void destroyAllIO ( nciu &chan );
void connectTimeoutNotify ();
bool searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisChannel );
void resetChannelRetryCounts ();
@@ -518,9 +527,10 @@ public:
virtual void connectAllIO ( nciu &chan );
virtual void disconnectAllIO ( nciu &chan );
virtual int clearChannelRequest ( nciu & );
virtual void uninstallIO ( baseNMIU & );
virtual bool uninstallIO ( baseNMIU & );
virtual void subscriptionCancelRequest ( netSubscription &subscr, bool userThread );
virtual double beaconPeriod () const;
virtual bool destroyAllIO ( nciu &chan );
protected:
cac * pCAC () const;
@@ -605,7 +615,7 @@ public:
char *pInBuf, unsigned long blockSize );
void repeaterRegistrationMessage ( unsigned attemptNumber );
void flush ();
SOCKET getSock () const;
unsigned getPort () const;
void show ( unsigned level ) const;
bool isCurrentThread () const;
@@ -622,6 +632,7 @@ private:
SOCKET sock;
unsigned short repeaterPort;
unsigned short serverPort;
unsigned short localPort;
bool shutdownCmd;
bool sockCloseCompleted;
@@ -711,12 +722,11 @@ public:
void hostName ( char *pBuf, unsigned bufLength ) const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~hostNameCache ();
private:
bool ioComplete;
char hostNameBuf [128];
~hostNameCache ();
friend class gnuWarningEliminate;
static tsFreeList < class hostNameCache, 16 > freeList;
};
@@ -743,7 +753,6 @@ public:
void flush ();
virtual void show ( unsigned level ) const;
//osiSockAddr address () const;
SOCKET getSock () const;
bool setEchoRequestPending ();
void processIncoming ();
@@ -794,6 +803,7 @@ private:
unsigned sendBytes ( const void *pBuf, unsigned nBytesInBuf );
unsigned recvBytes ( void *pBuf, unsigned nBytesInBuf );
bool flushToWire ( bool userThread );
bool threadContextSensitiveFlushToWire ( bool userThread );
friend void cacSendThreadTCP ( void *pParam );
friend void cacRecvThreadTCP ( void *pParam );
@@ -842,7 +852,8 @@ private:
int status, const char *pContext, unsigned type, unsigned long count );
void connectAllIO ( nciu &chan );
void disconnectAllIO ( nciu &chan );
void uninstallIO ( baseNMIU & );
bool uninstallIO ( baseNMIU & );
bool destroyAllIO ( nciu &chan );
int subscriptionRequest ( netSubscription &subscr, bool userThread );
void subscriptionCancelRequest ( netSubscription &subscr, bool userThread );
@@ -851,25 +862,6 @@ private:
static const pProtoStubTCP tcpJumpTableCAC [];
};
#if 0
class claimMsgCache {
public:
claimMsgCache ( bool v44 );
~claimMsgCache ();
int deliverMsg ( netiiu &iiu );
void connectChannel ( cac & );
private:
char *pStr;
unsigned clientId;
unsigned serverId;
unsigned currentStrLen;
unsigned bufLen;
bool v44;
friend bool nciu::setClaimMsgCache ( class claimMsgCache & );
};
#endif
class inetAddrID {
public:
inetAddrID ( const struct sockaddr_in &addrIn );
@@ -892,15 +884,13 @@ public:
epicsShareFunc void show ( unsigned level) const;
epicsShareFunc void * operator new ( size_t size );
epicsShareFunc void operator delete ( void *pCadaver, size_t size );
protected:
epicsShareFunc ~bhe (); // force allocation from freeList
private:
tcpiiu *piiu;
epicsTime timeStamp;
double averagePeriod;
static tsFreeList < class bhe, 1024 > freeList;
epicsShareFunc ~bhe (); // force allocation from freeList
friend class gnuWarningEliminate;
};
class caErrorCode {
@@ -959,28 +949,26 @@ static const unsigned CASG_MAGIC = 0xFAB4CAFE;
class syncGroupNotify : public cacNotify, public tsDLNode < syncGroupNotify > {
public:
syncGroupNotify ( struct CASG &sgIn, void *pValue );
void destroy ();
void show (unsigned level) const;
void release ();
void show ( unsigned level ) const;
void * operator new (size_t size);
void operator delete (void *pCadaver, size_t size);
private:
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
void lock () const;
void unlock () const;
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
virtual ~syncGroupNotify (); // allocate only from pool
private:
struct CASG &sg;
unsigned magic;
void *pValue;
unsigned long seqNo;
void completionNotify ( cacChannelIO & );
void completionNotify ( cacChannelIO &,
unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext, unsigned type, unsigned long count );
static tsFreeList < class syncGroupNotify, 1024 > freeList;
friend class gnuWarningEliminate;
};
/*
@@ -1022,8 +1010,7 @@ public:
void decrementOutstandingIO ();
void decrementOutstandingIO ( unsigned seqNumber );
void incrementOutstandingIO ();
void lockOutstandingIO () const;
void unlockOutstandingIO () const;
void incrementOutstandingIO ( unsigned seqNumber );
unsigned readSequenceOfOutstandingIO () const;
unsigned currentOutstandingIOCount () const;
void cleanUpOutstandingIO ();
@@ -1065,9 +1052,6 @@ public:
// beacon management
void beaconNotify ( const inetAddrID &addr );
bhe *lookupBeaconInetAddr ( const inetAddrID &ina );
bhe *createBeaconHashEntry ( const inetAddrID &ina,
const epicsTime &initialTimeStamp );
void repeaterSubscribeConfirmNotify ();
// IIU routines
@@ -1090,15 +1074,14 @@ public:
void connectChannel ( unsigned id );
void connectChannel ( bool v44Ok, unsigned id,
unsigned nativeType, unsigned long nativeCount, unsigned sid );
void channelDestroy ( unsigned id );
void disconnectChannel ( unsigned id );
bool createChannelIO ( const char *name_str, cacChannel &chan );
cacChannelIO * createChannelIO ( const char *name_str, cacChannelNotify &chan );
void installNetworkChannel ( nciu &, netiiu *&piiu );
void lookupChannelAndTransferToTCP ( unsigned cid, unsigned sid,
unsigned typeCode, unsigned long count, unsigned minorVersionNumber,
const osiSockAddr & );
void accessRightsNotify ( unsigned id, caar );
void uninstallLocalChannel ( cacLocalChannelIO & );
void destroyNCIU ( nciu & );
void accessRightsNotify ( unsigned id, const caar & );
void uninstallChannel ( nciu & );
// sync group routines
CASG * lookupCASG ( unsigned id );
@@ -1109,9 +1092,8 @@ public:
void registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg );
void enableCallbackPreemption ();
void disableCallbackPreemption ();
void notifySearchResponse ( unsigned short retrySeqNo );
bool flushPermit () const;
const char * userNamePointer ();
const char * userNamePointer () const;
// diagnostics
unsigned connectionCount () const;
@@ -1121,13 +1103,13 @@ public:
void replaceErrLogHandler ( caPrintfFunc *ca_printf_func );
void ipAddrToAsciiAsynchronousRequestInstall ( ipAddrToAsciiAsynchronous & request );
void getFDRegCallback ( CAFDHANDLER *&fdRegFunc, void *&fdRegArg ) const;
private:
ipAddrToAsciiEngine ipToAEngine;
cacServiceList services;
tsDLList <tcpiiu> iiuList;
tsDLList <tcpiiu> iiuListLimbo;
tsDLList
<cacLocalChannelIO> localChanList;
chronIntIdResTable
< nciu > chanTable;
chronIntIdResTable
@@ -1154,10 +1136,6 @@ private:
unsigned initializingThreadsPriority;
bool enablePreemptiveCallback;
// IIU routines
tcpiiu * constructTCPIIU ( const osiSockAddr &, unsigned minorVersion );
double connectionTimeout () const;
int pendPrivate ( double timeout, int early );
bool setupUDP ();
};

View File

@@ -10,13 +10,13 @@
* Author: Jeff Hill
*
* Notes:
* 1) This class has a pointer to the IIU. Since it is possible
* for the channel to exist when no IIU exists (because the user
* created the channel), and because an IIU can disconnect and be
* destroyed at any time, then it is necessary to hold a mutex while
* the IIU pointer is in use. This mutex can not be the IIU's mutex
* because the IIU's lock must not be held while waiting for a
* message to be sent (otherwise a push pull deadlock can occur).
* 1) This class has a pointer to the IIU. This pointer always points at
* a valid IIU. If the client is deleted then the channel points at a
* static file scope IIU. IIU's that disconnect go into an inactive state
* and are stored on a list for later reuse. When the channel calls a
* member function of the IIU, the IIU verifies that the channel's IIU
* pointer is still pointing at itself only after it has acquired the IIU
* lock.
*/
#include "iocinf.h"
@@ -33,7 +33,7 @@ tsFreeList < class nciu, 1024 > nciu::freeList;
static const caar defaultAccessRights = { false, false };
nciu::nciu ( cac &cacIn, netiiu &iiuIn, cacChannel &chanIn,
nciu::nciu ( cac &cacIn, netiiu &iiuIn, cacChannelNotify &chanIn,
const char *pNameIn ) :
cacChannelIO ( chanIn ),
cacCtx ( cacIn ),
@@ -48,7 +48,9 @@ nciu::nciu ( cac &cacIn, netiiu &iiuIn, cacChannel &chanIn,
f_connected ( false ),
f_fullyConstructed ( true ),
f_previousConn ( false ),
f_claimSent ( false )
f_claimSent ( false ),
f_firstConnectDecrementsOutstandingIO ( false ),
f_connectTimeOutSeen ( false )
{
// second constraint is imposed by size field in protocol header
if ( this->nameLength > MAX_UDP_SEND - sizeof ( caHdr ) || this->nameLength > 0xffff ) {
@@ -67,13 +69,16 @@ void nciu::destroy ()
{
// this occurs here so that it happens when
// a lock is not applied
this->piiu->destroyAllIO ( *this );
unsigned i = 0u;
while ( ! this->piiu->destroyAllIO ( *this ) ) {
if ( i++ > 1000u ) {
this->cacCtx.printf (
"CAC: unable to destroy IO when channel destroyed?\n" );
break;
}
}
this->piiu->clearChannelRequest ( *this );
this->cacCtx.destroyNCIU ( *this );
}
void nciu::cacDestroy ()
{
this->cacCtx.uninstallChannel ( *this );
delete this;
}
@@ -83,9 +88,11 @@ nciu::~nciu ()
return;
}
// this must go in the derived class's destructor because
// this calls virtual functions in the cacChannelIO base
this->ioReleaseNotify ();
if ( ! this->f_connectTimeOutSeen && ! this->f_previousConn ) {
if ( this->f_firstConnectDecrementsOutstandingIO ) {
this->cacCtx.decrementOutstandingIO ();
}
}
delete [] this->pNameStr;
}
@@ -217,6 +224,12 @@ int nciu::write ( unsigned type, unsigned long countIn, const void *pValue, cacN
return this->piiu->writeNotifyRequest ( *this, notify, type, countIn, pValue );
}
void nciu::initiateConnect ()
{
this->notifyStateChangeFirstConnectInCountOfOutstandingIO ();
this->cacCtx.installNetworkChannel ( *this, this->piiu );
}
void nciu::connect ( unsigned nativeType,
unsigned long nativeCount, unsigned sidIn )
{
@@ -235,6 +248,13 @@ void nciu::connect ( unsigned nativeType,
}
this->lock ();
if ( ! this->f_connectTimeOutSeen && ! this->f_previousConn ) {
if ( this->f_firstConnectDecrementsOutstandingIO ) {
this->cacCtx.decrementOutstandingIO ();
}
}
bool v41Ok;
if ( this->piiu ) {
v41Ok = this->piiu->ca_v41_ok ();
@@ -263,7 +283,7 @@ void nciu::connect ( unsigned nativeType,
// resubscribe for monitors from this channel
this->piiu->connectAllIO ( *this );
this->connectNotify ();
this->notify ().connectNotify ( *this );
/*
* if less than v4.1 then the server will never
@@ -272,7 +292,16 @@ void nciu::connect ( unsigned nativeType,
* their call back here
*/
if ( ! v41Ok ) {
this->accessRightsNotify ( this->ar );
this->notify ().accessRightsNotify ( *this, this->ar );
}
}
void nciu::connectTimeoutNotify ()
{
if ( ! this->f_connectTimeOutSeen ) {
this->lock ();
this->f_connectTimeOutSeen = true;
this->unlock ();
}
}
@@ -309,8 +338,8 @@ void nciu::disconnect ( netiiu &newiiu )
/*
* look for events that have an event cancel in progress
*/
this->disconnectNotify ();
this->accessRightsNotify ( this->ar );
this->notify ().disconnectNotify ( *this );
this->notify ().accessRightsNotify ( *this, this->ar );
}
this->resetRetryCount ();
@@ -352,36 +381,6 @@ bool nciu::searchMsg ( unsigned short retrySeqNumber, unsigned &retryNoForThisCh
return status;
}
void nciu::incrementOutstandingIO ()
{
this->cacCtx.incrementOutstandingIO ();
}
void nciu::decrementOutstandingIO ()
{
this->cacCtx.decrementOutstandingIO ();
}
void nciu::decrementOutstandingIO ( unsigned seqNumber )
{
this->cacCtx.decrementOutstandingIO ( seqNumber );
}
void nciu::lockOutstandingIO () const
{
this->cacCtx.lockOutstandingIO ();
}
void nciu::unlockOutstandingIO () const
{
this->cacCtx.unlockOutstandingIO ();
}
unsigned nciu::readSequence () const
{
return this->cacCtx.readSequenceOfOutstandingIO ();
}
void nciu::hostName ( char *pBuf, unsigned bufLength ) const
{
this->piiu->hostName ( pBuf, bufLength );
@@ -499,7 +498,8 @@ int nciu::createChannelRequest ()
}
int nciu::subscribe ( unsigned type, unsigned long nElem,
unsigned mask, cacNotify &notify )
unsigned mask, cacNotify &notify,
cacNotifyIO *&pNotifyIO )
{
netSubscription *pSubcr = new netSubscription ( *this,
type, nElem, mask, notify );
@@ -508,6 +508,9 @@ int nciu::subscribe ( unsigned type, unsigned long nElem,
if ( status != ECA_NORMAL ) {
pSubcr->destroy ();
}
else {
pNotifyIO = pSubcr;
}
return status;
}
else {
@@ -515,6 +518,27 @@ int nciu::subscribe ( unsigned type, unsigned long nElem,
}
}
void nciu::notifyStateChangeFirstConnectInCountOfOutstandingIO ()
{
this->lock ();
// test is performed via a callback so that locking is correct
if ( ! this->f_connectTimeOutSeen && ! this->f_previousConn ) {
if ( this->notify ().includeFirstConnectInCountOfOutstandingIO () ) {
if ( ! this->f_firstConnectDecrementsOutstandingIO ) {
this->cacCtx.incrementOutstandingIO ();
this->f_firstConnectDecrementsOutstandingIO = true;
}
}
else {
if ( this->f_firstConnectDecrementsOutstandingIO ) {
this->cacCtx.decrementOutstandingIO ();
this->f_firstConnectDecrementsOutstandingIO = false;
}
}
}
this->unlock ();
}
void nciu::show ( unsigned level ) const
{
if ( this->f_connected ) {

View File

@@ -20,6 +20,8 @@
// nciu inline member functions
//
#include "ioCounter_IL.h"
inline void * nciu::operator new ( size_t size )
{
return nciu::freeList.allocate ( size );
@@ -58,7 +60,7 @@ inline void nciu::resetRetryCount ()
inline void nciu::accessRightsStateChange ( const caar &arIn )
{
this->ar = arIn;
this->accessRightsNotify ( this->ar );
this->notify ().accessRightsNotify ( *this, this->ar );
}
inline ca_uint32_t nciu::getSID () const
@@ -127,3 +129,19 @@ inline netiiu * nciu::getPIIU ()
return this->piiu;
}
inline cac & nciu::getCAC ()
{
return this->cacCtx;
}
inline void nciu::incrementOutstandingIO ( unsigned seqNumber )
{
this->cacCtx.incrementOutstandingIO ( seqNumber );
}
inline void nciu::decrementOutstandingIO ( unsigned seqNumber )
{
this->cacCtx.decrementOutstandingIO ( seqNumber );
}

View File

@@ -13,6 +13,7 @@
#include "iocinf.h"
#include "netReadCopyIO_IL.h"
#include "nciu_IL.h"
#include "baseNMIU_IL.h"
tsFreeList < class netReadCopyIO, 1024 > netReadCopyIO::freeList;
@@ -21,17 +22,11 @@ netReadCopyIO::netReadCopyIO ( nciu &chanIn, unsigned typeIn, unsigned long coun
baseNMIU ( chanIn ), type ( typeIn ), count ( countIn ),
pValue ( pValueIn ), seqNumber ( seqNumberIn )
{
chanIn.incrementOutstandingIO ();
this->chan.incrementOutstandingIO ( seqNumberIn );
}
netReadCopyIO::~netReadCopyIO ()
{
}
void netReadCopyIO::uninstall ()
{
this->chan.getPIIU ()->uninstallIO ( *this );
}
void netReadCopyIO::completionNotify ()
@@ -59,14 +54,22 @@ void netReadCopyIO::completionNotify ( unsigned typeIn,
void netReadCopyIO::exceptionNotify ( int status, const char *pContext )
{
ca_signal (status, pContext);
ca_signal_formated ( status, __FILE__, __LINE__,
"%s chan=%s\n", pContext, this->channelIO ().pName () );
}
void netReadCopyIO::exceptionNotify ( int status,
const char *pContextIn, unsigned typeIn, unsigned long countIn )
{
ca_signal_formated (status, __FILE__, __LINE__,
"%s type=%d count=%ld\n", pContextIn, typeIn, countIn);
ca_signal_formated ( status, __FILE__, __LINE__,
"%s chan=%s type=%d count=%ld\n", pContextIn,
this->channelIO ().pName (), typeIn, countIn);
}
cacChannelIO & netReadCopyIO::channelIO () const
{
return this->channel ();
}
void netReadCopyIO::show ( unsigned level ) const

View File

@@ -13,40 +13,47 @@
#include "iocinf.h"
#include "netReadNotifyIO_IL.h"
#include "nciu_IL.h"
#include "baseNMIU_IL.h"
tsFreeList < class netReadNotifyIO, 1024 > netReadNotifyIO::freeList;
netReadNotifyIO::netReadNotifyIO ( nciu &chan, cacNotify &notifyIn ) :
cacNotifyIO ( notifyIn ), baseNMIU ( chan ) {}
// private NOOP forces pool allocation
netReadNotifyIO::~netReadNotifyIO () {}
void netReadNotifyIO::uninstall ()
netReadNotifyIO::~netReadNotifyIO ()
{
this->chan.getPIIU ()->uninstallIO ( *this );
}
void netReadNotifyIO::destroy ()
{
delete this;
}
void netReadNotifyIO::completionNotify ()
{
this->cacNotifyIO::exceptionNotify ( ECA_INTERNAL, "no data returned ?" );
this->notify ().exceptionNotify ( this->channelIO (), ECA_INTERNAL, "no data returned ?" );
}
void netReadNotifyIO::completionNotify ( unsigned type,
unsigned long count, const void *pData )
{
this->cacNotifyIO::completionNotify ( type, count, pData );
this->notify ().completionNotify ( this->channelIO (), type, count, pData );
}
void netReadNotifyIO::exceptionNotify ( int status, const char *pContext )
{
this->cacNotifyIO::exceptionNotify ( status, pContext );
this->notify ().exceptionNotify ( this->channelIO (), status, pContext );
}
void netReadNotifyIO::exceptionNotify ( int status, const char *pContext,
unsigned type, unsigned long count )
{
this->cacNotifyIO::exceptionNotify ( status, pContext, type ,count );
this->notify ().exceptionNotify ( this->channelIO (), status, pContext, type ,count );
}
cacChannelIO & netReadNotifyIO::channelIO () const
{
return this->channel ();
}
void netReadNotifyIO::show ( unsigned level ) const

View File

@@ -13,6 +13,7 @@
#include "iocinf.h"
#include "netSubscription_IL.h"
#include "nciu_IL.h"
#include "baseNMIU_IL.h"
tsFreeList < class netSubscription, 1024 > netSubscription::freeList;
@@ -25,14 +26,21 @@ netSubscription::netSubscription ( nciu &chan, unsigned typeIn, unsigned long co
netSubscription::~netSubscription ()
{
// o netiiu lock must _not_ be applied when calling this
// o uninstall from channel and IIU occur in uninstall method
// netiiu lock must _not_ be applied when calling this
this->chan.getPIIU ()->subscriptionCancelRequest ( *this, true );
}
void netSubscription::uninstall ()
void netSubscription::destroy ()
{
this->chan.getPIIU ()->uninstallIO ( *this );
unsigned i = 0u;
while ( ! this->chan.getPIIU ()->uninstallIO ( *this ) ) {
if ( i++ > 1000u ) {
this->chan.getCAC ().printf (
"CAC: unable to destroy IO\n" );
break;
}
}
delete this;
}
class netSubscription * netSubscription::isSubscription ()
@@ -42,27 +50,32 @@ class netSubscription * netSubscription::isSubscription ()
void netSubscription::completionNotify ()
{
this->cacNotifyIO::completionNotify ();
this->notify ().completionNotify ( this->channel () );
}
void netSubscription::completionNotify ( unsigned typeIn,
unsigned long countIn, const void *pDataIn )
{
this->cacNotifyIO::completionNotify ( typeIn, countIn, pDataIn );
this->notify ().completionNotify ( this->channel (), typeIn, countIn, pDataIn );
}
void netSubscription::exceptionNotify ( int status, const char *pContext )
{
this->cacNotifyIO::exceptionNotify ( status, pContext );
this->notify ().exceptionNotify ( this->channel (), status, pContext );
}
void netSubscription::exceptionNotify ( int statusIn,
const char *pContextIn, unsigned typeIn, unsigned long countIn )
{
this->cacNotifyIO::exceptionNotify ( statusIn,
this->notify ().exceptionNotify ( this->channel (), statusIn,
pContextIn, typeIn, countIn );
}
cacChannelIO & netSubscription::channelIO () const
{
return this->channel ();
}
void netSubscription::show ( unsigned level ) const
{
printf ( "event subscription IO at %p, type %s, element count %lu, mask %u\n",

View File

@@ -13,44 +13,51 @@
#include "iocinf.h"
#include "netWriteNotifyIO_IL.h"
#include "nciu_IL.h"
#include "baseNMIU_IL.h"
tsFreeList < class netWriteNotifyIO, 1024 > netWriteNotifyIO::freeList;
netWriteNotifyIO::netWriteNotifyIO (nciu &chan, cacNotify &notifyIn) :
cacNotifyIO (notifyIn), baseNMIU (chan)
netWriteNotifyIO::netWriteNotifyIO ( nciu &chan, cacNotify &notifyIn ) :
cacNotifyIO ( notifyIn ), baseNMIU ( chan )
{
}
netWriteNotifyIO::~netWriteNotifyIO ()
{
// private NOOP forces pool allocation
}
void netWriteNotifyIO::uninstall ()
void netWriteNotifyIO::destroy ()
{
this->chan.getPIIU ()->uninstallIO ( *this );
delete this;
}
void netWriteNotifyIO::completionNotify ()
{
this->cacNotifyIO::completionNotify ();
this->notify ().completionNotify ( this->channelIO () );
}
void netWriteNotifyIO::completionNotify (
unsigned /* type */, unsigned long /* count */,
const void * /* pData */ )
{
this->cacNotifyIO::completionNotify ();
this->notify ().completionNotify ( this->channelIO () );
}
void netWriteNotifyIO::exceptionNotify ( int status, const char *pContext )
void netWriteNotifyIO::exceptionNotify ( int status,
const char *pContext )
{
this->cacNotifyIO::exceptionNotify (status, pContext);
this->notify ().exceptionNotify ( this->channelIO (), status, pContext );
}
void netWriteNotifyIO::exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count )
void netWriteNotifyIO::exceptionNotify ( int status,
const char *pContext, unsigned type, unsigned long count )
{
this->cacNotifyIO::exceptionNotify (status, pContext, type, count);
this->notify ().exceptionNotify ( this->channelIO (), status, pContext, type, count );
}
cacChannelIO & netWriteNotifyIO::channelIO () const
{
return this->channel ();
}
void netWriteNotifyIO::show ( unsigned level ) const

View File

@@ -24,7 +24,6 @@ netiiu::netiiu ( cac *pClientCtxIn ) : pClientCtx ( pClientCtxIn )
netiiu::~netiiu ()
{
assert ( this->channelList.count () == 0u );
}
void netiiu::show ( unsigned level ) const
@@ -99,23 +98,26 @@ void netiiu::disconnectAllChan ( netiiu & newiiu )
//
// netiiu::destroyAllIO ()
//
// care is taken not to not hold the lock while sending event
// subscription delete ( when the IO is deleted )
// 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 netiiu::destroyAllIO ( nciu &chan )
bool netiiu::destroyAllIO ( nciu &chan )
{
baseNMIU *pIO;
while ( true ) {
{
epicsAutoMutex autoMutex ( this->mutex );
pIO = chan.tcpiiuPrivateListOfIO::eventq.first ();
if ( ! pIO ) {
break;
}
pIO->uninstall ();
tsDLList < baseNMIU > eventQ;
{
epicsAutoMutex autoMutex ( this->mutex );
if ( chan.verifyIIU ( *this ) ) {
eventQ.add ( chan.tcpiiuPrivateListOfIO::eventq );
}
else {
return false;
}
}
while ( baseNMIU *pIO = eventQ.get () ) {
pIO->destroy ();
}
return true;
}
void netiiu::connectTimeoutNotify ()
@@ -260,13 +262,17 @@ void netiiu::connectAllIO ( nciu & )
{
}
void netiiu::uninstallIO ( baseNMIU &io )
bool netiiu::uninstallIO ( baseNMIU &io )
{
epicsAutoMutex autoMutex ( this->mutex );
if ( ! io.channel ().verifyIIU ( *this ) ) {
return false;
}
io.channel ().tcpiiuPrivateListOfIO::eventq.remove ( io );
return true;
}
double netiiu::beaconPeriod () const
{
return - DBL_MAX;
return ( - DBL_MAX );
}

View File

@@ -15,105 +15,133 @@
* 505 665 1831
*/
extern "C" void cacNoConnHandler ( struct connection_handler_args args );
class gnuOldAccessWarningEliminate {
};
struct oldChannel : public cacChannel {
class oldChannelNotify : public cacChannelNotify {
public:
oldChannel (caCh *pConnCallBack, void *pPrivate);
void destroy ();
void setPrivatePointer (void *);
oldChannelNotify ( caCh *pConnCallBackIn, void *pPrivateIn );
void release ();
void setPrivatePointer ( void * );
void * privatePointer () const;
int changeConnCallBack (caCh *pfunc);
int replaceAccessRightsEvent (caArh *pfunc);
void ioAttachNotify ();
void ioReleaseNotify ();
void * operator new (size_t size);
void operator delete (void *pCadaver, size_t size);
int changeConnCallBack ( cacChannelIO &, caCh *pfunc );
int replaceAccessRightsEvent ( cacChannelIO &chan, caArh *pfunc );
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~oldChannelNotify (); // must allocate from pool
private:
caCh *pConnCallBack;
void *pPrivate;
caArh *pAccessRightsFunc;
~oldChannel (); // must allocate from pool
void connectTimeoutNotify ();
void connectNotify ();
void disconnectNotify ();
void accessRightsNotify ( caar );
static tsFreeList < struct oldChannel, 1024 > freeList;
friend int epicsShareAPI ca_array_get (chtype type, unsigned long count, chid pChan, void *pValue);
friend void cacNoConnHandler ( struct connection_handler_args args );
void connectNotify ( cacChannelIO &chan );
void disconnectNotify ( cacChannelIO &chan );
void accessRightsNotify ( cacChannelIO &chan, const caar & );
bool includeFirstConnectInCountOfOutstandingIO () const;
class oldChannelNotify * pOldChannelNotify ();
static tsFreeList < class oldChannelNotify, 1024 > freeList;
};
class getCallback : public cacNotify {
public:
getCallback (oldChannel &chan, caEventCallBackFunc *pFunc, void *pPrivate);
void destroy ();
getCallback ( caEventCallBackFunc *pFunc, void *pPrivate );
void release ();
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~getCallback (); // allocate only out of pool
private:
oldChannel &chan;
caEventCallBackFunc *pFunc;
void *pPrivate;
~getCallback (); // allocate only out of pool
void completionNotify ();
void completionNotify (unsigned type, unsigned long count, const void *pData);
void exceptionNotify (int status, const char *pContext);
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
void completionNotify ( cacChannelIO &,
unsigned type, unsigned long count, const void *pData);
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext);
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext, unsigned type, unsigned long count );
static tsFreeList < class getCallback, 1024 > freeList;
friend class gnuWarningEliminate;
};
class putCallback : public cacNotify {
public:
putCallback (oldChannel &chan, caEventCallBackFunc *pFunc, void *pPrivate );
void destroy ();
putCallback ( caEventCallBackFunc *pFunc, void *pPrivate );
void release ();
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~putCallback (); // allocate only out of pool
private:
oldChannel &chan;
caEventCallBackFunc *pFunc;
void *pPrivate;
~putCallback (); // allocate only out of pool
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
void completionNotify ( cacChannelIO & );
void completionNotify ( cacChannelIO &,
unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext, unsigned type, unsigned long count );
static tsFreeList < class putCallback, 1024 > freeList;
friend class gnuWarningEliminate;
};
struct oldSubscription : public cacNotify {
public:
oldSubscription ( oldChannel &chan, caEventCallBackFunc *pFunc, void *pPrivate );
void destroy ();
oldChannel &channel ();
oldSubscription ( caEventCallBackFunc *pFunc, void *pPrivate );
void release ();
void * operator new ( size_t size );
void operator delete ( void *pCadaver, size_t size );
protected:
~oldSubscription (); // must allocate from pool
private:
oldChannel &chan;
caEventCallBackFunc *pFunc;
void *pPrivate;
void completionNotify ();
void completionNotify ( unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( int status, const char *pContext );
void exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count );
~oldSubscription (); // must allocate from pool
void completionNotify ( cacChannelIO &,
unsigned type, unsigned long count, const void *pData );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext );
void exceptionNotify ( cacChannelIO &,
int status, const char *pContext, unsigned type, unsigned long count );
static tsFreeList < struct oldSubscription, 1024 > freeList;
friend class gnuWarningEliminate;
};
inline getCallback::getCallback ( caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
pFunc ( pFuncIn ), pPrivate ( pPrivateIn )
{
}
inline void * getCallback::operator new ( size_t size )
{
return getCallback::freeList.allocate ( size );
}
inline void getCallback::operator delete ( void *pCadaver, size_t size )
{
getCallback::freeList.release ( pCadaver, size );
}
inline putCallback::putCallback ( caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
pFunc ( pFuncIn ), pPrivate ( pPrivateIn )
{
}
inline void * putCallback::operator new ( size_t size )
{
return putCallback::freeList.allocate ( size );
}
inline void putCallback::operator delete ( void *pCadaver, size_t size )
{
putCallback::freeList.release ( pCadaver, size );
}
inline oldSubscription::oldSubscription ( caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
pFunc ( pFuncIn ), pPrivate ( pPrivateIn )
{
}
inline void * oldSubscription::operator new ( size_t size )
{
return oldSubscription::freeList.allocate ( size );
}
inline void oldSubscription::operator delete ( void *pCadaver, size_t size )
{
oldSubscription::freeList.release ( pCadaver, size );
}

View File

@@ -1,196 +1,2 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "iocinf.h"
#include "oldAccess.h"
tsFreeList < struct oldChannel, 1024 > oldChannel::freeList;
/*
* cacAlreadyConnHandler ()
* This is installed into channels which dont have
* a connection handler when ca_pend_io() times
* out so that we will not decrement the pending
* recv count in the future.
*/
extern "C" void cacAlreadyConnHandler ( struct connection_handler_args )
{
}
/*
* cacNoConnHandler ()
* This is installed into channels which dont have
* a connection handler before ca_pend_io() times
* out so that we will properly decrement the pending
* recv count in the future.
*/
extern "C" void cacNoConnHandler ( struct connection_handler_args args )
{
args.chid->lockOutstandingIO ();
if ( args.chid->pConnCallBack == cacNoConnHandler ) {
args.chid->pConnCallBack = cacAlreadyConnHandler;
if ( args.op == CA_OP_CONN_UP ) {
args.chid->decrementOutstandingIO ();
}
}
args.chid->unlockOutstandingIO ();
}
extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
{
}
oldChannel::oldChannel (caCh *pConnCallBackIn, void *pPrivateIn) :
pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler )
{
if ( ! pConnCallBackIn ) {
this->pConnCallBack = cacNoConnHandler;
}
else {
this->pConnCallBack = pConnCallBackIn;
}
}
oldChannel::~oldChannel ()
{
if ( this->pConnCallBack == cacNoConnHandler ) {
this->decrementOutstandingIO ();
}
}
void oldChannel::destroy ()
{
delete this;
}
void oldChannel::ioAttachNotify ()
{
this->lockOutstandingIO ();
if ( this->pConnCallBack == cacNoConnHandler ) {
this->incrementOutstandingIO ();
}
this->unlockOutstandingIO ();
}
void oldChannel::ioReleaseNotify ()
{
this->lockOutstandingIO ();
if ( this->pConnCallBack == cacNoConnHandler ) {
this->decrementOutstandingIO ();
}
this->unlockOutstandingIO ();
}
void oldChannel::setPrivatePointer ( void *pPrivateIn )
{
this->pPrivate = pPrivateIn;
}
void * oldChannel::privatePointer () const
{
return this->pPrivate;
}
void oldChannel::connectTimeoutNotify ()
{
this->lockOutstandingIO ();
if ( this->pConnCallBack == cacNoConnHandler ) {
this->pConnCallBack = cacAlreadyConnHandler;
}
this->unlockOutstandingIO ();
}
void oldChannel::connectNotify ()
{
this->lockOutstandingIO ();
struct connection_handler_args args;
args.chid = this;
args.op = CA_OP_CONN_UP;
(*this->pConnCallBack) (args);
this->unlockOutstandingIO ();
}
void oldChannel::disconnectNotify ()
{
this->lockOutstandingIO ();
struct connection_handler_args args;
args.chid = this;
args.op = CA_OP_CONN_DOWN;
(*this->pConnCallBack) ( args );
this->unlockOutstandingIO ();
}
int oldChannel::changeConnCallBack ( caCh *pfunc )
{
this->lockOutstandingIO ();
if ( ! pfunc ) {
if ( this->pConnCallBack != cacNoConnHandler &&
this->pConnCallBack != cacAlreadyConnHandler ) {
if ( this->state () == cs_never_conn ) {
this->incrementOutstandingIO ();
this->pConnCallBack = cacNoConnHandler;
}
else {
this->pConnCallBack = cacAlreadyConnHandler;
}
}
}
else {
if ( this->pConnCallBack == cacNoConnHandler ) {
this->decrementOutstandingIO ();
}
this->pConnCallBack = pfunc;
}
this->unlockOutstandingIO ();
return ECA_NORMAL;
}
void oldChannel::accessRightsNotify ( caar ar )
{
struct access_rights_handler_args args;
args.chid = this;
args.ar = ar;
( *this->pAccessRightsFunc ) ( args );
}
int oldChannel::replaceAccessRightsEvent ( caArh *pfunc )
{
if ( ! pfunc ) {
pfunc = cacNoopAccesRightsHandler;
}
this->pAccessRightsFunc = pfunc;
if ( this->connected () ) {
struct access_rights_handler_args args;
args.chid = this;
args.ar = this->accessRights ();
(*pfunc) (args);
}
return ECA_NORMAL;
}
void * oldChannel::operator new ( size_t size )
{
return oldChannel::freeList.allocate ( size );
}
void oldChannel::operator delete ( void *pCadaver, size_t size )
{
oldChannel::freeList.release ( pCadaver, size );
}
#error defunct

124
src/ca/oldChannelNotify.cpp Normal file
View File

@@ -0,0 +1,124 @@
/*
* $Id$
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include "iocinf.h"
#include "oldAccess.h"
tsFreeList < class oldChannelNotify, 1024 > oldChannelNotify::freeList;
extern "C" void cacNoopConnHandler ( struct connection_handler_args )
{
}
extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
{
}
oldChannelNotify::oldChannelNotify ( caCh *pConnCallBackIn, void *pPrivateIn ) :
pConnCallBack ( pConnCallBackIn ? pConnCallBackIn : cacNoopConnHandler ),
pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler )
{
}
oldChannelNotify::~oldChannelNotify ()
{
}
void oldChannelNotify::release ()
{
delete this;
}
void oldChannelNotify::setPrivatePointer ( void *pPrivateIn )
{
this->pPrivate = pPrivateIn;
}
void * oldChannelNotify::privatePointer () const
{
return this->pPrivate;
}
int oldChannelNotify::changeConnCallBack ( cacChannelIO &chan, caCh *pfunc )
{
this->pConnCallBack = pfunc ? pfunc : cacNoopConnHandler;
// test for NOOP connection handler does _not_ occur here because the
// lock is not applied
chan.notifyStateChangeFirstConnectInCountOfOutstandingIO ();
return ECA_NORMAL;
}
int oldChannelNotify::replaceAccessRightsEvent ( cacChannelIO &chan, caArh *pfunc )
{
// The order of the following is significant to guarantee that the
// access rights handler is always gets called even if the channel connects
// while this is running. There is some very small chance that the
// handler could be called twice here with the same access rights state, but
// that will not upset the application.
this->pAccessRightsFunc = pfunc ? pfunc : cacNoopAccesRightsHandler;
if ( chan.connected () ) {
struct access_rights_handler_args args;
args.chid = &chan;
args.ar = chan.accessRights ();
( *pfunc ) ( args );
}
return ECA_NORMAL;
}
void oldChannelNotify::connectNotify ( cacChannelIO &chan )
{
struct connection_handler_args args;
args.chid = &chan;
args.op = CA_OP_CONN_UP;
( *this->pConnCallBack ) ( args );
}
void oldChannelNotify::disconnectNotify ( cacChannelIO &chan )
{
struct connection_handler_args args;
args.chid = &chan;
args.op = CA_OP_CONN_DOWN;
( *this->pConnCallBack ) ( args );
}
void oldChannelNotify::accessRightsNotify ( cacChannelIO &chan, const caar &ar )
{
struct access_rights_handler_args args;
args.chid = &chan;
args.ar = ar;
( *this->pAccessRightsFunc ) ( args );
}
bool oldChannelNotify::includeFirstConnectInCountOfOutstandingIO () const
{
return ( this->pConnCallBack == cacNoopConnHandler );
}
class oldChannelNotify * oldChannelNotify::pOldChannelNotify ()
{
return this;
}
void * oldChannelNotify::operator new ( size_t size )
{
return oldChannelNotify::freeList.allocate ( size );
}
void oldChannelNotify::operator delete ( void *pCadaver, size_t size )
{
oldChannelNotify::freeList.release ( pCadaver, size );
}

View File

@@ -15,31 +15,17 @@
tsFreeList < struct oldSubscription, 1024 > oldSubscription::freeList;
oldSubscription::oldSubscription ( oldChannel &chanIn, caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
chan (chanIn), pFunc (pFuncIn), pPrivate (pPrivateIn)
{
}
oldSubscription::~oldSubscription ()
{
}
oldChannel &oldSubscription::channel ()
{
return this->chan;
}
void oldSubscription::completionNotify ()
{
cacNotify::completionNotify ();
}
void oldSubscription::completionNotify (unsigned type, unsigned long count, const void *pData)
void oldSubscription::completionNotify ( cacChannelIO &io,
unsigned type, unsigned long count, const void *pData)
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.chid = & io;
args.type = type;
args.count = count;
args.status = ECA_NORMAL;
@@ -47,37 +33,38 @@ void oldSubscription::completionNotify (unsigned type, unsigned long count, cons
( *this->pFunc ) (args);
}
void oldSubscription::exceptionNotify ( int status, const char * /* pContext */ )
void oldSubscription::exceptionNotify ( cacChannelIO &io,
int status, const char * /* pContext */ )
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.type = 0;
args.chid = & io;
args.type = TYPENOTCONN;
args.count = 0;
args.status = status;
args.dbr = 0;
( *this->pFunc ) (args);
}
void oldSubscription::exceptionNotify ( int status, const char *pContext,
unsigned type, unsigned long count )
void oldSubscription::exceptionNotify ( cacChannelIO &io,
int status, const char *pContext,
unsigned type, unsigned long count )
{
cacNotify::exceptionNotify ( status, pContext, type, count );
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = & io;
args.type = type;
args.count = count;
args.status = status;
args.dbr = 0;
( *this->pFunc ) (args);
}
void oldSubscription::destroy ()
void oldSubscription::release ()
{
delete this;
}
void * oldSubscription::operator new ( size_t size )
{
return oldSubscription::freeList.allocate ( size );
}
void oldSubscription::operator delete ( void *pCadaver, size_t size )
{
oldSubscription::freeList.release ( pCadaver, size );
}

View File

@@ -20,64 +20,68 @@
tsFreeList < class putCallback, 1024 > putCallback::freeList;
putCallback::putCallback (oldChannel &chanIn, caEventCallBackFunc *pFuncIn, void *pPrivateIn ) :
chan (chanIn), pFunc (pFuncIn), pPrivate (pPrivateIn)
{
}
putCallback::~putCallback ()
{
}
void putCallback::destroy ()
void putCallback::release ()
{
delete this;
}
void putCallback::completionNotify ()
void putCallback::completionNotify ( cacChannelIO &io )
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.type = 0;
args.count = 0;
args.chid = & io;
args.type = TYPENOTCONN;
args.count = 0;
args.status = ECA_NORMAL;
args.dbr = 0;
(*this->pFunc) (args);
}
void putCallback::completionNotify ( unsigned type,
unsigned long count, const void *pData )
{
cacNotify::completionNotify ( type, count, pData );
}
void putCallback::exceptionNotify (int status, const char * /* pContext */ )
void putCallback::completionNotify ( cacChannelIO &io, unsigned type,
unsigned long count, const void *pData )
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = &this->chan;
args.type = 0;
args.chid = & io;
args.type = type;
args.count = count;
args.status = ECA_NORMAL;
args.dbr = 0;
(*this->pFunc) (args);
}
void putCallback::exceptionNotify ( cacChannelIO &io,
int status, const char * /* pContext */ )
{
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = & io;
args.type = TYPENOTCONN;
args.count = 0;
args.status = status;
args.dbr = 0;
(*this->pFunc) (args);
}
void putCallback::exceptionNotify ( int status,
void putCallback::exceptionNotify ( cacChannelIO &io, int status,
const char *pContext, unsigned type, unsigned long count )
{
cacNotify::exceptionNotify ( status, pContext, type, count );
struct event_handler_args args;
args.usr = this->pPrivate;
args.chid = & io;
args.type = type;
args.count = count;
args.status = status;
args.dbr = 0;
(*this->pFunc) (args);
}
void * putCallback::operator new ( size_t size )
{
return putCallback::freeList.allocate ( size );
}
void putCallback::operator delete ( void *pCadaver, size_t size )
{
putCallback::freeList.release ( pCadaver, size );
}

View File

@@ -41,7 +41,7 @@ syncGroupNotify::syncGroupNotify ( CASG &sgIn, void *pValueIn ) :
this->sg.mutex.unlock ();
}
void syncGroupNotify::destroy ()
void syncGroupNotify::release ()
{
delete this;
}
@@ -53,8 +53,10 @@ syncGroupNotify::~syncGroupNotify ()
this->sg.mutex.unlock ();
}
void syncGroupNotify::completionNotify ()
void syncGroupNotify::completionNotify ( cacChannelIO & )
{
bool done;
if ( this->magic != CASG_MAGIC ) {
ca_printf ("cac: sync group io_complete(): bad sync grp op magic number?\n");
return;
@@ -64,21 +66,28 @@ void syncGroupNotify::completionNotify ()
if ( this->seqNo == this->sg.seqNo ) {
assert ( this->sg.opPendCount > 0u );
this->sg.opPendCount--;
done = this->sg.opPendCount == 0;
}
else {
done = true;
}
this->sg.mutex.unlock ();
if ( this->sg.opPendCount == 0 ) {
if ( done ) {
this->sg.sem.signal ();
}
}
void syncGroupNotify::completionNotify ( unsigned type, unsigned long count, const void *pData )
void syncGroupNotify::completionNotify ( cacChannelIO &,
unsigned type, unsigned long count, const void *pData )
{
if ( this->magic != CASG_MAGIC ) {
ca_printf ("cac: sync group io_complete(): bad sync grp op magic number?\n");
return;
}
bool complete;
this->sg.mutex.lock ();
if ( this->seqNo == this->sg.seqNo ) {
/*
@@ -86,14 +95,18 @@ void syncGroupNotify::completionNotify ( unsigned type, unsigned long count, con
*/
if ( this->pValue ) {
size_t size = dbr_size_n ( type, count );
memcpy (this->pValue, pData, size);
memcpy ( this->pValue, pData, size );
}
assert ( this->sg.opPendCount > 0u );
this->sg.opPendCount--;
complete = this->sg.opPendCount == 0;
}
else {
complete = true;
}
this->sg.mutex.unlock ();
if ( this->sg.opPendCount == 0 ) {
if ( complete ) {
this->sg.sem.signal ();
}
}
@@ -104,27 +117,20 @@ void syncGroupNotify::show ( unsigned /* level */ ) const
this->pValue, this->magic, this->seqNo, &this->sg);
}
void syncGroupNotify::exceptionNotify ( int status, const char *pContext )
void syncGroupNotify::exceptionNotify ( cacChannelIO &io,
int status, const char *pContext )
{
ca_signal_formated ( status, __FILE__, __LINE__,
"CA Sync Group request failed because \"%s\"\n", pContext);
"CA Sync Group request to channel %s failed because \"%s\"\n",
io.pName (), pContext);
}
void syncGroupNotify::exceptionNotify ( int status, const char *pContext, unsigned type, unsigned long count )
void syncGroupNotify::exceptionNotify ( cacChannelIO &io,
int status, const char *pContext, unsigned type, unsigned long count )
{
ca_signal_formated ( status, __FILE__, __LINE__,
"CA Sync Group request failed with type=%d count=%ld because \"%s\"\n",
type, count, pContext);
}
void syncGroupNotify::lock () const
{
this->sg.mutex.lock ();
}
void syncGroupNotify::unlock () const
{
this->sg.mutex.unlock ();
"CA Sync Group request failed with channel=%s type=%d count=%ld because \"%s\"\n",
io.pName (), type, count, pContext);
}
void * syncGroupNotify::operator new (size_t size)

View File

@@ -508,6 +508,14 @@ bool tcpiiu::initiateConnect ( const osiSockAddr &addrIn, unsigned minorVersion,
socket_close ( this->sock );
return false;
}
CAFDHANDLER *fdRegFunc;
void *fdRegArg;
this->pCAC ()->getFDRegCallback ( fdRegFunc, fdRegArg );
if ( fdRegFunc ) {
( *fdRegFunc ) ( fdRegArg, this->sock, TRUE );
}
return true;
}
@@ -594,7 +602,6 @@ void tcpiiu::cleanShutdown ()
else {
this->state = iiu_disconnected;
}
}
else if ( this->state == iiu_connecting ) {
int status = socket_close ( this->sock );
@@ -662,6 +669,13 @@ void tcpiiu::disconnect ()
this->ioTable.numEntriesInstalled () );
}
CAFDHANDLER *fdRegFunc;
void *fdRegArg;
this->pCAC ()->getFDRegCallback ( fdRegFunc, fdRegArg );
if ( fdRegFunc ) {
( *fdRegFunc ) ( fdRegArg, this->sock, FALSE );
}
this->cleanShutdown ();
// wait for send thread to exit
@@ -1157,7 +1171,7 @@ void tcpiiu::readRespAction ()
void tcpiiu::clearChannelRespAction ()
{
this->pCAC ()->channelDestroy ( this->curMsg.m_available );
// currently a noop
}
void tcpiiu::exceptionRespAction ()
@@ -1421,7 +1435,7 @@ int tcpiiu::writeRequest ( nciu &chan, unsigned type, unsigned nElem, const void
}
if ( this->sendQue.flushThreshold ( postcnt + 16u ) ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
epicsAutoMutex autoMutex ( this->mutex );
@@ -1484,7 +1498,7 @@ int tcpiiu::writeNotifyRequest ( nciu &chan, cacNotify &notify, unsigned type,
}
if ( this->sendQue.flushThreshold ( postcnt + 16u ) ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
epicsAutoMutex autoMutex ( this->mutex );
@@ -1532,7 +1546,7 @@ int tcpiiu::readCopyRequest ( nciu &chan, unsigned type, unsigned nElem, void *p
}
if ( this->sendQue.flushThreshold ( 16u ) ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
epicsAutoMutex autoMutex ( this->mutex );
@@ -1543,8 +1557,9 @@ int tcpiiu::readCopyRequest ( nciu &chan, unsigned type, unsigned nElem, void *p
status = ECA_DISCONNCHID;
}
else {
netReadCopyIO *pIO = new netReadCopyIO ( chan, type, nElem, pValue,
this->pCAC ()->readSequenceOfOutstandingIO () );
unsigned seqNo = this->pCAC ()->readSequenceOfOutstandingIO ();
netReadCopyIO *pIO = new netReadCopyIO ( chan, type,
nElem, pValue, seqNo );
if ( ! pIO ) {
status = ECA_ALLOCMEM;
}
@@ -1575,7 +1590,7 @@ int tcpiiu::readNotifyRequest ( nciu &chan, cacNotify &notify,
}
if ( this->sendQue.flushThreshold ( 16u ) ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
epicsAutoMutex autoMutex ( this->mutex );
@@ -1668,7 +1683,7 @@ int tcpiiu::clearChannelRequest ( nciu &chan )
int status;
if ( this->sendQue.flushThreshold ( 16u ) ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
epicsAutoMutex autoMutex ( this->mutex );
@@ -1707,7 +1722,7 @@ int tcpiiu::subscriptionRequest ( netSubscription &subscr, bool userThread )
if ( this->sendQue.flushThreshold ( 32u ) ) {
if ( userThread ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
else {
this->flush ();
@@ -1748,7 +1763,7 @@ void tcpiiu::subscriptionCancelRequest ( netSubscription &subscr, bool userThrea
{
if ( this->sendQue.flushThreshold ( 16u ) ) {
if ( userThread ) {
this->flushToWire ( true );
this->threadContextSensitiveFlushToWire ( true );
}
else {
this->flush ();
@@ -1775,10 +1790,8 @@ void tcpiiu::lastChannelDetachNotify ()
this->cleanShutdown ();
}
bool tcpiiu::flushToWire ( bool userThread )
bool tcpiiu::threadContextSensitiveFlushToWire ( bool userThread )
{
bool success = true;
// the recv thread is not permitted to flush as this
// can result in a push / pull deadlock on the TCP pipe,
// but in that case we still schedual the flush through
@@ -1787,6 +1800,12 @@ bool tcpiiu::flushToWire ( bool userThread )
this->flush ();
return true;
}
return this->flushToWire ( userThread );
}
bool tcpiiu::flushToWire ( bool userThread )
{
bool success = true;
// enable callback processing prior to taking the flush lock
if ( userThread ) {
@@ -1984,13 +2003,43 @@ void tcpiiu::disconnectAllIO ( nciu &chan )
}
}
void tcpiiu::uninstallIO ( baseNMIU &io )
//
// 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
//
bool tcpiiu::destroyAllIO ( nciu &chan )
{
tsDLList < baseNMIU > eventQ;
{
epicsAutoMutex autoMutex ( this->mutex );
if ( chan.verifyIIU ( *this ) ) {
while ( baseNMIU *pIO = eventQ.get () ) {
this->ioTable.remove ( *pIO );
eventQ.add ( *pIO );
}
}
else {
return false;
}
}
while ( baseNMIU *pIO = eventQ.get () ) {
pIO->destroy ();
}
return true;
}
bool tcpiiu::uninstallIO ( baseNMIU &io )
{
epicsAutoMutex autoMutex ( this->mutex );
if ( io.channel ().verifyConnected ( *this ) ) {
if ( io.channel ().verifyIIU ( *this ) ) {
this->ioTable.remove ( io );
}
else {
return false;
}
io.channel ().tcpiiuPrivateListOfIO::eventq.remove ( io );
return true;
}
double tcpiiu::beaconPeriod () const