many changes associated will disconnecting the channel but not disconnecting the circuit
This commit is contained in:
@@ -38,6 +38,9 @@
|
||||
|
||||
extern epicsThreadPrivateId caClientContextId;
|
||||
|
||||
cacService * ca_client_context::pDefaultService = 0;
|
||||
epicsMutex ca_client_context::defaultServiceInstallMutex;
|
||||
|
||||
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
|
||||
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
|
||||
@@ -47,6 +50,22 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
{
|
||||
static const unsigned short PORT_ANY = 0u;
|
||||
|
||||
if ( ! osiSockAttach () ) {
|
||||
throwWithLocation ( noSocket () );
|
||||
}
|
||||
|
||||
{
|
||||
// this wont consistently work if called from file scope constructor
|
||||
epicsGuard < epicsMutex > guard ( ca_client_context::defaultServiceInstallMutex );
|
||||
if ( ca_client_context::pDefaultService ) {
|
||||
this->pServiceContext.reset (
|
||||
& ca_client_context::pDefaultService->contextCreate ( this->mutex, *this ) );
|
||||
}
|
||||
else {
|
||||
this->pServiceContext.reset ( new cac ( this->mutex, *this ) );
|
||||
}
|
||||
}
|
||||
|
||||
this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if ( this->sock == INVALID_SOCKET ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -113,9 +132,6 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
this->localPort = epicsNTOH16 ( tmpAddr.ia.sin_port );
|
||||
}
|
||||
|
||||
epics_auto_ptr < cac > pCAC (
|
||||
new cac ( *this ) );
|
||||
|
||||
epics_auto_ptr < epicsGuard < epicsMutex > > pCBGuard;
|
||||
if ( ! enablePreemptiveCallback ) {
|
||||
pCBGuard.reset ( new epicsGuard < epicsMutex > ( this->callbackMutex ) );
|
||||
@@ -123,7 +139,6 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
|
||||
// multiple steps ensure exception safety
|
||||
this->pCallbackGuard = pCBGuard;
|
||||
this->pClientCtx = pCAC;
|
||||
}
|
||||
|
||||
ca_client_context::~ca_client_context ()
|
||||
@@ -133,49 +148,75 @@ ca_client_context::~ca_client_context ()
|
||||
( this->fdRegArg, this->sock, false );
|
||||
}
|
||||
epicsSocketDestroy ( this->sock );
|
||||
|
||||
osiSockRelease ();
|
||||
|
||||
// force a logical shutdown order
|
||||
// so that the cac class does not hang its
|
||||
// receive threads during their shutdown sequence
|
||||
// and so that classes using this classes mutex
|
||||
// are destroyed before the mutex is destroyed
|
||||
if ( this->pCallbackGuard.get() ) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
|
||||
this->pServiceContext.reset ( 0 );
|
||||
}
|
||||
else {
|
||||
this->pServiceContext.reset ( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
void ca_client_context::destroyChannel ( oldChannelNotify & chan )
|
||||
{
|
||||
chan.~oldChannelNotify ();
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
chan.destructor ( guard );
|
||||
this->oldChannelNotifyFreeList.release ( & chan );
|
||||
}
|
||||
|
||||
void ca_client_context::destroyGetCopy ( getCopy & gc )
|
||||
void ca_client_context::destroyGetCopy (
|
||||
epicsGuard < epicsMutex > & guard, getCopy & gc )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
gc.~getCopy ();
|
||||
this->getCopyFreeList.release ( & gc );
|
||||
}
|
||||
|
||||
void ca_client_context::destroyGetCallback ( getCallback & gcb )
|
||||
void ca_client_context::destroyGetCallback (
|
||||
epicsGuard < epicsMutex > & guard, getCallback & gcb )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
gcb.~getCallback ();
|
||||
this->getCallbackFreeList.release ( & gcb );
|
||||
}
|
||||
|
||||
void ca_client_context::destroyPutCallback ( putCallback & pcb )
|
||||
void ca_client_context::destroyPutCallback (
|
||||
epicsGuard < epicsMutex > & guard, putCallback & pcb )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
pcb.~putCallback ();
|
||||
this->putCallbackFreeList.release ( & pcb );
|
||||
}
|
||||
|
||||
void ca_client_context::destroySubscription ( oldSubscription & os )
|
||||
void ca_client_context::destroySubscription (
|
||||
epicsGuard < epicsMutex > & guard, oldSubscription & os )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
os.~oldSubscription ();
|
||||
this->subscriptionFreeList.release ( & os );
|
||||
}
|
||||
|
||||
void ca_client_context::changeExceptionEvent ( caExceptionHandler *pfunc, void *arg )
|
||||
void ca_client_context::changeExceptionEvent (
|
||||
caExceptionHandler * pfunc, void * arg )
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->ca_exception_func = pfunc;
|
||||
this->ca_exception_arg = arg;
|
||||
// should block here until releated callback in progress completes
|
||||
}
|
||||
|
||||
void ca_client_context::replaceErrLogHandler ( caPrintfFunc *ca_printf_func )
|
||||
void ca_client_context::replaceErrLogHandler (
|
||||
caPrintfFunc * ca_printf_func )
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( ca_printf_func ) {
|
||||
this->pVPrintfFunc = ca_printf_func;
|
||||
}
|
||||
@@ -185,16 +226,18 @@ void ca_client_context::replaceErrLogHandler ( caPrintfFunc *ca_printf_func )
|
||||
// should block here until releated callback in progress completes
|
||||
}
|
||||
|
||||
void ca_client_context::registerForFileDescriptorCallBack ( CAFDHANDLER *pFunc, void *pArg )
|
||||
void ca_client_context::registerForFileDescriptorCallBack (
|
||||
CAFDHANDLER *pFunc, void *pArg )
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->fdRegFunc = pFunc;
|
||||
this->fdRegArg = pArg;
|
||||
this->fdRegFuncNeedsToBeCalled = true;
|
||||
// should block here until releated callback in progress completes
|
||||
}
|
||||
|
||||
int ca_client_context::printf ( const char *pformat, ... ) const
|
||||
int ca_client_context::printf (
|
||||
const char *pformat, ... ) const
|
||||
{
|
||||
va_list theArgs;
|
||||
int status;
|
||||
@@ -208,11 +251,12 @@ int ca_client_context::printf ( const char *pformat, ... ) const
|
||||
return status;
|
||||
}
|
||||
|
||||
int ca_client_context::vPrintf ( const char *pformat, va_list args ) const // X aCC 361
|
||||
int ca_client_context::vPrintf (
|
||||
const char *pformat, va_list args ) const // X aCC 361
|
||||
{
|
||||
caPrintfFunc *pFunc;
|
||||
caPrintfFunc * pFunc;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
pFunc = this->pVPrintfFunc;
|
||||
}
|
||||
if ( pFunc ) {
|
||||
@@ -223,81 +267,137 @@ int ca_client_context::vPrintf ( const char *pformat, va_list args ) const // X
|
||||
}
|
||||
}
|
||||
|
||||
void ca_client_context::exception ( int stat, const char *pCtx,
|
||||
const char *pFile, unsigned lineNo )
|
||||
void ca_client_context::exception (
|
||||
epicsGuard < epicsMutex > & guard, int stat, const char * pCtx,
|
||||
const char * pFile, unsigned lineNo )
|
||||
{
|
||||
struct exception_handler_args args;
|
||||
caExceptionHandler *pFunc;
|
||||
void *pArg;
|
||||
caExceptionHandler * pFunc = this->ca_exception_func;
|
||||
void * pArg = this->ca_exception_arg;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
|
||||
pFunc = this->ca_exception_func;
|
||||
pArg = this->ca_exception_arg;
|
||||
}
|
||||
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = NULL;
|
||||
args.type = TYPENOTCONN;
|
||||
args.count = 0;
|
||||
args.addr = NULL;
|
||||
args.stat = stat;
|
||||
args.op = CA_OP_OTHER;
|
||||
args.ctx = pCtx;
|
||||
args.pFile = pFile;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
}
|
||||
else {
|
||||
this->pClientCtx->signal ( stat, pFile, lineNo, pCtx );
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = NULL;
|
||||
args.type = TYPENOTCONN;
|
||||
args.count = 0;
|
||||
args.addr = NULL;
|
||||
args.stat = stat;
|
||||
args.op = CA_OP_OTHER;
|
||||
args.ctx = pCtx;
|
||||
args.pFile = pFile;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
}
|
||||
else {
|
||||
this->signal ( stat, pFile, lineNo, pCtx );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ca_client_context::exception ( int status, const char *pContext,
|
||||
const char *pFileName, unsigned lineNo, oldChannelNotify &chan,
|
||||
void ca_client_context::exception (
|
||||
epicsGuard < epicsMutex > & guard, int status, const char * pContext,
|
||||
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
|
||||
unsigned type, arrayElementCount count, unsigned op )
|
||||
{
|
||||
struct exception_handler_args args;
|
||||
caExceptionHandler *pFunc;
|
||||
void *pArg;
|
||||
caExceptionHandler * pFunc = this->ca_exception_func;
|
||||
void * pArg = this->ca_exception_arg;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > autoMutex ( this->mutex );
|
||||
pFunc = this->ca_exception_func;
|
||||
pArg = this->ca_exception_arg;
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = &chan;
|
||||
args.type = type;
|
||||
args.count = count;
|
||||
args.addr = NULL;
|
||||
args.stat = status;
|
||||
args.op = op;
|
||||
args.ctx = pContext;
|
||||
args.pFile = pFileName;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
}
|
||||
else {
|
||||
this->signal ( status, pFileName, lineNo,
|
||||
"op=%u, channel=%s, type=%s, count=%lu, ctx=\"%s\"",
|
||||
op, ca_name ( &chan ),
|
||||
dbr_type_to_text ( static_cast <int> ( type ) ),
|
||||
count, pContext );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NOOP if they disable exceptions
|
||||
if ( pFunc ) {
|
||||
args.chid = &chan;
|
||||
args.type = type;
|
||||
args.count = count;
|
||||
args.addr = NULL;
|
||||
args.stat = status;
|
||||
args.op = op;
|
||||
args.ctx = pContext;
|
||||
args.pFile = pFileName;
|
||||
args.lineNo = lineNo;
|
||||
args.usr = pArg;
|
||||
( *pFunc ) ( args );
|
||||
void ca_client_context::signal ( int ca_status, const char * pfilenm,
|
||||
int lineno, const char * pFormat, ... )
|
||||
{
|
||||
va_list theArgs;
|
||||
va_start ( theArgs, pFormat );
|
||||
this->vSignal ( ca_status, pfilenm, lineno, pFormat, theArgs);
|
||||
va_end ( theArgs );
|
||||
}
|
||||
|
||||
void ca_client_context::vSignal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, va_list args )
|
||||
{
|
||||
static const char *severity[] =
|
||||
{
|
||||
"Warning",
|
||||
"Success",
|
||||
"Error",
|
||||
"Info",
|
||||
"Fatal",
|
||||
"Fatal",
|
||||
"Fatal",
|
||||
"Fatal"
|
||||
};
|
||||
|
||||
this->printf ( "CA.Client.Exception...............................................\n" );
|
||||
|
||||
this->printf ( " %s: \"%s\"\n",
|
||||
severity[ CA_EXTRACT_SEVERITY ( ca_status ) ],
|
||||
ca_message ( ca_status ) );
|
||||
|
||||
if ( pFormat ) {
|
||||
this->printf ( " Context: \"" );
|
||||
this->vPrintf ( pFormat, args );
|
||||
this->printf ( "\"\n" );
|
||||
}
|
||||
else {
|
||||
this->pClientCtx->signal ( status, pFileName, lineNo,
|
||||
"op=%u, channel=%s, type=%s, count=%lu, ctx=\"%s\"",
|
||||
op, ca_name ( &chan ),
|
||||
dbr_type_to_text ( static_cast <int> ( type ) ),
|
||||
count, pContext );
|
||||
|
||||
if ( pfilenm ) {
|
||||
this->printf ( " Source File: %s line %d\n",
|
||||
pfilenm, lineno );
|
||||
}
|
||||
|
||||
epicsTime current = epicsTime::getCurrent ();
|
||||
char date[64];
|
||||
current.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S.%f");
|
||||
this->printf ( " Current Time: %s\n", date );
|
||||
|
||||
/*
|
||||
* Terminate execution if unsuccessful
|
||||
*/
|
||||
if( ! ( ca_status & CA_M_SUCCESS ) &&
|
||||
CA_EXTRACT_SEVERITY ( ca_status ) != CA_K_WARNING ){
|
||||
errlogFlush ();
|
||||
abort ();
|
||||
}
|
||||
|
||||
this->printf ( "..................................................................\n" );
|
||||
}
|
||||
|
||||
void ca_client_context::show ( unsigned level ) const
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
::printf ( "ca_client_context at %p pndRecvCnt=%u ioSeqNo=%u\n",
|
||||
static_cast <const void *> ( this ),
|
||||
this->pndRecvCnt, this->ioSeqNo );
|
||||
|
||||
if ( level > 0u ) {
|
||||
this->mutex.show ( level - 1u );
|
||||
this->pClientCtx->show ( level - 1u );
|
||||
this->pServiceContext->show ( guard, level - 1u );
|
||||
::printf ( "\tpreemptive callback is %s\n",
|
||||
this->pCallbackGuard.get() ? "disabled" : "enabled" );
|
||||
::printf ( "\tthere are %u unsatisfied IO operations blocking ca_pend_io()\n",
|
||||
@@ -306,6 +406,8 @@ void ca_client_context::show ( unsigned level ) const
|
||||
this->ioSeqNo );
|
||||
::printf ( "IO done event:\n");
|
||||
this->ioDone.show ( level - 1u );
|
||||
::printf ( "Synchronous group identifier hash table:\n" );
|
||||
this->sgTable.show ( level - 1u );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,37 +417,26 @@ void ca_client_context::attachToClientCtx ()
|
||||
epicsThreadPrivateSet ( caClientContextId, this );
|
||||
}
|
||||
|
||||
void ca_client_context::incrementOutstandingIO ( unsigned ioSeqNoIn )
|
||||
void ca_client_context::incrementOutstandingIO (
|
||||
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->ioSeqNo == ioSeqNoIn ) {
|
||||
assert ( this->pndRecvCnt < UINT_MAX );
|
||||
this->pndRecvCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
void ca_client_context::decrementOutstandingIO ( unsigned ioSeqNoIn )
|
||||
void ca_client_context::decrementOutstandingIO (
|
||||
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
|
||||
{
|
||||
bool signalNeeded;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
if ( this->ioSeqNo == ioSeqNoIn ) {
|
||||
assert ( this->pndRecvCnt > 0u );
|
||||
this->pndRecvCnt--;
|
||||
if ( this->pndRecvCnt == 0u ) {
|
||||
signalNeeded = true;
|
||||
}
|
||||
else {
|
||||
signalNeeded = false;
|
||||
}
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
if ( this->ioSeqNo == ioSeqNoIn ) {
|
||||
assert ( this->pndRecvCnt > 0u );
|
||||
this->pndRecvCnt--;
|
||||
if ( this->pndRecvCnt == 0u ) {
|
||||
this->ioDone.signal ();
|
||||
}
|
||||
else {
|
||||
signalNeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( signalNeeded ) {
|
||||
this->ioDone.signal ();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +458,9 @@ int ca_client_context::pendIO ( const double & timeout )
|
||||
epicsTime beg_time = epicsTime::getCurrent ();
|
||||
double remaining = timeout;
|
||||
|
||||
this->flushRequest ();
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
this->flush ( guard );
|
||||
|
||||
while ( this->pndRecvCnt > 0 ) {
|
||||
if ( remaining < CAC_SIGNIFICANT_DELAY ) {
|
||||
@@ -375,7 +468,10 @@ int ca_client_context::pendIO ( const double & timeout )
|
||||
break;
|
||||
}
|
||||
|
||||
this->blockForEventAndEnableCallbacks ( this->ioDone, remaining );
|
||||
{
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->blockForEventAndEnableCallbacks ( this->ioDone, remaining );
|
||||
}
|
||||
|
||||
double delay = epicsTime::getCurrent () - beg_time;
|
||||
if ( delay < timeout ) {
|
||||
@@ -386,11 +482,8 @@ int ca_client_context::pendIO ( const double & timeout )
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
this->ioSeqNo++;
|
||||
this->pndRecvCnt = 0u;
|
||||
}
|
||||
this->ioSeqNo++;
|
||||
this->pndRecvCnt = 0u;
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -411,10 +504,16 @@ int ca_client_context::pendEvent ( const double & timeout )
|
||||
|
||||
epicsTime current = epicsTime::getCurrent ();
|
||||
|
||||
this->flushRequest ();
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->flush ( guard );
|
||||
}
|
||||
|
||||
// process at least once if preemptive callback is disabled
|
||||
if ( this->pCallbackGuard.get() ) {
|
||||
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
//
|
||||
// This is needed because in non-preemptive callback mode
|
||||
// legacy applications that use file descriptor managers
|
||||
@@ -423,11 +522,11 @@ int ca_client_context::pendEvent ( const double & timeout )
|
||||
// been read. We must guarantee that other threads get a
|
||||
// chance to run if there is data in any of the sockets.
|
||||
//
|
||||
epicsGuardRelease < epicsMutex > unguardcb ( *this->pCallbackGuard );
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
if ( this->fdRegFunc ) {
|
||||
epicsGuardRelease < ca_client_context_mutex > unguard ( guard );
|
||||
// remove short udp message sent to wake up a file descriptor manager
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
|
||||
// remove short udp message sent to wake
|
||||
// up a file descriptor manager
|
||||
osiSockAddr tmpAddr;
|
||||
osiSocklen_t addrSize = sizeof ( tmpAddr.sa );
|
||||
char buf = 0;
|
||||
@@ -439,7 +538,7 @@ int ca_client_context::pendEvent ( const double & timeout )
|
||||
}
|
||||
this->noWakeupSincePend = true;
|
||||
while ( this->callbackThreadsPending > 0 ) {
|
||||
epicsGuardRelease < ca_client_context_mutex > unguard ( guard );
|
||||
epicsGuardRelease < epicsMutex > unguard ( guard );
|
||||
this->callbackThreadActivityComplete.wait ( 30.0 );
|
||||
}
|
||||
}
|
||||
@@ -486,7 +585,7 @@ void ca_client_context::callbackLock ()
|
||||
if ( this->pCallbackGuard.get() ) {
|
||||
bool sendNeeded = false;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->callbackThreadsPending++;
|
||||
if ( this->fdRegFunc && this->noWakeupSincePend ) {
|
||||
this->noWakeupSincePend = false;
|
||||
@@ -517,7 +616,7 @@ void ca_client_context::callbackUnlock ()
|
||||
if ( this->pCallbackGuard.get() ) {
|
||||
bool signalNeeded = false;
|
||||
{
|
||||
epicsGuard < ca_client_context_mutex > guard ( this->mutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( this->callbackThreadsPending <= 1 ) {
|
||||
if ( this->callbackThreadsPending == 1 ) {
|
||||
this->callbackThreadsPending = 0;
|
||||
@@ -537,71 +636,101 @@ void ca_client_context::callbackUnlock ()
|
||||
void ca_client_context::changeConnCallBack (
|
||||
caCh * pfunc, caCh * & pConnCallBack, const bool & currentlyConnected )
|
||||
{
|
||||
epicsGuard < epicsMutex > callbackGuard ( this->callbackMutex );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( ! currentlyConnected ) {
|
||||
if ( pfunc ) {
|
||||
if ( ! pConnCallBack ) {
|
||||
this->decrementOutstandingIO ( this->ioSeqNo );
|
||||
this->decrementOutstandingIO ( guard, this->ioSeqNo );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( pConnCallBack ) {
|
||||
this->incrementOutstandingIO ( this->ioSeqNo );
|
||||
this->incrementOutstandingIO ( guard, this->ioSeqNo );
|
||||
}
|
||||
}
|
||||
}
|
||||
pConnCallBack = pfunc;
|
||||
}
|
||||
|
||||
void ca_client_context::registerService ( cacService &service )
|
||||
cacChannel & ca_client_context::createChannel (
|
||||
epicsGuard < epicsMutex > & guard, const char * pChannelName,
|
||||
oldChannelNotify & chan, cacChannel::priLev pri )
|
||||
{
|
||||
this->pClientCtx->registerService ( service );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
return this->pServiceContext->createChannel (
|
||||
guard, pChannelName, chan, pri );
|
||||
}
|
||||
|
||||
cacChannel & ca_client_context::createChannel ( const char * name_str,
|
||||
oldChannelNotify & chan, cacChannel::priLev pri )
|
||||
void ca_client_context::flush ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
return this->pClientCtx->createChannel ( name_str, chan, pri );
|
||||
this->pServiceContext->flush ( guard );
|
||||
}
|
||||
|
||||
void ca_client_context::flushRequest ()
|
||||
unsigned ca_client_context::circuitCount () const
|
||||
{
|
||||
this->pClientCtx->flushRequest ();
|
||||
}
|
||||
|
||||
unsigned ca_client_context::connectionCount () const
|
||||
{
|
||||
return this->pClientCtx->connectionCount ();
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
return this->pServiceContext->circuitCount ( guard );
|
||||
}
|
||||
|
||||
unsigned ca_client_context::beaconAnomaliesSinceProgramStart () const
|
||||
{
|
||||
return this->pClientCtx->beaconAnomaliesSinceProgramStart ();
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
return this->pServiceContext->beaconAnomaliesSinceProgramStart ( guard );
|
||||
}
|
||||
|
||||
CASG * ca_client_context::lookupCASG ( unsigned id )
|
||||
void ca_client_context::installCASG (
|
||||
epicsGuard < epicsMutex > & guard, CASG & sg )
|
||||
{
|
||||
return this->pClientCtx->lookupCASG ( id );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->sgTable.add ( sg );
|
||||
}
|
||||
|
||||
void ca_client_context::installCASG ( CASG &sg )
|
||||
void ca_client_context::uninstallCASG (
|
||||
epicsGuard < epicsMutex > & guard, CASG & sg )
|
||||
{
|
||||
this->pClientCtx->installCASG ( sg );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->sgTable.remove ( sg );
|
||||
}
|
||||
|
||||
void ca_client_context::uninstallCASG ( CASG &sg )
|
||||
CASG * ca_client_context::lookupCASG (
|
||||
epicsGuard < epicsMutex > & guard, unsigned idIn )
|
||||
{
|
||||
this->pClientCtx->uninstallCASG ( sg );
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
CASG * psg = this->sgTable.lookup ( idIn );
|
||||
if ( psg ) {
|
||||
if ( ! psg->verify ( guard ) ) {
|
||||
psg = 0;
|
||||
}
|
||||
}
|
||||
return psg;
|
||||
}
|
||||
|
||||
void ca_client_context::vSignal ( int ca_status, const char *pfilenm,
|
||||
int lineno, const char *pFormat, va_list args )
|
||||
void ca_client_context::selfTest () const
|
||||
{
|
||||
this->pClientCtx->vSignal ( ca_status, pfilenm,
|
||||
lineno, pFormat, args );
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
this->sgTable.verify ();
|
||||
this->pServiceContext->selfTest ( guard );
|
||||
}
|
||||
|
||||
void ca_client_context::selfTest ()
|
||||
epicsMutex & ca_client_context::mutexRef () const
|
||||
{
|
||||
this->pClientCtx->selfTest ();
|
||||
return this->mutex;
|
||||
}
|
||||
|
||||
cacContext & ca_client_context::createNetworkContext ( epicsMutex & mutex )
|
||||
{
|
||||
return * new cac ( mutex, *this );
|
||||
}
|
||||
|
||||
|
||||
void epicsShareAPI caInstallDefaultService ( cacService & service )
|
||||
{
|
||||
// this wont consistently work if called from file scope constructor
|
||||
epicsGuard < epicsMutex > guard ( ca_client_context::defaultServiceInstallMutex );
|
||||
if ( ca_client_context::pDefaultService ) {
|
||||
throw std::logic_error ( "CA in-memory service already installed and can't be replaced");
|
||||
}
|
||||
ca_client_context::pDefaultService = & service;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user