Jeff Hill johill@lanl.gov
2013-05-16 11:17:47 -06:00
parent de2495d276
commit 5e5ea11658
22 changed files with 1287 additions and 1066 deletions

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -25,8 +25,6 @@
#include "cac.h"
#include "sgAutoPtr.h"
casgRecycle::~casgRecycle () {}
CASG::CASG ( epicsGuard < epicsMutex > & guard, ca_client_context & cacIn ) :
client ( cacIn ), magic ( CASG_MAGIC )
{
@@ -37,13 +35,14 @@ CASG::~CASG ()
{
}
void CASG::destructor (
void CASG::destructor (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( this->verify ( guard ) ) {
this->reset ( guard );
this->reset ( cbGuard, guard );
this->client.uninstallCASG ( guard, *this );
this->magic = 0;
}
@@ -61,9 +60,9 @@ bool CASG::verify ( epicsGuard < epicsMutex > & ) const
/*
* CASG::block ()
*/
int CASG::block (
epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard,
int CASG::block (
epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard,
double timeout )
{
epicsTime cur_time;
@@ -75,7 +74,7 @@ int CASG::block (
guard.assertIdenticalMutex ( this->client.mutexRef() );
// prevent recursion nightmares by disabling blocking
// for IO from within a CA callback.
// for IO from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
@@ -120,44 +119,45 @@ int CASG::block (
}
/*
* force a time update
* force a time update
*/
cur_time = epicsTime::getCurrent ();
delay = cur_time - beg_time;
}
this->reset ( guard );
return status;
}
void CASG::reset (
void CASG::reset (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->destroyCompletedIO ( guard );
this->destroyPendingIO ( guard );
this->destroyCompletedIO ( cbGuard, guard );
this->destroyPendingIO ( cbGuard, guard );
}
// lock must be applied
void CASG::destroyCompletedIO (
void CASG::destroyCompletedIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
syncGroupNotify * pNotify;
while ( ( pNotify = this->ioCompletedList.get () ) ) {
pNotify->destroy ( guard, * this );
pNotify->destroy ( cbGuard, guard );
}
}
void CASG::destroyPendingIO (
void CASG::destroyPendingIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
pNotify->cancel ( guard );
// cancel must release the guard while
pNotify->cancel ( cbGuard, guard );
// cancel must release the guard while
// canceling put callbacks so we
// must double check list membership
if ( pNotify->ioPending ( guard ) ) {
@@ -166,7 +166,7 @@ void CASG::destroyPendingIO (
else {
this->ioCompletedList.remove ( *pNotify );
}
pNotify->destroy ( guard, *this );
pNotify->destroy ( cbGuard, guard );
}
}
@@ -176,7 +176,7 @@ void CASG::show ( unsigned level ) const
this->show ( guard, level );
}
void CASG::show (
void CASG::show (
epicsGuard < epicsMutex > & guard, unsigned level ) const
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
@@ -184,14 +184,14 @@ void CASG::show (
this->getId (), this->magic, this->ioPendingList.count () );
if ( level ) {
::printf ( "\tPending" );
tsDLIterConst < syncGroupNotify > notifyPending =
tsDLIterConst < syncGroupNotify > notifyPending =
this->ioPendingList.firstIter ();
while ( notifyPending.valid () ) {
notifyPending->show ( guard, level - 1u );
notifyPending++;
}
::printf ( "\tCompleted" );
tsDLIterConst < syncGroupNotify > notifyCompleted =
tsDLIterConst < syncGroupNotify > notifyCompleted =
this->ioCompletedList.firstIter ();
while ( notifyCompleted.valid () ) {
notifyCompleted->show ( guard, level - 1u );
@@ -201,10 +201,11 @@ void CASG::show (
}
bool CASG::ioComplete (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->destroyCompletedIO ( guard );
this->destroyCompletedIO ( cbGuard, guard );
return this->ioPendingList.count () == 0u;
}
@@ -212,9 +213,9 @@ void CASG::put ( epicsGuard < epicsMutex > & guard, chid pChan,
unsigned type, arrayElementCount count, const void * pValue )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this, this->ioPendingList );
sgAutoPtr < syncGroupWriteNotify > pNotify ( guard, *this );
pNotify = syncGroupWriteNotify::factory (
this->freeListWriteOP, *this, pChan );
this->freeListWriteOP, *this, & CASG :: recycleWriteNotifyIO, pChan );
pNotify->begin ( guard, type, count, pValue );
pNotify.release ();
}
@@ -223,14 +224,14 @@ void CASG::get ( epicsGuard < epicsMutex > & guard, chid pChan,
unsigned type, arrayElementCount count, void *pValue )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this, this->ioPendingList );
sgAutoPtr < syncGroupReadNotify > pNotify ( guard, *this );
pNotify = syncGroupReadNotify::factory (
this->freeListReadOP, *this, pChan, pValue );
this->freeListReadOP, *this, & CASG :: recycleReadNotifyIO, pChan, pValue );
pNotify->begin ( guard, type, count );
pNotify.release ();
}
void CASG::completionNotify (
void CASG::completionNotify (
epicsGuard < epicsMutex > & guard, syncGroupNotify & notify )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
@@ -241,56 +242,56 @@ void CASG::completionNotify (
}
}
void CASG::recycleSyncGroupWriteNotify (
epicsGuard < epicsMutex > & guard, syncGroupWriteNotify & io )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->freeListWriteOP.release ( & io );
}
void CASG::recycleSyncGroupReadNotify (
epicsGuard < epicsMutex > & guard, syncGroupReadNotify & io )
void CASG :: recycleReadNotifyIO ( epicsGuard < epicsMutex > & guard,
syncGroupReadNotify & io )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->freeListReadOP.release ( & io );
}
void CASG :: recycleWriteNotifyIO ( epicsGuard < epicsMutex > & guard,
syncGroupWriteNotify & io )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
this->freeListWriteOP.release ( & io );
}
int CASG :: printFormated ( const char *pformat, ... )
{
va_list theArgs;
int status;
va_start ( theArgs, pformat );
status = this->client.varArgsPrintFormated ( pformat, theArgs );
va_end ( theArgs );
return status;
}
void CASG::exception (
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
void CASG::exception (
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( status != ECA_CHANDESTROY ) {
this->client.exception (
this->client.exception (
guard, status, pContext, pFileName, lineNo );
}
}
void CASG::exception (
epicsGuard < epicsMutex > & guard,
void CASG::exception (
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op )
{
guard.assertIdenticalMutex ( this->client.mutexRef() );
if ( status != ECA_CHANDESTROY ) {
this->client.exception (
guard, status, pContext, pFileName,
this->client.exception (
guard, status, pContext, pFileName,
lineNo, chan, type, count, op );
}
}

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -30,7 +30,7 @@
/*
* allocate error message string array
* allocate error message string array
* here so I can use sizeof
*/
#define CA_ERROR_GLBLSOURCE
@@ -182,7 +182,7 @@ int epicsShareAPI ca_task_initialize ( void )
}
// extern "C"
int epicsShareAPI ca_context_create (
int epicsShareAPI ca_context_create (
ca_preemptive_callback_select premptiveCallbackSelect )
{
ca_client_context *pcac;
@@ -202,7 +202,7 @@ int epicsShareAPI ca_context_create (
return ECA_NORMAL;
}
pcac = new ca_client_context (
pcac = new ca_client_context (
premptiveCallbackSelect == ca_enable_preemptive_callback );
if ( ! pcac ) {
return ECA_ALLOCMEM;
@@ -275,7 +275,7 @@ int epicsShareAPI ca_task_exit ()
*/
// extern "C"
int epicsShareAPI ca_build_and_connect ( const char *name_str, chtype get_type,
arrayElementCount get_count, chid * chan, void *pvalue,
arrayElementCount get_count, chid * chan, void *pvalue,
caCh *conn_func, void *puser )
{
if ( get_type != TYPENOTCONN && pvalue != 0 && get_count != 0 ) {
@@ -286,14 +286,14 @@ int epicsShareAPI ca_build_and_connect ( const char *name_str, chtype get_type,
}
/*
* ca_search_and_connect()
* ca_search_and_connect()
*/
// extern "C"
int epicsShareAPI ca_search_and_connect (
const char * name_str, chid * chanptr,
caCh * conn_func, void * puser )
{
return ca_create_channel ( name_str, conn_func,
return ca_create_channel ( name_str, conn_func,
puser, CA_PRIORITY_DEFAULT, chanptr );
}
@@ -312,7 +312,7 @@ int epicsShareAPI ca_create_channel (
CAFDHANDLER * pFunc = 0;
void * pArg = 0;
{
epicsGuard < epicsMutex >
epicsGuard < epicsMutex >
guard ( pcac->mutex );
if ( pcac->fdRegFuncNeedsToBeCalled ) {
pFunc = pcac->fdRegFunc;
@@ -327,9 +327,9 @@ int epicsShareAPI ca_create_channel (
try {
epicsGuard < epicsMutex > guard ( pcac->mutex );
oldChannelNotify * pChanNotify =
new ( pcac->oldChannelNotifyFreeList )
oldChannelNotify ( guard, *pcac, name_str,
oldChannelNotify * pChanNotify =
new ( pcac->oldChannelNotifyFreeList )
oldChannelNotify ( guard, *pcac, name_str,
conn_func, puser, priority );
// make sure that their chan pointer is set prior to
// calling connection call backs
@@ -352,9 +352,9 @@ int epicsShareAPI ca_create_channel (
return ECA_UNAVAILINSERV;
}
catch ( std :: exception & except ) {
pcac->printFormated (
pcac->printFormated (
"ca_create_channel: "
"unexpected exception was \"%s\"",
"unexpected exception was \"%s\"",
except.what () );
return ECA_INTERNAL;
}
@@ -369,22 +369,42 @@ int epicsShareAPI ca_create_channel (
* ca_clear_channel ()
*
* a known defect here is that there will be a
* crash if they destroy the channel after destroying
* crash if they destroy the channel after destroying
* its context
*/
// extern "C"
int epicsShareAPI ca_clear_channel ( chid pChan )
{
ca_client_context & cac = pChan->getClientCtx ();
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
pChan->eliminateExcessiveSendBacklog ( guard );
{
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
pChan->eliminateExcessiveSendBacklog ( guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
if ( cac.pCallbackGuard.get() &&
cac.createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( cac.mutex );
pChan->destructor ( *cac.pCallbackGuard.get(), guard );
cac.oldChannelNotifyFreeList.release ( pChan );
}
else {
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( cac.cbMutex );
epicsGuard < epicsMutex > guard ( cac.mutex );
pChan->destructor ( *cac.pCallbackGuard.get(), guard );
cac.oldChannelNotifyFreeList.release ( pChan );
}
pChan->destructor ( guard );
cac.oldChannelNotifyFreeList.release ( pChan );
return ECA_NORMAL;
}
@@ -399,7 +419,7 @@ int epicsShareAPI ca_add_exception_event ( caExceptionHandler *pfunc, void *arg
if ( caStatus != ECA_NORMAL ) {
return caStatus;
}
pcac->changeExceptionEvent ( pfunc, arg );
return ECA_NORMAL;
@@ -408,10 +428,10 @@ int epicsShareAPI ca_add_exception_event ( caExceptionHandler *pfunc, void *arg
/*
* ca_add_masked_array_event
*/
int epicsShareAPI ca_add_masked_array_event (
chtype type, arrayElementCount count, chid pChan,
caEventCallBackFunc *pCallBack, void *pCallBackArg,
ca_real, ca_real, ca_real,
int epicsShareAPI ca_add_masked_array_event (
chtype type, arrayElementCount count, chid pChan,
caEventCallBackFunc *pCallBack, void *pCallBackArg,
ca_real, ca_real, ca_real,
evid *monixptr, long mask )
{
return ca_create_subscription ( type, count, pChan, mask,
@@ -429,7 +449,7 @@ int epicsShareAPI ca_clear_event ( evid pMon )
// extern "C"
chid epicsShareAPI ca_evid_to_chid ( evid pMon )
{
return & pMon->channel ();
return & pMon->channel ();
}
// extern "C"
@@ -498,7 +518,7 @@ int epicsShareAPI ca_pend_io ( ca_real timeout )
/*
* ca_flush_io ()
*/
*/
int epicsShareAPI ca_flush_io ()
{
ca_client_context * pcac;
@@ -545,7 +565,7 @@ void epicsShareAPI ca_signal ( long ca_status, const char *message )
* ca_message (long ca_status)
*
* - if it is an unknown error code then it possible
* that the error string generated below
* that the error string generated below
* will be overwritten before (or while) the caller
* of this routine is calling this routine
* (if they call this routine again).
@@ -567,7 +587,7 @@ const char * epicsShareAPI ca_message ( long ca_status )
* ca_signal_with_file_and_lineno()
*/
// extern "C"
void epicsShareAPI ca_signal_with_file_and_lineno ( long ca_status,
void epicsShareAPI ca_signal_with_file_and_lineno ( long ca_status,
const char *message, const char *pfilenm, int lineno )
{
ca_signal_formated ( ca_status, pfilenm, lineno, message );
@@ -577,7 +597,7 @@ void epicsShareAPI ca_signal_with_file_and_lineno ( long ca_status,
* ca_signal_formated()
*/
// extern "C"
void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm,
void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm,
int lineno, const char *pFormat, ... )
{
ca_client_context *pcac;
@@ -590,12 +610,12 @@ void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm,
}
va_list theArgs;
va_start ( theArgs, pFormat );
va_start ( theArgs, pFormat );
if ( pcac ) {
pcac->vSignal ( ca_status, pfilenm, lineno, pFormat, theArgs );
}
else {
fprintf ( stderr, "CA exception in thread w/o CA ctx: status=%s file=%s line=%d: \n",
fprintf ( stderr, "CA exception in thread w/o CA ctx: status=%s file=%s line=%d: \n",
ca_message ( ca_status ), pfilenm, lineno );
if ( pFormat ) {
vfprintf ( stderr, pFormat, theArgs );
@@ -607,7 +627,7 @@ void epicsShareAPI ca_signal_formated ( long ca_status, const char *pfilenm,
/*
* CA_ADD_FD_REGISTRATION
*
* call their function with their argument whenever
* call their function with their argument whenever
* a new fd is added or removed
* (for a manager of the select system call under UNIX)
*
@@ -631,7 +651,7 @@ int epicsShareAPI ca_add_fd_registration ( CAFDHANDLER * func, void * arg )
* function that returns the CA version string
*/
// extern "C"
const char * epicsShareAPI ca_version ()
const char * epicsShareAPI ca_version ()
{
return CA_VERSION_STRING ( CA_MINOR_PROTOCOL_REVISION );
}
@@ -660,7 +680,7 @@ int epicsShareAPI ca_replace_printf_handler ( caPrintfFunc *ca_printf_func )
* (for testing purposes only)
*/
// extern "C"
unsigned epicsShareAPI ca_get_ioc_connection_count ()
unsigned epicsShareAPI ca_get_ioc_connection_count ()
{
ca_client_context * pcac;
int caStatus = fetchClientContext ( & pcac );
@@ -720,7 +740,7 @@ struct ca_client_context * epicsShareAPI ca_current_context ()
{
struct ca_client_context *pCtx;
if ( caClientContextId ) {
pCtx = ( struct ca_client_context * )
pCtx = ( struct ca_client_context * )
epicsThreadPrivateGet ( caClientContextId );
}
else {
@@ -749,7 +769,7 @@ int epicsShareAPI ca_attach_context ( struct ca_client_context * pCtx )
return ECA_NORMAL;
}
void epicsShareAPI ca_detach_context ()
void epicsShareAPI ca_detach_context ()
{
if ( caClientContextId ) {
epicsThreadPrivateSet ( caClientContextId, 0 );
@@ -794,43 +814,43 @@ epicsShareDef const int epicsTypeToDBR_XXXX [lastEpicsType+1] = {
// extern "C"
epicsShareDef const epicsType DBR_XXXXToEpicsType [LAST_BUFFER_TYPE+1] = {
epicsOldStringT,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsFloat64T,
epicsOldStringT,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsFloat64T,
epicsOldStringT,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsFloat64T,
epicsOldStringT,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsFloat64T,
epicsOldStringT,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsInt16T,
epicsFloat32T,
epicsEnum16T,
epicsUInt8T,
epicsInt32T,
epicsFloat64T,
epicsUInt16T,
@@ -939,7 +959,7 @@ epicsShareDef const unsigned short dbr_value_size[LAST_BUFFER_TYPE+1] = {
sizeof(dbr_string_t), /* string max size */
};
//extern "C"
//extern "C"
epicsShareDef const enum dbr_value_class dbr_value_class[LAST_BUFFER_TYPE+1] = {
dbr_class_string, /* string max size */
dbr_class_int, /* short */

View File

@@ -4,19 +4,19 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* 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
@@ -27,7 +27,7 @@
#endif
#include <stdexcept>
#include <string> // vxWorks 6.0 requires this include
#include <string> // vxWorks 6.0 requires this include
#include <stdio.h>
#include "epicsExit.h"
@@ -67,11 +67,11 @@ cacService * ca_client_context::pDefaultService = 0;
epicsMutex * ca_client_context::pDefaultServiceInstallMutex;
ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
createdByThread ( epicsThreadGetIdSelf () ),
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
createdByThread ( epicsThreadGetIdSelf () ),
ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
pVPrintfFunc ( errlogVprintf ), fdRegFunc ( 0 ), fdRegArg ( 0 ),
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), callbackThreadsPending ( 0u ),
localPort ( 0 ), fdRegFuncNeedsToBeCalled ( false ),
pndRecvCnt ( 0u ), ioSeqNo ( 0u ), callbackThreadsPending ( 0u ),
localPort ( 0 ), fdRegFuncNeedsToBeCalled ( false ),
noWakeupSincePend ( true )
{
static const unsigned short PORT_ANY = 0u;
@@ -85,7 +85,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
if ( ca_client_context::pDefaultService ) {
this->pServiceContext.reset (
& ca_client_context::pDefaultService->contextCreate (
& ca_client_context::pDefaultService->contextCreate (
this->mutex, this->cbMutex, *this ) );
}
else {
@@ -125,7 +125,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
osiSockAddr addr;
memset ( (char *)&addr, 0 , sizeof ( addr ) );
addr.ia.sin_family = AF_INET;
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
addr.ia.sin_port = htons ( PORT_ANY );
int status = bind (this->sock, &addr.sa, sizeof (addr) );
if ( status < 0 ) {
@@ -139,7 +139,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
throwWithLocation ( noSocket () );
}
}
{
osiSockAddr tmpAddr;
osiSocklen_t saddr_length = sizeof ( tmpAddr );
@@ -159,9 +159,9 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
this->localPort = htons ( tmpAddr.ia.sin_port );
}
epics_auto_ptr < epicsGuard < epicsMutex > > pCBGuard;
epics_auto_ptr < CallbackGuard > pCBGuard;
if ( ! enablePreemptiveCallback ) {
pCBGuard.reset ( new epicsGuard < epicsMutex > ( this->cbMutex ) );
pCBGuard.reset ( new CallbackGuard ( this->cbMutex ) );
}
// multiple steps ensure exception safety
@@ -171,7 +171,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
ca_client_context::~ca_client_context ()
{
if ( this->fdRegFunc ) {
( *this->fdRegFunc )
( *this->fdRegFunc )
( this->fdRegArg, this->sock, false );
}
epicsSocketDestroy ( this->sock );
@@ -179,9 +179,9 @@ ca_client_context::~ca_client_context ()
osiSockRelease ();
// force a logical shutdown order
// so that the cac class does not hang its
// so that the cac class does not hang its
// receive threads during their shutdown sequence
// and so that classes using this classes mutex
// and so that classes using this classes mutex
// are destroyed before the mutex is destroyed
if ( this->pCallbackGuard.get() ) {
epicsGuardRelease < epicsMutex > unguard ( *this->pCallbackGuard );
@@ -192,7 +192,7 @@ ca_client_context::~ca_client_context ()
}
}
void ca_client_context::destroyGetCopy (
void ca_client_context::destroyGetCopy (
epicsGuard < epicsMutex > & guard, getCopy & gc )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -200,7 +200,7 @@ void ca_client_context::destroyGetCopy (
this->getCopyFreeList.release ( & gc );
}
void ca_client_context::destroyGetCallback (
void ca_client_context::destroyGetCallback (
epicsGuard < epicsMutex > & guard, getCallback & gcb )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -208,7 +208,7 @@ void ca_client_context::destroyGetCallback (
this->getCallbackFreeList.release ( & gcb );
}
void ca_client_context::destroyPutCallback (
void ca_client_context::destroyPutCallback (
epicsGuard < epicsMutex > & guard, putCallback & pcb )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -216,7 +216,7 @@ void ca_client_context::destroyPutCallback (
this->putCallbackFreeList.release ( & pcb );
}
void ca_client_context::destroySubscription (
void ca_client_context::destroySubscription (
epicsGuard < epicsMutex > & guard, oldSubscription & os )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -224,7 +224,7 @@ void ca_client_context::destroySubscription (
this->subscriptionFreeList.release ( & os );
}
void ca_client_context::changeExceptionEvent (
void ca_client_context::changeExceptionEvent (
caExceptionHandler * pfunc, void * arg )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -233,7 +233,7 @@ void ca_client_context::changeExceptionEvent (
// should block here until releated callback in progress completes
}
void ca_client_context::replaceErrLogHandler (
void ca_client_context::replaceErrLogHandler (
caPrintfFunc * ca_printf_func )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -246,7 +246,7 @@ void ca_client_context::replaceErrLogHandler (
// should block here until releated callback in progress completes
}
void ca_client_context::registerForFileDescriptorCallBack (
void ca_client_context::registerForFileDescriptorCallBack (
CAFDHANDLER *pFunc, void *pArg )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -261,22 +261,22 @@ void ca_client_context::registerForFileDescriptorCallBack (
// should block here until releated callback in progress completes
}
int ca_client_context :: printFormated (
int ca_client_context :: printFormated (
const char *pformat, ... ) const
{
va_list theArgs;
int status;
va_start ( theArgs, pformat );
status = this->ca_client_context :: varArgsPrintFormated ( pformat, theArgs );
va_end ( theArgs );
return status;
}
int ca_client_context :: varArgsPrintFormated (
int ca_client_context :: varArgsPrintFormated (
const char *pformat, va_list args ) const
{
caPrintfFunc * pFunc;
@@ -292,8 +292,8 @@ int ca_client_context :: varArgsPrintFormated (
}
}
void ca_client_context::exception (
epicsGuard < epicsMutex > & guard, int stat, const char * pCtx,
void ca_client_context::exception (
epicsGuard < epicsMutex > & guard, int stat, const char * pCtx,
const char * pFile, unsigned lineNo )
{
struct exception_handler_args args;
@@ -321,9 +321,9 @@ void ca_client_context::exception (
}
}
void ca_client_context::exception (
void ca_client_context::exception (
epicsGuard < epicsMutex > & guard, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op )
{
struct exception_handler_args args;
@@ -346,29 +346,29 @@ void ca_client_context::exception (
( *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 ) ),
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 );
}
}
}
void ca_client_context::signal ( int ca_status, const char * pfilenm,
void ca_client_context::signal ( int ca_status, const char * pfilenm,
int lineno, const char * pFormat, ... )
{
va_list theArgs;
va_start ( theArgs, pFormat );
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,
void ca_client_context :: vSignal (
int ca_status, const char *pfilenm,
int lineno, const char *pFormat, va_list args )
{
static const char *severity[] =
static const char *severity[] =
{
"Warning",
"Success",
@@ -379,11 +379,11 @@ void ca_client_context :: vSignal (
"Fatal",
"Fatal"
};
this->printFormated ( "CA.Client.Exception...............................................\n" );
this->printFormated ( " %s: \"%s\"\n",
severity[ CA_EXTRACT_SEVERITY ( ca_status ) ],
this->printFormated ( " %s: \"%s\"\n",
severity[ CA_EXTRACT_SEVERITY ( ca_status ) ],
ca_message ( ca_status ) );
if ( pFormat ) {
@@ -391,26 +391,26 @@ void ca_client_context :: vSignal (
this->varArgsPrintFormated ( pFormat, args );
this->printFormated ( "\"\n" );
}
if ( pfilenm ) {
this->printFormated ( " Source File: %s line %d\n",
pfilenm, lineno );
}
pfilenm, lineno );
}
epicsTime current = epicsTime::getCurrent ();
char date[64];
current.strftime ( date, sizeof ( date ), "%a %b %d %Y %H:%M:%S.%f");
this->printFormated ( " Current Time: %s\n", date );
/*
* Terminate execution if unsuccessful
*/
if( ! ( ca_status & CA_M_SUCCESS ) &&
if( ! ( ca_status & CA_M_SUCCESS ) &&
CA_EXTRACT_SEVERITY ( ca_status ) != CA_K_WARNING ){
errlogFlush ();
abort ();
}
this->printFormated ( "..................................................................\n" );
}
@@ -418,7 +418,7 @@ void ca_client_context::show ( unsigned level ) const
{
epicsGuard < epicsMutex > guard ( this->mutex );
::printf ( "ca_client_context at %p pndRecvCnt=%u ioSeqNo=%u\n",
::printf ( "ca_client_context at %p pndRecvCnt=%u ioSeqNo=%u\n",
static_cast <const void *> ( this ),
this->pndRecvCnt, this->ioSeqNo );
@@ -443,7 +443,7 @@ void ca_client_context::attachToClientCtx ()
epicsThreadPrivateSet ( caClientContextId, this );
}
void ca_client_context::incrementOutstandingIO (
void ca_client_context::incrementOutstandingIO (
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -453,7 +453,7 @@ void ca_client_context::incrementOutstandingIO (
}
}
void ca_client_context::decrementOutstandingIO (
void ca_client_context::decrementOutstandingIO (
epicsGuard < epicsMutex > & guard, unsigned ioSeqNoIn )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -466,16 +466,16 @@ void ca_client_context::decrementOutstandingIO (
}
}
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! is disabled. This prevents the preemptive callback lock from being released
// !!!! by other threads than the one that locked it.
//
int ca_client_context::pendIO ( const double & timeout )
{
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
@@ -487,7 +487,7 @@ int ca_client_context::pendIO ( const double & timeout )
epicsGuard < epicsMutex > guard ( this->mutex );
this->flush ( guard );
while ( this->pndRecvCnt > 0 ) {
if ( remaining < CAC_SIGNIFICANT_DELAY ) {
status = ECA_TIMEOUT;
@@ -514,16 +514,16 @@ int ca_client_context::pendIO ( const double & timeout )
return status;
}
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! is disabled. This prevents the preemptive callback lock from being released
// !!!! by other threads than the one that locked it.
//
int ca_client_context::pendEvent ( const double & timeout )
{
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
// prevent recursion nightmares by disabling calls to
// pendIO () from within a CA callback.
if ( epicsThreadPrivateGet ( caClientCallbackThreadId ) ) {
return ECA_EVDISALLOW;
}
@@ -541,17 +541,17 @@ int ca_client_context::pendEvent ( const double & timeout )
epicsGuard < epicsMutex > guard ( this->mutex );
//
// This is needed because in non-preemptive callback mode
// legacy applications that use file descriptor managers
// This is needed because in non-preemptive callback mode
// legacy applications that use file descriptor managers
// will register for ca receive thread activity and keep
// calling ca_pend_event until all of the socket data has
// been read. We must guarantee that other threads get a
// been read. We must guarantee that other threads get a
// chance to run if there is data in any of the sockets.
//
if ( this->fdRegFunc ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
// remove short udp message sent to wake
// remove short udp message sent to wake
// up a file descriptor manager
osiSockAddr tmpAddr;
osiSocklen_t addrSize = sizeof ( tmpAddr.sa );
@@ -592,7 +592,7 @@ int ca_client_context::pendEvent ( const double & timeout )
return ECA_TIMEOUT;
}
void ca_client_context::blockForEventAndEnableCallbacks (
void ca_client_context::blockForEventAndEnableCallbacks (
epicsEvent & event, const double & timeout )
{
if ( this->pCallbackGuard.get() ) {
@@ -659,12 +659,12 @@ void ca_client_context::callbackProcessingCompleteNotify ()
}
}
cacChannel & ca_client_context::createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannel & ca_client_context::createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannelNotify & chan, cacChannel::priLev pri )
{
guard.assertIdenticalMutex ( this->mutex );
return this->pServiceContext->createChannel (
return this->pServiceContext->createChannel (
guard, pChannelName, chan, pri );
}
@@ -685,21 +685,21 @@ unsigned ca_client_context::beaconAnomaliesSinceProgramStart () const
return this->pServiceContext->beaconAnomaliesSinceProgramStart ( guard );
}
void ca_client_context::installCASG (
void ca_client_context::installCASG (
epicsGuard < epicsMutex > & guard, CASG & sg )
{
guard.assertIdenticalMutex ( this->mutex );
this->sgTable.idAssignAdd ( sg );
}
void ca_client_context::uninstallCASG (
void ca_client_context::uninstallCASG (
epicsGuard < epicsMutex > & guard, CASG & sg )
{
guard.assertIdenticalMutex ( this->mutex );
this->sgTable.remove ( sg );
}
CASG * ca_client_context::lookupCASG (
CASG * ca_client_context::lookupCASG (
epicsGuard < epicsMutex > & guard, unsigned idIn )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -724,7 +724,7 @@ epicsMutex & ca_client_context::mutexRef () const
return this->mutex;
}
cacContext & ca_client_context::createNetworkContext (
cacContext & ca_client_context::createNetworkContext (
epicsMutex & mutexIn, epicsMutex & cbMutexIn )
{
return * new cac ( mutexIn, cbMutexIn, *this );
@@ -751,34 +751,54 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
{
oldChannelNotify & chan = pMon->channel ();
ca_client_context & cac = chan.getClientCtx ();
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
// if this stalls out on a live circuit then an exception
// can be forthcoming which we must ignore as the clear
// request must always be successful
chan.eliminateExcessiveSendBacklog ( guard );
// !!!! the order in which we take the mutex here prevents deadlocks
{
epicsGuard < epicsMutex > guard ( cac.mutex );
try {
// if this stalls out on a live circuit then an exception
// can be forthcoming which we must ignore as the clear
// request must always be successful
chan.eliminateExcessiveSendBacklog ( guard );
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
}
}
catch ( cacChannel::notConnected & ) {
// intentionally ignored
if ( cac.pCallbackGuard.get() &&
cac.createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( cac.mutex );
pMon->cancel ( *cac.pCallbackGuard.get(), guard );
}
else {
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( cac.cbMutex );
epicsGuard < epicsMutex > guard ( cac.mutex );
pMon->cancel ( cbGuard, guard );
}
pMon->cancel ( guard );
return ECA_NORMAL;
}
void ca_client_context :: eliminateExcessiveSendBacklog (
void ca_client_context :: eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & guard, cacChannel & chan )
{
if ( chan.requestMessageBytesPending ( guard ) >
if ( chan.requestMessageBytesPending ( guard ) >
ca_client_context :: flushBlockThreshold ) {
if ( this->pCallbackGuard.get() &&
if ( this->pCallbackGuard.get() &&
this->createdByThread == epicsThreadGetIdSelf () ) {
// we need to be very careful about lock hierarchy
// we need to be very careful about lock hierarchy
// inversion in this situation
epicsGuardRelease < epicsMutex > unguard ( guard );
{
epicsGuardRelease < epicsMutex > cbunguard (
* this->pCallbackGuard.get() );
{
{
epicsGuard < epicsMutex > nestedGuard ( this->mutex );
chan.flush ( nestedGuard );
}

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -22,7 +22,7 @@
#include <new>
#include <stdexcept>
#include <string> // vxWorks 6.0 requires this include
#include <string> // vxWorks 6.0 requires this include
#include "dbDefs.h"
#include "epicsGuard.h"
@@ -50,12 +50,12 @@
#include "autoPtrFreeList.h"
#include "noopiiu.h"
static const char pVersionCAC[] =
"@(#) " EPICS_VERSION_STRING
static const char pVersionCAC[] =
"@(#) " EPICS_VERSION_STRING
", CA Client Library " __DATE__;
// TCP response dispatch table
const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
{
&cac::versionAction,
&cac::eventRespAction,
@@ -68,7 +68,7 @@ const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
&cac::badTCPRespAction,
&cac::badTCPRespAction,
// legacy CA_PROTO_READ_SYNC used as an echo with legacy server
&cac::echoRespAction,
&cac::echoRespAction,
&cac::exceptionRespAction,
&cac::clearChannelRespAction,
&cac::badTCPRespAction,
@@ -89,7 +89,7 @@ const cac::pProtoStubTCP cac::tcpJumpTableCAC [] =
};
// TCP exception dispatch table
const cac::pExcepProtoStubTCP cac::tcpExcepJumpTableCAC [] =
const cac::pExcepProtoStubTCP cac::tcpExcepJumpTableCAC [] =
{
&cac::defaultExcep, // CA_PROTO_VERSION
&cac::eventAddExcep, // CA_PROTO_EVENT_ADD
@@ -109,7 +109,7 @@ const cac::pExcepProtoStubTCP cac::tcpExcepJumpTableCAC [] =
&cac::readNotifyExcep, // CA_PROTO_READ_NOTIFY
&cac::defaultExcep, // CA_PROTO_READ_BUILD
&cac::defaultExcep, // REPEATER_CONFIRM
&cac::defaultExcep, // CA_PROTO_CREATE_CHAN
&cac::defaultExcep, // CA_PROTO_CREATE_CHAN
&cac::writeNotifyExcep, // CA_PROTO_WRITE_NOTIFY
&cac::defaultExcep, // CA_PROTO_CLIENT_NAME
&cac::defaultExcep, // CA_PROTO_HOST_NAME
@@ -124,9 +124,9 @@ const cac::pExcepProtoStubTCP cac::tcpExcepJumpTableCAC [] =
//
// cac::cac ()
//
cac::cac (
epicsMutex & mutualExclusionIn,
epicsMutex & callbackControlIn,
cac::cac (
epicsMutex & mutualExclusionIn,
epicsMutex & callbackControlIn,
cacContextNotify & notifyIn ) :
_refLocalHostName ( localHostNameCache.getReference () ),
programBeginTime ( epicsTime::getCurrent() ),
@@ -134,7 +134,7 @@ cac::cac (
mutex ( mutualExclusionIn ),
cbMutex ( callbackControlIn ),
ipToAEngine ( ipAddrToAsciiEngine::allocate () ),
timerQueue ( epicsTimerQueueActive::allocate ( false,
timerQueue ( epicsTimerQueueActive::allocate ( false,
lowestPriorityLevelAbove(epicsThreadGetPrioritySelf()) ) ),
pUserName ( 0 ),
pudpiiu ( 0 ),
@@ -157,8 +157,8 @@ cac::cac (
long status;
/*
* Certain os, such as HPUX, do not unblock a socket system call
* when another thread asynchronously calls both shutdown() and
* Certain os, such as HPUX, do not unblock a socket system call
* when another thread asynchronously calls both shutdown() and
* close(). To solve this problem we need to employ OS specific
* mechanisms.
*/
@@ -179,7 +179,7 @@ cac::cac (
strncpy ( this->pUserName, tmp, len );
}
this->_serverPort =
this->_serverPort =
envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT,
static_cast <unsigned short> (CA_SERVER_PORT) );
@@ -224,7 +224,7 @@ cac::cac (
}
unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes ();
if ( bufsPerArray > 1u ) {
maxContigFrames = bufsPerArray *
maxContigFrames = bufsPerArray *
contiguousMsgCountWhichTriggersFlowControl;
}
}
@@ -275,8 +275,8 @@ cac::~cac ()
// this blocks until the UDP thread exits so that
// it will not sneak in any new clients
//
// lock intentionally not held here so that we dont deadlock
// waiting for the UDP thread to exit while it is waiting to
// lock intentionally not held here so that we dont deadlock
// waiting for the UDP thread to exit while it is waiting to
// get the lock.
{
epicsGuard < epicsMutex > cbGuard ( this->cbMutex );
@@ -298,11 +298,11 @@ cac::~cac ()
}
}
}
//
// wait for all tcp threads to exit
//
// this will block for oustanding sends to go out so dont
// this will block for oustanding sends to go out so dont
// hold a lock while waiting
//
{
@@ -323,7 +323,7 @@ cac::~cac ()
delete [] this->pUserName;
tsSLList < bhe > tmpBeaconList;
this->beaconTable.removeAll ( tmpBeaconList );
this->beaconTable.removeAll ( tmpBeaconList );
while ( bhe * pBHE = tmpBeaconList.get() ) {
pBHE->~bhe ();
this->bheFreeList.release ( pBHE );
@@ -338,7 +338,7 @@ cac::~cac ()
osiSockRelease ();
// its ok for channels and subscriptions to still
// exist at this point. The user created them and
// exist at this point. The user created them and
// its his responsibility to clean them up.
}
@@ -346,7 +346,7 @@ unsigned cac::lowestPriorityLevelAbove ( unsigned priority )
{
unsigned abovePriority;
epicsThreadBooleanStatus tbs;
tbs = epicsThreadLowestPriorityLevelAbove (
tbs = epicsThreadLowestPriorityLevelAbove (
priority, & abovePriority );
if ( tbs != epicsThreadBooleanStatusSuccess ) {
abovePriority = priority;
@@ -358,7 +358,7 @@ unsigned cac::highestPriorityLevelBelow ( unsigned priority )
{
unsigned belowPriority;
epicsThreadBooleanStatus tbs;
tbs = epicsThreadHighestPriorityLevelBelow (
tbs = epicsThreadHighestPriorityLevelBelow (
priority, & belowPriority );
if ( tbs != epicsThreadBooleanStatusSuccess ) {
belowPriority = priority;
@@ -379,21 +379,21 @@ void cac::flush ( epicsGuard < epicsMutex > & guard )
}
}
unsigned cac::circuitCount (
unsigned cac::circuitCount (
epicsGuard < epicsMutex > & guard ) const
{
guard.assertIdenticalMutex ( this->mutex );
return this->circuitList.count ();
}
void cac::show (
void cac::show (
epicsGuard < epicsMutex > & guard, unsigned level ) const
{
guard.assertIdenticalMutex ( this->mutex );
::printf ( "Channel Access Client Context at %p for user %s\n",
::printf ( "Channel Access Client Context at %p for user %s\n",
static_cast <const void *> ( this ), this->pUserName );
// this also supresses the "defined, but not used"
// this also supresses the "defined, but not used"
// warning message
::printf ( "\trevision \"%s\"\n", pVersionCAC );
@@ -451,7 +451,7 @@ void cac::beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime,
/*
* return if the beacon period has not changed significantly
*/
if ( ! pBHE->updatePeriod ( guard, this->programBeginTime,
if ( ! pBHE->updatePeriod ( guard, this->programBeginTime,
currentTime, beaconNumber, protocolRevision ) ) {
return;
}
@@ -488,8 +488,8 @@ void cac::beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime,
# endif
}
cacChannel & cac::createChannel (
epicsGuard < epicsMutex > & guard, const char * pName,
cacChannel & cac::createChannel (
epicsGuard < epicsMutex > & guard, const char * pName,
cacChannelNotify & chan, cacChannel::priLev pri )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -503,19 +503,19 @@ cacChannel & cac::createChannel (
}
if ( ! this->pudpiiu ) {
this->pudpiiu = new udpiiu (
guard, this->timerQueue, this->cbMutex,
this->pudpiiu = new udpiiu (
guard, this->timerQueue, this->cbMutex,
this->mutex, this->notify, *this, this->_serverPort,
this->searchDestList );
}
nciu * pNetChan = new ( this->channelFreeList )
nciu * pNetChan = new ( this->channelFreeList )
nciu ( *this, noopIIU, chan, pName, pri );
this->chanTable.idAssignAdd ( *pNetChan );
return *pNetChan;
}
bool cac::findOrCreateVirtCircuit (
bool cac::findOrCreateVirtCircuit (
epicsGuard < epicsMutex > & guard, const osiSockAddr & addr,
unsigned priority, tcpiiu *& piiu, unsigned minorVersionNumber,
SearchDestTCP * pSearchDest )
@@ -532,14 +532,14 @@ bool cac::findOrCreateVirtCircuit (
try {
autoPtrFreeList < tcpiiu, 32, epicsMutexNOOP > pnewiiu (
this->freeListVirtualCircuit,
new ( this->freeListVirtualCircuit ) tcpiiu (
*this, this->mutex, this->cbMutex, this->notify, this->connTMO,
this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
new ( this->freeListVirtualCircuit ) tcpiiu (
*this, this->mutex, this->cbMutex, this->notify, this->connTMO,
this->timerQueue, addr, this->comBufMemMgr, minorVersionNumber,
this->ipToAEngine, priority, pSearchDest ) );
bhe * pBHE = this->beaconTable.lookup ( addr.ia );
if ( ! pBHE ) {
pBHE = new ( this->bheFreeList )
pBHE = new ( this->bheFreeList )
bhe ( this->mutex, epicsTime (), 0u, addr.ia );
if ( this->beaconTable.add ( *pBHE ) < 0 ) {
return newIIU;
@@ -553,13 +553,13 @@ bool cac::findOrCreateVirtCircuit (
newIIU = true;
}
catch ( std :: exception & except ) {
errlogPrintf (
errlogPrintf (
"CAC: exception during virtual circuit creation \"%s\"\n",
except.what () );
return newIIU;
}
catch ( ... ) {
errlogPrintf (
errlogPrintf (
"CAC: Nonstandard exception during virtual circuit creation\n" );
return newIIU;
}
@@ -567,9 +567,9 @@ bool cac::findOrCreateVirtCircuit (
return newIIU;
}
void cac::transferChanToVirtCircuit (
void cac::transferChanToVirtCircuit (
unsigned cid, unsigned sid,
ca_uint16_t typeCode, arrayElementCount count,
ca_uint16_t typeCode, arrayElementCount count,
unsigned minorVersionNumber, const osiSockAddr & addr,
const epicsTime & currentTime )
{
@@ -604,12 +604,12 @@ void cac::transferChanToVirtCircuit (
char acc[64];
pChan->getPIIU(guard)->getHostName ( guard, acc, sizeof ( acc ) );
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
msgForMultiplyDefinedPV ( this->ipToAEngine,
msgForMultiplyDefinedPV ( this->ipToAEngine,
*this, pChan->pName ( guard ), acc );
// It is possible for the ioInitiate call below to
// call the callback directly if queue quota is exceeded.
// This callback takes the callback lock and therefore we
// must release the primary mutex here to avoid a lock
// must release the primary mutex here to avoid a lock
// hierarchy inversion.
epicsGuardRelease < epicsMutex > unguard ( guard );
pMsg->ioInitiate ( addr );
@@ -625,9 +625,9 @@ void cac::transferChanToVirtCircuit (
pChan->getPriority(guard), piiu, minorVersionNumber );
// must occur before moving to new iiu
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
guard, *pChan, currentTime );
piiu->installChannel (
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( newIIU ) {
@@ -635,14 +635,14 @@ void cac::transferChanToVirtCircuit (
}
}
void cac::destroyChannel (
void cac::destroyChannel (
epicsGuard < epicsMutex > & guard,
nciu & chan )
nciu & chan )
{
guard.assertIdenticalMutex ( this->mutex );
// uninstall channel so that recv threads
// will not start a new callback for this channel's IO.
// will not start a new callback for this channel's IO.
if ( this->chanTable.remove ( chan ) != & chan ) {
throw std::logic_error ( "Invalid channel identifier" );
}
@@ -650,9 +650,9 @@ void cac::destroyChannel (
this->channelFreeList.release ( & chan );
}
void cac::disconnectAllIO (
void cac::disconnectAllIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
epicsGuard < epicsMutex > & guard,
nciu & chan, tsDLList < baseNMIU > & ioList )
{
cbGuard.assertIdenticalMutex ( this->cbMutex );
@@ -672,8 +672,8 @@ void cac::disconnectAllIO (
}
}
int cac :: printFormated (
epicsGuard < epicsMutex > & callbackControl,
int cac :: printFormated (
epicsGuard < epicsMutex > & callbackControl,
const char * pformat, ... ) const
{
va_list theArgs;
@@ -683,26 +683,26 @@ int cac :: printFormated (
return status;
}
netWriteNotifyIO & cac::writeNotifyRequest (
netWriteNotifyIO & cac::writeNotifyRequest (
epicsGuard < epicsMutex > & guard, nciu & chan, privateInterfaceForIO & icni,
unsigned type, arrayElementCount nElem, const void * pValue, cacWriteNotify & notifyIn )
{
guard.assertIdenticalMutex ( this->mutex );
autoPtrRecycle < netWriteNotifyIO > pIO (
guard, this->ioTable, *this,
autoPtrRecycle < netWriteNotifyIO > pIO (
guard, this->ioTable, *this,
netWriteNotifyIO::factory ( this->freeListWriteNotifyIO, icni, notifyIn ) );
this->ioTable.idAssignAdd ( *pIO );
chan.getPIIU(guard)->writeNotifyRequest (
chan.getPIIU(guard)->writeNotifyRequest (
guard, chan, *pIO, type, nElem, pValue );
return *pIO.release();
}
netReadNotifyIO & cac::readNotifyRequest (
netReadNotifyIO & cac::readNotifyRequest (
epicsGuard < epicsMutex > & guard, nciu & chan, privateInterfaceForIO & icni,
unsigned type, arrayElementCount nElem, cacReadNotify & notifyIn )
{
guard.assertIdenticalMutex ( this->mutex );
autoPtrRecycle < netReadNotifyIO > pIO (
autoPtrRecycle < netReadNotifyIO > pIO (
guard, this->ioTable, *this,
netReadNotifyIO::factory ( this->freeListReadNotifyIO, icni, notifyIn ) );
this->ioTable.idAssignAdd ( *pIO );
@@ -711,7 +711,8 @@ netReadNotifyIO & cac::readNotifyRequest (
}
bool cac::destroyIO (
epicsGuard < epicsMutex > & guard,
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn, nciu & chan )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -720,18 +721,18 @@ bool cac::destroyIO (
if ( pIO ) {
class netSubscription * pSubscr = pIO->isSubscription ();
if ( pSubscr ) {
pSubscr->unsubscribeIfRequired ( guard, chan );
pSubscr->unsubscribeIfRequired ( guard, chan );
}
// this uninstalls from the list and destroys the IO
pIO->exception ( guard, *this,
ECA_CHANDESTROY, chan.pName ( guard ) );
return true;
}
}
return false;
}
void cac::ioShow (
void cac::ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn, unsigned level ) const
{
@@ -741,8 +742,8 @@ void cac::ioShow (
}
}
void cac::ioExceptionNotify (
unsigned idIn, int status, const char * pContext,
void cac::ioExceptionNotify (
unsigned idIn, int status, const char * pContext,
unsigned type, arrayElementCount count )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -752,8 +753,8 @@ void cac::ioExceptionNotify (
}
}
void cac::ioExceptionNotifyAndUninstall (
unsigned idIn, int status, const char * pContext,
void cac::ioExceptionNotifyAndUninstall (
unsigned idIn, int status, const char * pContext,
unsigned type, arrayElementCount count )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -763,38 +764,38 @@ void cac::ioExceptionNotifyAndUninstall (
}
}
void cac::recycleReadNotifyIO (
void cac::recycleReadNotifyIO (
epicsGuard < epicsMutex > & guard, netReadNotifyIO & io )
{
guard.assertIdenticalMutex ( this->mutex );
this->freeListReadNotifyIO.release ( & io );
}
void cac::recycleWriteNotifyIO (
void cac::recycleWriteNotifyIO (
epicsGuard < epicsMutex > & guard, netWriteNotifyIO & io )
{
guard.assertIdenticalMutex ( this->mutex );
this->freeListWriteNotifyIO.release ( & io );
}
void cac::recycleSubscription (
void cac::recycleSubscription (
epicsGuard < epicsMutex > & guard, netSubscription & io )
{
guard.assertIdenticalMutex ( this->mutex );
this->freeListSubscription.release ( & io );
}
netSubscription & cac::subscriptionRequest (
epicsGuard < epicsMutex > & guard,
netSubscription & cac::subscriptionRequest (
epicsGuard < epicsMutex > & guard,
nciu & chan, privateInterfaceForIO & privChan,
unsigned type,
arrayElementCount nElem, unsigned mask,
arrayElementCount nElem, unsigned mask,
cacStateNotify & notifyIn,
bool chanIsInstalled )
{
guard.assertIdenticalMutex ( this->mutex );
autoPtrRecycle < netSubscription > pIO (
guard, this->ioTable, *this,
autoPtrRecycle < netSubscription > pIO (
guard, this->ioTable, *this,
netSubscription::factory ( this->freeListSubscription,
privChan, type, nElem, mask, notifyIn ) );
this->ioTable.idAssignAdd ( *pIO );
@@ -804,23 +805,23 @@ netSubscription & cac::subscriptionRequest (
return *pIO.release ();
}
bool cac::versionAction ( callbackManager &, tcpiiu & iiu,
bool cac::versionAction ( callbackManager &, tcpiiu & iiu,
const epicsTime &, const caHdrLargeArray & msg, void * )
{
iiu.versionRespNotify ( msg );
return true;
}
bool cac::echoRespAction (
callbackManager & mgr, tcpiiu & iiu,
bool cac::echoRespAction (
callbackManager & mgr, tcpiiu & iiu,
const epicsTime & /* current */, const caHdrLargeArray &, void * )
{
iiu.probeResponseNotify ( mgr.cbGuard );
return true;
}
bool cac::writeNotifyRespAction (
callbackManager &, tcpiiu &,
bool cac::writeNotifyRespAction (
callbackManager &, tcpiiu &,
const epicsTime &, const caHdrLargeArray & hdr, void * )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -837,7 +838,7 @@ bool cac::writeNotifyRespAction (
return true;
}
bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -856,13 +857,13 @@ bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
baseNMIU * pmiu = this->ioTable.remove ( hdr.m_available );
//
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// no need to worry here about the baseNMIU being deleted while
// it is in use here.
//
if ( pmiu ) {
// if its a circuit-becomes-responsive subscription update
// if its a circuit-becomes-responsive subscription update
// then we need to reinstall the IO into the table
netSubscription * pSubscr = pmiu->isSubscription ();
if ( pSubscr ) {
@@ -874,7 +875,7 @@ bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
* convert the data buffer from net
* format to host format
*/
caStatus = caNetConvert (
caStatus = caNetConvert (
hdr.m_dataType, pMsgBdy, pMsgBdy, false, hdr.m_count );
}
if ( caStatus == ECA_NORMAL ) {
@@ -882,7 +883,7 @@ bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
hdr.m_dataType, hdr.m_count, pMsgBdy );
}
else {
pmiu->exception ( guard, *this,
pmiu->exception ( guard, *this,
caStatus, "read failed",
hdr.m_dataType, hdr.m_count );
}
@@ -890,8 +891,8 @@ bool cac::readNotifyRespAction ( callbackManager &, tcpiiu & iiu,
return true;
}
bool cac::searchRespAction ( callbackManager &, tcpiiu & iiu,
const epicsTime & currentTime, const caHdrLargeArray & msg,
bool cac::searchRespAction ( callbackManager &, tcpiiu & iiu,
const epicsTime & currentTime, const caHdrLargeArray & msg,
void * /* pMsgBdy */ )
{
assert ( this->pudpiiu );
@@ -899,13 +900,13 @@ bool cac::searchRespAction ( callbackManager &, tcpiiu & iiu,
return true;
}
bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
{
{
int caStatus;
/*
* m_postsize = 0 used to be a subscription cancel confirmation,
* m_postsize = 0 used to be a subscription cancel confirmation,
* but is now a noop because the IO block is immediately deleted
*/
if ( ! hdr.m_postsize ) {
@@ -926,8 +927,8 @@ bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
}
//
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// no need to worry here about the baseNMIU being deleted while
// it is in use here.
//
@@ -937,7 +938,7 @@ bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
* convert the data buffer from net format to host format
*/
if ( caStatus == ECA_NORMAL ) {
caStatus = caNetConvert (
caStatus = caNetConvert (
hdr.m_dataType, pMsgBdy, pMsgBdy, false, hdr.m_count );
}
if ( caStatus == ECA_NORMAL ) {
@@ -945,7 +946,7 @@ bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
hdr.m_dataType, hdr.m_count, pMsgBdy );
}
else {
pmiu->exception ( guard, *this, caStatus,
pmiu->exception ( guard, *this, caStatus,
"subscription update read failed",
hdr.m_dataType, hdr.m_count );
}
@@ -953,14 +954,14 @@ bool cac::eventRespAction ( callbackManager &, tcpiiu &iiu,
return true;
}
bool cac::readRespAction ( callbackManager &, tcpiiu &,
bool cac::readRespAction ( callbackManager &, tcpiiu &,
const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
{
epicsGuard < epicsMutex > guard ( this->mutex );
baseNMIU * pmiu = this->ioTable.remove ( hdr.m_available );
//
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// The IO destroy routines take the call back mutex
// when uninstalling and deleting the baseNMIU so there is
// no need to worry here about the baseNMIU being deleted while
// it is in use here.
//
@@ -971,14 +972,14 @@ bool cac::readRespAction ( callbackManager &, tcpiiu &,
return true;
}
bool cac::clearChannelRespAction ( callbackManager &, tcpiiu &,
bool cac::clearChannelRespAction ( callbackManager &, tcpiiu &,
const epicsTime &, const caHdrLargeArray &, void * /* pMsgBody */ )
{
return true; // currently a noop
}
bool cac::defaultExcep (
callbackManager &, tcpiiu & iiu,
bool cac::defaultExcep (
callbackManager &, tcpiiu & iiu,
const caHdrLargeArray &, const char * pCtx, unsigned status )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -990,69 +991,69 @@ bool cac::defaultExcep (
return true;
}
void cac::exception (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, int status,
void cac::exception (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, int status,
const char * pContext, const char * pFileName, unsigned lineNo )
{
cbGuard.assertIdenticalMutex ( this->cbMutex );
guard.assertIdenticalMutex ( this->mutex );
this->notify.exception ( guard, status, pContext,
this->notify.exception ( guard, status, pContext,
pFileName, lineNo );
}
bool cac::eventAddExcep (
callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
bool cac::eventAddExcep (
callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
const char *pCtx, unsigned status )
{
this->ioExceptionNotify ( hdr.m_available, status, pCtx,
this->ioExceptionNotify ( hdr.m_available, status, pCtx,
hdr.m_dataType, hdr.m_count );
return true;
}
bool cac::readExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray & hdr,
bool cac::readExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray & hdr,
const char * pCtx, unsigned status )
{
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
status, pCtx, hdr.m_dataType, hdr.m_count );
return true;
}
bool cac::writeExcep (
bool cac::writeExcep (
callbackManager & mgr,
tcpiiu &, const caHdrLargeArray & hdr,
tcpiiu &, const caHdrLargeArray & hdr,
const char * pCtx, unsigned status )
{
epicsGuard < epicsMutex > guard ( this->mutex );
nciu * pChan = this->chanTable.lookup ( hdr.m_available );
if ( pChan ) {
pChan->writeException ( mgr.cbGuard, guard, status, pCtx,
pChan->writeException ( mgr.cbGuard, guard, status, pCtx,
hdr.m_dataType, hdr.m_count );
}
return true;
}
bool cac::readNotifyExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
bool cac::readNotifyExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
const char *pCtx, unsigned status )
{
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
status, pCtx, hdr.m_dataType, hdr.m_count );
return true;
}
bool cac::writeNotifyExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
bool cac::writeNotifyExcep ( callbackManager &, tcpiiu &,
const caHdrLargeArray &hdr,
const char *pCtx, unsigned status )
{
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
this->ioExceptionNotifyAndUninstall ( hdr.m_available,
status, pCtx, hdr.m_dataType, hdr.m_count );
return true;
}
bool cac::exceptionRespAction ( callbackManager & cbMutexIn, tcpiiu & iiu,
bool cac::exceptionRespAction ( callbackManager & cbMutexIn, tcpiiu & iiu,
const epicsTime &, const caHdrLargeArray & hdr, void * pMsgBdy )
{
const caHdr * pReq = reinterpret_cast < const caHdr * > ( pMsgBdy );
@@ -1069,7 +1070,7 @@ bool cac::exceptionRespAction ( callbackManager & cbMutexIn, tcpiiu & iiu,
req.m_available = AlignedWireRef < const epicsUInt32 > ( pReq->m_available );
const ca_uint32_t * pLW = reinterpret_cast < const ca_uint32_t * > ( pReq + 1 );
if ( req.m_postsize == 0xffff ) {
static const unsigned annexSize =
static const unsigned annexSize =
sizeof ( req.m_postsize ) + sizeof ( req.m_count );
bytesSoFar += annexSize;
if ( hdr.m_postsize < bytesSoFar ) {
@@ -1100,9 +1101,9 @@ bool cac::accessRightsRespAction (
nciu * pChan = this->chanTable.lookup ( hdr.m_cid );
if ( pChan ) {
unsigned ar = hdr.m_available;
caAccessRights accessRights (
( ar & CA_PROTO_ACCESS_RIGHT_READ ) ? true : false,
( ar & CA_PROTO_ACCESS_RIGHT_WRITE ) ? true : false);
caAccessRights accessRights (
( ar & CA_PROTO_ACCESS_RIGHT_READ ) ? true : false,
( ar & CA_PROTO_ACCESS_RIGHT_WRITE ) ? true : false);
pChan->accessRightsStateChange ( accessRights, mgr.cbGuard, guard );
}
@@ -1125,11 +1126,11 @@ bool cac::createChannelRespAction (
}
bool wasExpected = iiu.connectNotify ( guard, *pChan );
if ( wasExpected ) {
pChan->connect ( hdr.m_dataType, hdr.m_count, sidTmp,
pChan->connect ( hdr.m_dataType, hdr.m_count, sidTmp,
mgr.cbGuard, guard );
}
else {
errlogPrintf (
errlogPrintf (
"CA Client Library: Ignored duplicate create channel "
"response from CA server?\n" );
}
@@ -1140,10 +1141,10 @@ bool cac::createChannelRespAction (
iiu.clearChannelRequest ( guard, hdr.m_available, hdr.m_cid );
}
return true;
return true;
}
bool cac::verifyAndDisconnectChan (
bool cac::verifyAndDisconnectChan (
callbackManager & mgr, tcpiiu &,
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
{
@@ -1168,18 +1169,18 @@ void cac::disconnectChannel (
chan.unresponsiveCircuitNotify ( cbGuard, guard );
}
bool cac::badTCPRespAction ( callbackManager &, tcpiiu & iiu,
bool cac::badTCPRespAction ( callbackManager &, tcpiiu & iiu,
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
{
epicsGuard < epicsMutex > guard ( this->mutex );
char hostName[64];
iiu.getHostName ( guard, hostName, sizeof ( hostName ) );
errlogPrintf ( "CAC: Undecipherable TCP message ( bad response type %u ) from %s\n",
errlogPrintf ( "CAC: Undecipherable TCP message ( bad response type %u ) from %s\n",
hdr.m_cmmd, hostName );
return false;
}
bool cac::executeResponse ( callbackManager & mgr, tcpiiu & iiu,
bool cac::executeResponse ( callbackManager & mgr, tcpiiu & iiu,
const epicsTime & currentTime, caHdrLargeArray & hdr, char * pMshBody )
{
// execute the response message
@@ -1193,7 +1194,7 @@ bool cac::executeResponse ( callbackManager & mgr, tcpiiu & iiu,
return ( this->*pStub ) ( mgr, iiu, currentTime, hdr, pMshBody );
}
void cac::selfTest (
void cac::selfTest (
epicsGuard < epicsMutex > & guard ) const
{
guard.assertIdenticalMutex ( this->mutex );
@@ -1221,7 +1222,7 @@ void cac::destroyIIU ( tcpiiu & iiu )
pBHE->unregisterIIU ( guard, iiu );
}
}
assert ( this->pudpiiu );
iiu.disconnectAllChannels ( mgr.cbGuard, guard, *this->pudpiiu );
@@ -1233,7 +1234,7 @@ void cac::destroyIIU ( tcpiiu & iiu )
// so we must not hold the primary mutex here
//
// this waits for send/recv threads to exit
// this also uses the cac free lists so cac must wait
// this also uses the cac free lists so cac must wait
// for this to finish before it shuts down
iiu.~tcpiiu ();
@@ -1248,8 +1249,8 @@ void cac::destroyIIU ( tcpiiu & iiu )
// do not touch "this" after lock is released above
}
double cac::beaconPeriod (
epicsGuard < epicsMutex > & guard,
double cac::beaconPeriod (
epicsGuard < epicsMutex > & guard,
const nciu & chan ) const
{
const netiiu * pIIU = chan.getConstPIIU ( guard );
@@ -1266,8 +1267,8 @@ double cac::beaconPeriod (
return - DBL_MAX;
}
void cac::initiateConnect (
epicsGuard < epicsMutex > & guard,
void cac::initiateConnect (
epicsGuard < epicsMutex > & guard,
nciu & chan, netiiu * & piiu )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -1285,7 +1286,7 @@ void cacComBufMemoryManager::release ( void * pCadaver )
this->freeList.release ( pCadaver );
}
void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
const char * pChannelName, const char * pAcc, const char * pRej )
{
char buf[256];

View File

@@ -4,7 +4,7 @@
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -57,11 +57,11 @@ class netSubscription;
// is applied
class cacRecycle {
public:
virtual void recycleReadNotifyIO (
virtual void recycleReadNotifyIO (
epicsGuard < epicsMutex > &, netReadNotifyIO &io ) = 0;
virtual void recycleWriteNotifyIO (
virtual void recycleWriteNotifyIO (
epicsGuard < epicsMutex > &, netWriteNotifyIO &io ) = 0;
virtual void recycleSubscription (
virtual void recycleSubscription (
epicsGuard < epicsMutex > &, netSubscription &io ) = 0;
protected:
virtual ~cacRecycle() {}
@@ -96,85 +96,81 @@ private:
class callbackManager : public notifyGuard {
public:
callbackManager (
cacContextNotify &,
callbackManager (
cacContextNotify &,
epicsMutex & callbackControl );
epicsGuard < epicsMutex > cbGuard;
};
class cac :
class cac :
public cacContext,
private cacRecycle,
private cacRecycle,
private callbackForMultiplyDefinedPV
{
public:
cac (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
cac (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
cacContextNotify & );
virtual ~cac ();
// beacon management
void beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime,
void beaconNotify ( const inetAddrID & addr, const epicsTime & currentTime,
ca_uint32_t beaconNumber, unsigned protocolRevision );
unsigned beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & ) const;
// IO management
void flush ( epicsGuard < epicsMutex > & guard );
bool executeResponse ( callbackManager &, tcpiiu &,
bool executeResponse ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, caHdrLargeArray &, char *pMsgBody );
// channel routines
void transferChanToVirtCircuit (
unsigned cid, unsigned sid,
ca_uint16_t typeCode, arrayElementCount count,
void transferChanToVirtCircuit (
unsigned cid, unsigned sid,
ca_uint16_t typeCode, arrayElementCount count,
unsigned minorVersionNumber, const osiSockAddr &,
const epicsTime & currentTime );
cacChannel & createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannel & createChannel (
epicsGuard < epicsMutex > & guard, const char * pChannelName,
cacChannelNotify &, cacChannel::priLev );
void destroyChannel (
void destroyChannel (
epicsGuard < epicsMutex > &, nciu & );
void initiateConnect (
void initiateConnect (
epicsGuard < epicsMutex > &, nciu &, netiiu * & );
nciu * lookupChannel (
epicsGuard < epicsMutex > &, const cacChannel::ioid & );
// IO requests
netWriteNotifyIO & writeNotifyRequest (
netWriteNotifyIO & writeNotifyRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem, const void * pValue,
unsigned type, arrayElementCount nElem, const void * pValue,
cacWriteNotify & );
netReadNotifyIO & readNotifyRequest (
netReadNotifyIO & readNotifyRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem,
unsigned type, arrayElementCount nElem,
cacReadNotify & );
netSubscription & subscriptionRequest (
netSubscription & subscriptionRequest (
epicsGuard < epicsMutex > &, nciu &, privateInterfaceForIO &,
unsigned type, arrayElementCount nElem, unsigned mask,
unsigned type, arrayElementCount nElem, unsigned mask,
cacStateNotify &, bool channelIsInstalled );
bool destroyIO (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn,
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const cacChannel::ioid & idIn,
nciu & chan );
void disconnectAllIO (
void disconnectAllIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
epicsGuard < epicsMutex > & guard,
nciu &, tsDLList < baseNMIU > & ioList );
void ioShow (
void ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid &id, unsigned level ) const;
// sync group routines
CASG * lookupCASG ( epicsGuard < epicsMutex > &, unsigned id );
void installCASG ( epicsGuard < epicsMutex > &, CASG & );
void uninstallCASG ( epicsGuard < epicsMutex > &, CASG & );
// exception generation
void exception (
epicsGuard < epicsMutex > & cbGuard,
void exception (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
const char * pFileName, unsigned lineNo );
@@ -189,11 +185,11 @@ public:
// diagnostics
unsigned circuitCount ( epicsGuard < epicsMutex > & ) const;
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
int printFormated (
epicsGuard < epicsMutex > & callbackControl,
int printFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, ... ) const;
int varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
int varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, va_list args ) const;
double connectionTimeout ( epicsGuard < epicsMutex > & );
@@ -210,17 +206,17 @@ public:
unsigned getInitializingThreadsPriority () const;
epicsMutex & mutexRef ();
void attachToClientCtx ();
void selfTest (
void selfTest (
epicsGuard < epicsMutex > & ) const;
double beaconPeriod (
double beaconPeriod (
epicsGuard < epicsMutex > &,
const nciu & chan ) const;
static unsigned lowestPriorityLevelAbove ( unsigned priority );
static unsigned highestPriorityLevelBelow ( unsigned priority );
void destroyIIU ( tcpiiu & iiu );
void destroyIIU ( tcpiiu & iiu );
const char * pLocalHostName ();
private:
epicsSingleton < localHostName > :: reference _refLocalHostName;
chronIntIdResTable < nciu > chanTable;
@@ -229,11 +225,11 @@ private:
// !!!! to maintain one IO table for all types of
// !!!! IO. It would probably be better to maintain
// !!!! an independent table for each IO type. The
// !!!! new adaptive sized hash table will not
// !!!! waste memory. Making this change will
// !!!! avoid virtual function overhead when
// !!!! new adaptive sized hash table will not
// !!!! waste memory. Making this change will
// !!!! avoid virtual function overhead when
// !!!! accessing the different types of IO. This
// !!!! approach would also probably be safer in
// !!!! approach would also probably be safer in
// !!!! terms of detecting damaged protocol.
//
chronIntIdResTable < baseNMIU > ioTable;
@@ -241,23 +237,23 @@ private:
resTable < tcpiiu, caServerID > serverTable;
tsDLList < tcpiiu > circuitList;
tsDLList < SearchDest > searchDestList;
tsFreeList
< class tcpiiu, 32, epicsMutexNOOP >
tsFreeList
< class tcpiiu, 32, epicsMutexNOOP >
freeListVirtualCircuit;
tsFreeList
< class netReadNotifyIO, 1024, epicsMutexNOOP >
tsFreeList
< class netReadNotifyIO, 1024, epicsMutexNOOP >
freeListReadNotifyIO;
tsFreeList
< class netWriteNotifyIO, 1024, epicsMutexNOOP >
tsFreeList
< class netWriteNotifyIO, 1024, epicsMutexNOOP >
freeListWriteNotifyIO;
tsFreeList
< class netSubscription, 1024, epicsMutexNOOP >
tsFreeList
< class netSubscription, 1024, epicsMutexNOOP >
freeListSubscription;
tsFreeList
< class nciu, 1024, epicsMutexNOOP >
tsFreeList
< class nciu, 1024, epicsMutexNOOP >
channelFreeList;
tsFreeList
< class msgForMultiplyDefinedPV, 16 >
tsFreeList
< class msgForMultiplyDefinedPV, 16 >
mdpvFreeList;
cacComBufMemoryManager comBufMemMgr;
bheFreeStore bheFreeList;
@@ -285,74 +281,74 @@ private:
unsigned iiuExistenceCount;
bool cacShutdownInProgress;
void recycleReadNotifyIO (
void recycleReadNotifyIO (
epicsGuard < epicsMutex > &, netReadNotifyIO &io );
void recycleWriteNotifyIO (
void recycleWriteNotifyIO (
epicsGuard < epicsMutex > &, netWriteNotifyIO &io );
void recycleSubscription (
void recycleSubscription (
epicsGuard < epicsMutex > &, netSubscription &io );
void disconnectChannel (
epicsGuard < epicsMutex > & cbGuard,
void disconnectChannel (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard, nciu & chan );
void ioExceptionNotify ( unsigned id, int status,
void ioExceptionNotify ( unsigned id, int status,
const char * pContext, unsigned type, arrayElementCount count );
void ioExceptionNotifyAndUninstall ( unsigned id, int status,
void ioExceptionNotifyAndUninstall ( unsigned id, int status,
const char * pContext, unsigned type, arrayElementCount count );
void pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
void pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
const char * pChannelName, const char * pAcc, const char * pRej );
// recv protocol stubs
bool versionAction ( callbackManager &, tcpiiu &,
bool versionAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool echoRespAction ( callbackManager &, tcpiiu &,
bool echoRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool writeNotifyRespAction ( callbackManager &, tcpiiu &,
bool writeNotifyRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool searchRespAction ( callbackManager &, tcpiiu &,
bool searchRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool readNotifyRespAction ( callbackManager &, tcpiiu &,
bool readNotifyRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool eventRespAction ( callbackManager &, tcpiiu &,
bool eventRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool readRespAction ( callbackManager &, tcpiiu &,
bool readRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool clearChannelRespAction ( callbackManager &, tcpiiu &,
bool clearChannelRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool exceptionRespAction ( callbackManager &, tcpiiu &,
bool exceptionRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool accessRightsRespAction ( callbackManager &, tcpiiu &,
bool accessRightsRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool createChannelRespAction ( callbackManager &, tcpiiu &,
bool createChannelRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool verifyAndDisconnectChan ( callbackManager &, tcpiiu &,
bool verifyAndDisconnectChan ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
bool badTCPRespAction ( callbackManager &, tcpiiu &,
bool badTCPRespAction ( callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
typedef bool ( cac::*pProtoStubTCP ) (
callbackManager &, tcpiiu &,
typedef bool ( cac::*pProtoStubTCP ) (
callbackManager &, tcpiiu &,
const epicsTime & currentTime, const caHdrLargeArray &, void *pMsgBdy );
static const pProtoStubTCP tcpJumpTableCAC [];
bool defaultExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool defaultExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool eventAddExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool eventAddExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool readExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool readExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool writeExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool writeExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool clearChanExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool clearChanExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool readNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool readNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
bool writeNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
bool writeNotifyExcep ( callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
typedef bool ( cac::*pExcepProtoStubTCP ) (
callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
typedef bool ( cac::*pExcepProtoStubTCP ) (
callbackManager &, tcpiiu &iiu, const caHdrLargeArray &hdr,
const char *pCtx, unsigned status );
static const pExcepProtoStubTCP tcpExcepJumpTableCAC [];
@@ -375,8 +371,8 @@ inline epicsMutex & cac::mutexRef ()
return this->mutex;
}
inline int cac :: varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
inline int cac :: varArgsPrintFormated (
epicsGuard < epicsMutex > & callbackControl,
const char *pformat, va_list args ) const
{
callbackControl.assertIdenticalMutex ( this->cbMutex );
@@ -435,14 +431,14 @@ inline notifyGuard::~notifyGuard ()
this->notify.callbackProcessingCompleteNotify ();
}
inline callbackManager::callbackManager (
inline callbackManager::callbackManager (
cacContextNotify & notify, epicsMutex & callbackControl ) :
notifyGuard ( notify ), cbGuard ( callbackControl )
{
}
inline nciu * cac::lookupChannel (
epicsGuard < epicsMutex > & guard,
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & idIn )
{
guard.assertIdenticalMutex ( this->mutex );
@@ -458,11 +454,11 @@ inline unsigned cac ::
maxContiguousFrames ( epicsGuard < epicsMutex > & ) const
{
return maxContigFrames;
}
}
inline double cac ::
connectionTimeout ( epicsGuard < epicsMutex > & guard )
{
{
guard.assertIdenticalMutex ( this->mutex );
return this->connTMO;
}

View File

@@ -5,18 +5,18 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* 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
@@ -74,9 +74,9 @@ public:
virtual ~cacWriteNotify () = 0;
virtual void completion ( epicsGuard < epicsMutex > & ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
virtual void exception (
epicsGuard < epicsMutex > &,
int status, const char * pContext,
int status, const char * pContext,
unsigned type, arrayElementCount count ) = 0;
};
@@ -85,13 +85,13 @@ public:
class epicsShareClass cacReadNotify {
public:
virtual ~cacReadNotify () = 0;
virtual void completion (
epicsGuard < epicsMutex > &, unsigned type,
virtual void completion (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pData ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char * pContext, unsigned type,
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char * pContext, unsigned type,
arrayElementCount count ) = 0;
};
@@ -100,21 +100,21 @@ public:
class epicsShareClass cacStateNotify {
public:
virtual ~cacStateNotify () = 0;
virtual void current (
epicsGuard < epicsMutex > &, unsigned type,
virtual void current (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pData ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char *pContext, unsigned type,
virtual void exception (
epicsGuard < epicsMutex > &, int status,
const char *pContext, unsigned type,
arrayElementCount count ) = 0;
};
class caAccessRights {
public:
caAccessRights (
bool readPermit = false,
bool writePermit = false,
caAccessRights (
bool readPermit = false,
bool writePermit = false,
bool operatorConfirmationRequest = false);
void setReadPermit ();
void setWritePermit ();
@@ -138,20 +138,30 @@ public:
virtual void disconnectNotify ( epicsGuard < epicsMutex > & ) = 0;
virtual void serviceShutdownNotify (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual void accessRightsNotify (
virtual void accessRightsNotify (
epicsGuard < epicsMutex > &, const caAccessRights & ) = 0;
virtual void exception (
virtual void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void readException (
virtual void readException (
epicsGuard < epicsMutex > &, int status, const char *pContext,
unsigned type, arrayElementCount count, void *pValue ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void writeException (
virtual void writeException (
epicsGuard < epicsMutex > &, int status, const char * pContext,
unsigned type, arrayElementCount count ) = 0;
};
class CallbackGuard :
public epicsGuard < epicsMutex > {
public:
CallbackGuard ( epicsMutex & mutex ) :
epicsGuard < epicsMutex > ( mutex ) {}
private:
CallbackGuard ( const CallbackGuard & );
CallbackGuard & operator = ( const CallbackGuard & );
};
//
// Notes
// 1) This interface assumes that when a channel is deleted then all
@@ -174,43 +184,52 @@ public:
cacChannel ( cacChannelNotify & );
virtual void destroy (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
cacChannelNotify & notify () const; // required ?????
virtual unsigned getName (
epicsGuard < epicsMutex > &,
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw () = 0;
// !! deprecated, avoid use !!
virtual const char * pName (
epicsGuard < epicsMutex > & guard ) const throw () = 0;
virtual void show (
virtual void show (
epicsGuard < epicsMutex > &,
unsigned level ) const = 0;
virtual void initiateConnect (
epicsGuard < epicsMutex > & ) = 0;
virtual unsigned requestMessageBytesPending (
virtual unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual void flush (
virtual void flush (
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual ioStatus read (
virtual ioStatus read (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
cacReadNotify &, ioid * = 0 ) = 0;
virtual void write (
virtual void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
const void *pValue ) = 0;
virtual ioStatus write (
virtual ioStatus write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
const void *pValue, cacWriteNotify &, ioid * = 0 ) = 0;
virtual void subscribe (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, unsigned mask, cacStateNotify &,
virtual void subscribe (
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, unsigned mask, cacStateNotify &,
ioid * = 0 ) = 0;
virtual void ioCancel (
// The primary mutex must be released when calling the user's
// callback, and therefore a finite interval exists when we are
// moving forward with the intent to call the users callback
// but the users IO could be deleted during this interval.
// To prevent the user's callback from being called after
// destroying his IO we must past a guard for the callback
// mutex here.
virtual void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & ) = 0;
virtual void ioShow (
virtual void ioShow (
epicsGuard < epicsMutex > &,
const ioid &, unsigned level ) const = 0;
virtual short nativeType (
@@ -226,9 +245,9 @@ public:
virtual double receiveWatchdogDelay (
epicsGuard < epicsMutex > & ) const; // negative DBL_MAX if UKN
virtual bool ca_v42_ok (
epicsGuard < epicsMutex > & ) const;
epicsGuard < epicsMutex > & ) const;
virtual bool connected (
epicsGuard < epicsMutex > & ) const;
epicsGuard < epicsMutex > & ) const;
virtual unsigned getHostName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLength ) const throw ();
@@ -261,11 +280,11 @@ private:
class epicsShareClass cacContext {
public:
virtual ~cacContext ();
virtual cacChannel & createChannel (
virtual cacChannel & createChannel (
epicsGuard < epicsMutex > &,
const char * pChannelName, cacChannelNotify &,
const char * pChannelName, cacChannelNotify &,
cacChannel::priLev = cacChannel::priorityDefault ) = 0;
virtual void flush (
virtual void flush (
epicsGuard < epicsMutex > & ) = 0;
virtual unsigned circuitCount (
epicsGuard < epicsMutex > & ) const = 0;
@@ -273,18 +292,18 @@ public:
epicsGuard < epicsMutex > & ) const = 0;
virtual unsigned beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & ) const = 0;
virtual void show (
virtual void show (
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
};
class epicsShareClass cacContextNotify {
public:
virtual ~cacContextNotify () = 0;
virtual cacContext & createNetworkContext (
virtual cacContext & createNetworkContext (
epicsMutex & mutualExclusion, epicsMutex & callbackControl ) = 0;
// we should probably have a different vf for each type of exception ????
virtual void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
virtual void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo ) = 0;
// perhaps this should be phased out in deference to the exception mechanism
virtual int varArgsPrintFormated ( const char * pformat, va_list args ) const = 0;
@@ -300,9 +319,9 @@ public:
class epicsShareClass cacService {
public:
virtual ~cacService () = 0;
virtual cacContext & contextCreate (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
virtual cacContext & contextCreate (
epicsMutex & mutualExclusion,
epicsMutex & callbackControl,
cacContextNotify & ) = 0;
};
@@ -320,9 +339,9 @@ inline cacChannelNotify & cacChannel::notify () const
return this->callback;
}
inline caAccessRights::caAccessRights (
inline caAccessRights::caAccessRights (
bool readPermit, bool writePermit, bool operatorConfirmationRequest) :
f_readPermit ( readPermit ), f_writePermit ( writePermit ),
f_readPermit ( readPermit ), f_writePermit ( writePermit ),
f_operatorConfirmationRequest ( operatorConfirmationRequest ) {}
inline void caAccessRights::setReadPermit ()

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
@@ -39,9 +39,9 @@
#include "db_access.h" // for INVALID_DB_REQ
#include "noopiiu.h"
nciu::nciu ( cac & cacIn, netiiu & iiuIn, cacChannelNotify & chanIn,
nciu::nciu ( cac & cacIn, netiiu & iiuIn, cacChannelNotify & chanIn,
const char *pNameIn, cacChannel::priLev pri ) :
cacChannel ( chanIn ),
cacChannel ( chanIn ),
cacCtx ( cacIn ),
piiu ( & iiuIn ),
sid ( UINT_MAX ),
@@ -57,7 +57,7 @@ nciu::nciu ( cac & cacIn, netiiu & iiuIn, cacChannelNotify & chanIn,
if ( nameLengthTmp > MAX_UDP_SEND - sizeof ( caHdr ) || nameLengthTmp > USHRT_MAX ) {
throw cacChannel::badString ();
}
if ( pri > 0xff ) {
throw cacChannel::badPriority ();
}
@@ -76,26 +76,28 @@ nciu::~nciu ()
// channels are created by the user, and only destroyed by the user
// using this routine
void nciu::destroy (
epicsGuard < epicsMutex > & guard )
{
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExcusionGuard )
{
while ( baseNMIU * pNetIO = this->eventq.first () ) {
bool success = this->cacCtx.destroyIO ( guard, pNetIO->getId (), *this );
bool success = this->cacCtx.destroyIO ( callbackGuard, mutualExcusionGuard,
pNetIO->getId (), *this );
assert ( success );
}
// if the claim reply has not returned yet then we will issue
// the clear channel request to the server when the claim reply
// arrives and there is no matching nciu in the client
if ( this->channelNode::isInstalledInServer ( guard ) ) {
this->getPIIU(guard)->clearChannelRequest (
guard, this->sid, this->id );
if ( this->channelNode::isInstalledInServer ( mutualExcusionGuard ) ) {
this->getPIIU(mutualExcusionGuard)->clearChannelRequest (
mutualExcusionGuard, this->sid, this->id );
}
this->piiu->uninstallChan ( guard, *this );
this->cacCtx.destroyChannel ( guard, *this );
this->piiu->uninstallChan ( mutualExcusionGuard, *this );
this->cacCtx.destroyChannel ( mutualExcusionGuard, *this );
}
void nciu::operator delete ( void * )
{
{
// Visual C++ .net appears to require operator delete if
// placement operator delete is defined? I smell a ms rat
// because if I declare placement new and delete, but
@@ -105,15 +107,15 @@ void nciu::operator delete ( void * )
__FILE__, __LINE__ );
}
void nciu::initiateConnect (
void nciu::initiateConnect (
epicsGuard < epicsMutex > & guard )
{
{
this->cacCtx.initiateConnect ( guard, *this, this->piiu );
}
void nciu::connect ( unsigned nativeType,
unsigned nativeCount, unsigned sidIn,
epicsGuard < epicsMutex > & /* cbGuard */,
void nciu::connect ( unsigned nativeType,
unsigned nativeCount, unsigned sidIn,
epicsGuard < epicsMutex > & /* cbGuard */,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
@@ -127,7 +129,7 @@ void nciu::connect ( unsigned nativeType,
/*
* if less than v4.1 then the server will never
* send access rights and there will always be access
* send access rights and there will always be access
*/
bool v41Ok = this->piiu->ca_v41_ok ( guard );
if ( ! v41Ok ) {
@@ -138,49 +140,49 @@ void nciu::connect ( unsigned nativeType,
/*
* if less than v4.1 then the server will never
* send access rights and we know that there
* will always be access and also need to call
* will always be access and also need to call
* their call back here
*/
if ( ! v41Ok ) {
this->notify().accessRightsNotify (
this->notify().accessRightsNotify (
guard, this->accessRightState );
}
// channel uninstal routine grabs the callback lock so
// a channel will not be deleted while a call back is
// a channel will not be deleted while a call back is
// in progress
//
// the callback lock is also taken when a channel
// disconnects to prevent a race condition with the
// the callback lock is also taken when a channel
// disconnects to prevent a race condition with the
// code below - ie we hold the callback lock here
// so a chanel cant be destroyed out from under us.
this->notify().connectNotify ( guard );
}
void nciu::unresponsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
void nciu::unresponsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
ioid tmpId = this->getId ();
cac & caRefTmp = this->cacCtx;
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
this->cacCtx.disconnectAllIO ( cbGuard, guard,
this->cacCtx.disconnectAllIO ( cbGuard, guard,
*this, this->eventq );
this->notify().disconnectNotify ( guard );
// if they destroy the channel in their disconnect
// if they destroy the channel in their disconnect
// handler then we have to be very careful to not
// touch this object if it has been destroyed
nciu * pChan = caRefTmp.lookupChannel ( guard, tmpId );
if ( pChan ) {
caAccessRights noRights;
pChan->notify().accessRightsNotify ( guard, noRights );
// likewise, they might destroy the channel in their access rights
// handler so we have to be very careful to not touch this
// likewise, they might destroy the channel in their access rights
// handler so we have to be very careful to not touch this
// object from here on down
}
}
void nciu::setServerAddressUnknown ( netiiu & newiiu,
void nciu::setServerAddressUnknown ( netiiu & newiiu,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
@@ -193,8 +195,8 @@ void nciu::setServerAddressUnknown ( netiiu & newiiu,
this->accessRightState.clrWritePermit();
}
void nciu::accessRightsStateChange (
const caAccessRights & arIn, epicsGuard < epicsMutex > & /* cbGuard */,
void nciu::accessRightsStateChange (
const caAccessRights & arIn, epicsGuard < epicsMutex > & /* cbGuard */,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
@@ -204,7 +206,7 @@ void nciu::accessRightsStateChange (
// the channel delete routine takes the call back lock so
// that this will not be called when the channel is being
// deleted.
//
//
this->notify().accessRightsNotify ( guard, this->accessRightState );
}
@@ -213,7 +215,7 @@ void nciu::accessRightsStateChange (
*/
bool nciu::searchMsg ( epicsGuard < epicsMutex > & guard )
{
bool success = this->piiu->searchMsg (
bool success = this->piiu->searchMsg (
guard, this->getId (), this->pNameStr, this->nameLength );
if ( success ) {
if ( this->retry < UINT_MAX ) {
@@ -256,21 +258,21 @@ unsigned nciu::nameLen (
return this->nameLength;
}
unsigned nciu::requestMessageBytesPending (
unsigned nciu::requestMessageBytesPending (
epicsGuard < epicsMutex > & guard )
{
return piiu->requestMessageBytesPending ( guard );
}
void nciu::flush (
void nciu::flush (
epicsGuard < epicsMutex > & guard )
{
piiu->flush ( guard );
}
cacChannel::ioStatus nciu::read (
cacChannel::ioStatus nciu::read (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount countIn,
unsigned type, arrayElementCount countIn,
cacReadNotify &notify, ioid *pId )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
@@ -292,7 +294,7 @@ cacChannel::ioStatus nciu::read (
throw cacChannel::badType ();
}
netReadNotifyIO & io = this->cacCtx.readNotifyRequest (
netReadNotifyIO & io = this->cacCtx.readNotifyRequest (
guard, *this, *this, type, countIn, notify );
if ( pId ) {
*pId = io.getId ();
@@ -314,7 +316,7 @@ void nciu::stringVerify ( const char *pStr, const unsigned count )
}
}
void nciu::write (
void nciu::write (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount countIn, const void * pValue )
{
@@ -337,8 +339,8 @@ void nciu::write (
this->piiu->writeRequest ( guard, *this, type, countIn, pValue );
}
cacChannel::ioStatus nciu::write (
epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount countIn,
cacChannel::ioStatus nciu::write (
epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount countIn,
const void * pValue, cacWriteNotify & notify, ioid * pId )
{
// make sure that they get this and not "no write access"
@@ -356,7 +358,7 @@ cacChannel::ioStatus nciu::write (
nciu::stringVerify ( (char *) pValue, countIn );
}
netWriteNotifyIO & io = this->cacCtx.writeNotifyRequest (
netWriteNotifyIO & io = this->cacCtx.writeNotifyRequest (
guard, *this, *this, type, countIn, pValue, notify );
if ( pId ) {
*pId = io.getId ();
@@ -365,13 +367,13 @@ cacChannel::ioStatus nciu::write (
return cacChannel::iosAsynch;
}
void nciu::subscribe (
epicsGuard < epicsMutex > & guard, unsigned type,
arrayElementCount nElem, unsigned mask,
void nciu::subscribe (
epicsGuard < epicsMutex > & guard, unsigned type,
arrayElementCount nElem, unsigned mask,
cacStateNotify & notify, ioid *pId )
{
netSubscription & io = this->cacCtx.subscriptionRequest (
guard, *this, *this, type, nElem, mask, notify,
netSubscription & io = this->cacCtx.subscriptionRequest (
guard, *this, *this, type, nElem, mask, notify,
this->channelNode::isInstalledInServer ( guard ) );
this->eventq.add ( io );
if ( pId ) {
@@ -379,24 +381,27 @@ void nciu::subscribe (
}
}
void nciu::ioCancel (
epicsGuard < epicsMutex > & guard, const ioid & idIn )
void nciu::ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & idIn )
{
this->cacCtx.destroyIO ( guard, idIn, *this );
this->cacCtx.destroyIO ( callbackGuard,
mutualExclusionGuard, idIn, *this );
}
void nciu::ioShow (
epicsGuard < epicsMutex > & guard,
void nciu::ioShow (
epicsGuard < epicsMutex > & guard,
const ioid &idIn, unsigned level ) const
{
this->cacCtx.ioShow ( guard, idIn, level );
}
unsigned nciu::getHostName (
unsigned nciu::getHostName (
epicsGuard < epicsMutex > & guard,
char *pBuf, unsigned bufLength ) const throw ()
{
return this->piiu->getHostName (
{
return this->piiu->getHostName (
guard, pBuf, bufLength );
}
@@ -424,7 +429,7 @@ short nciu::nativeType (
return type;
}
arrayElementCount nciu::nativeElementCount (
arrayElementCount nciu::nativeElementCount (
epicsGuard < epicsMutex > & guard ) const
{
arrayElementCount countOut = 0ul;
@@ -472,20 +477,20 @@ void nciu::show ( unsigned level ) const
this->show ( guard, level );
}
void nciu::show (
void nciu::show (
epicsGuard < epicsMutex > & guard, unsigned level ) const
{
if ( this->connected ( guard ) ) {
char hostNameTmp [256];
this->getHostName ( guard, hostNameTmp, sizeof ( hostNameTmp ) );
::printf ( "Channel \"%s\", connected to server %s",
::printf ( "Channel \"%s\", connected to server %s",
this->pNameStr, hostNameTmp );
if ( level > 1u ) {
int tmpTypeCode = static_cast < int > ( this->typeCode );
::printf ( ", native type %s, native element count %u",
dbf_type_to_text ( tmpTypeCode ), this->count );
::printf ( ", %sread access, %swrite access",
this->accessRightState.readPermit() ? "" : "no ",
::printf ( ", %sread access, %swrite access",
this->accessRightState.readPermit() ? "" : "no ",
this->accessRightState.writePermit() ? "" : "no ");
}
::printf ( "\n" );
@@ -495,7 +500,7 @@ void nciu::show (
}
if ( level > 2u ) {
::printf ( "\tnetwork IO pointer = %p\n",
::printf ( "\tnetwork IO pointer = %p\n",
static_cast <void *> ( this->piiu ) );
::printf ( "\tserver identifier %u\n", this->sid );
::printf ( "\tsearch retry number=%u\n", this->retry );
@@ -503,7 +508,7 @@ void nciu::show (
}
}
void nciu::ioCompletionNotify (
void nciu::ioCompletionNotify (
epicsGuard < epicsMutex > &, class baseNMIU & io )
{
this->eventq.remove ( io );
@@ -544,7 +549,7 @@ void nciu::sendSubscriptionUpdateRequests ( epicsGuard < epicsMutex > & guard )
pNetIO->forceSubscriptionUpdate ( guard, *this );
}
catch ( ... ) {
errlogPrintf (
errlogPrintf (
"CAC: failed to send subscription update request "
"during channel connect\n" );
}
@@ -552,68 +557,68 @@ void nciu::sendSubscriptionUpdateRequests ( epicsGuard < epicsMutex > & guard )
}
}
void nciu::disconnectAllIO (
epicsGuard < epicsMutex > & cbGuard,
void nciu::disconnectAllIO (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
this->cacCtx.disconnectAllIO ( cbGuard, guard,
this->cacCtx.disconnectAllIO ( cbGuard, guard,
*this, this->eventq );
}
void nciu::serviceShutdownNotify (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
{
this->setServerAddressUnknown ( noopIIU, mutualExclusionGuard );
this->notify().serviceShutdownNotify ( mutualExclusionGuard );
}
void channelNode::setRespPendingState (
epicsGuard < epicsMutex > &, unsigned index )
void channelNode::setRespPendingState (
epicsGuard < epicsMutex > &, unsigned index )
{
this->listMember =
this->listMember =
static_cast < channelNode::channelState >
( channelNode::cs_searchRespPending0 + index );
if ( this->listMember > cs_searchRespPending17 ) {
throw std::runtime_error (
throw std::runtime_error (
"resp search timer index out of bounds" );
}
}
void channelNode::setReqPendingState (
epicsGuard < epicsMutex > &, unsigned index )
void channelNode::setReqPendingState (
epicsGuard < epicsMutex > &, unsigned index )
{
this->listMember =
this->listMember =
static_cast < channelNode::channelState >
( channelNode::cs_searchReqPending0 + index );
if ( this->listMember > cs_searchReqPending17 ) {
throw std::runtime_error (
throw std::runtime_error (
"req search timer index out of bounds" );
}
}
unsigned channelNode::getMaxSearchTimerCount ()
unsigned channelNode::getMaxSearchTimerCount ()
{
return epicsMin (
return epicsMin (
cs_searchReqPending17 - cs_searchReqPending0,
cs_searchRespPending17 - cs_searchRespPending0 ) + 1u;
}
unsigned channelNode::getSearchTimerIndex (
unsigned channelNode::getSearchTimerIndex (
epicsGuard < epicsMutex > & )
{
channelNode::channelState chanState = this->listMember;
unsigned index = 0u;
if ( chanState >= cs_searchReqPending0 &&
if ( chanState >= cs_searchReqPending0 &&
chanState <= cs_searchReqPending17 ) {
index = chanState - cs_searchReqPending0;
}
else if ( chanState >= cs_searchRespPending0 &&
else if ( chanState >= cs_searchRespPending0 &&
chanState <= cs_searchRespPending17 ) {
index = chanState - cs_searchRespPending0;
}
else {
throw std::runtime_error (
throw std::runtime_error (
"channel was expected to be in a search timer, but wasnt" );;
}
return index;

View File

@@ -5,24 +5,24 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* 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
*/
#ifndef nciuh
#ifndef nciuh
#define nciuh
#ifdef epicsExportSharedSymbols
@@ -123,45 +123,45 @@ private:
class privateInterfaceForIO {
public:
virtual void ioCompletionNotify (
virtual void ioCompletionNotify (
epicsGuard < epicsMutex > &, class baseNMIU & ) = 0;
virtual arrayElementCount nativeElementCount (
virtual arrayElementCount nativeElementCount (
epicsGuard < epicsMutex > & ) const = 0;
virtual bool connected ( epicsGuard < epicsMutex > & ) const = 0;
protected:
virtual ~privateInterfaceForIO() {}
};
class nciu :
class nciu :
public cacChannel,
public chronIntIdRes < nciu >,
public chronIntIdRes < nciu >,
public channelNode,
private privateInterfaceForIO {
public:
nciu ( cac &, netiiu &, cacChannelNotify &,
nciu ( cac &, netiiu &, cacChannelNotify &,
const char * pNameIn, cacChannel::priLev );
~nciu ();
void connect ( unsigned nativeType,
unsigned nativeCount, unsigned sid,
epicsGuard < epicsMutex > & cbGuard,
void connect ( unsigned nativeType,
unsigned nativeCount, unsigned sid,
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void connect ( epicsGuard < epicsMutex > & cbGuard,
void connect ( epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void unresponsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
void unresponsiveCircuitNotify (
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void circuitHangupNotify ( class udpiiu &,
epicsGuard < epicsMutex > & cbGuard,
void circuitHangupNotify ( class udpiiu &,
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
void setServerAddressUnknown (
void setServerAddressUnknown (
netiiu & newiiu, epicsGuard < epicsMutex > & guard );
bool searchMsg (
bool searchMsg (
epicsGuard < epicsMutex > & );
void serviceShutdownNotify (
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & callbackControlGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void accessRightsStateChange ( const caAccessRights &,
epicsGuard < epicsMutex > & cbGuard,
void accessRightsStateChange ( const caAccessRights &,
epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard );
ca_uint32_t getSID (
epicsGuard < epicsMutex > & ) const;
@@ -172,12 +172,12 @@ public:
const netiiu * getConstPIIU (
epicsGuard < epicsMutex > & ) const;
cac & getClient ();
void searchReplySetUp ( netiiu &iiu, unsigned sidIn,
void searchReplySetUp ( netiiu &iiu, unsigned sidIn,
ca_uint16_t typeIn, arrayElementCount countIn,
epicsGuard < epicsMutex > & );
void show (
void show (
unsigned level ) const;
void show (
void show (
epicsGuard < epicsMutex > &,
unsigned level ) const;
unsigned getName (
@@ -189,22 +189,22 @@ public:
epicsGuard < epicsMutex > & ) const;
unsigned getHostName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw ();
void writeException (
char * pBuf, unsigned bufLen ) const throw ();
void writeException (
epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > &,
int status, const char *pContext, unsigned type, arrayElementCount count );
cacChannel::priLev getPriority (
epicsGuard < epicsMutex > & ) const;
void * operator new (
void * operator new (
size_t size, tsFreeList < class nciu, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (
( void *, tsFreeList < class nciu, 1024, epicsMutexNOOP > & ))
//arrayElementCount nativeElementCount ( epicsGuard < epicsMutex > & ) const;
void resubscribe ( epicsGuard < epicsMutex > & );
void sendSubscriptionUpdateRequests ( epicsGuard < epicsMutex > & );
void disconnectAllIO (
void disconnectAllIO (
epicsGuard < epicsMutex > &, epicsGuard < epicsMutex > & );
bool connected ( epicsGuard < epicsMutex > & ) const;
bool connected ( epicsGuard < epicsMutex > & ) const;
unsigned getcount() const { return count; }
private:
@@ -218,38 +218,47 @@ private:
unsigned retry; // search retry number
unsigned short nameLength; // channel name length
ca_uint16_t typeCode;
ca_uint8_t priority;
ca_uint8_t priority;
virtual void destroy (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void initiateConnect (
epicsGuard < epicsMutex > & );
unsigned requestMessageBytesPending (
unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & mutualExclusionGuard );
void flush (
void flush (
epicsGuard < epicsMutex > & mutualExclusionGuard );
ioStatus read (
ioStatus read (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
cacReadNotify &, ioid * );
void write (
void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
const void *pValue );
ioStatus write (
ioStatus write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
const void *pValue, cacWriteNotify &, ioid * );
void subscribe (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount nElem,
void subscribe (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount nElem,
unsigned mask, cacStateNotify &notify, ioid * );
virtual void ioCancel (
// The primary mutex must be released when calling the user's
// callback, and therefore a finite interval exists when we are
// moving forward with the intent to call the users callback
// but the users IO could be deleted during this interval.
// To prevent the user's callback from being called after
// destroying his IO we must past a guard for the callback
// mutex here.
virtual void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & );
void ioShow (
void ioShow (
epicsGuard < epicsMutex > &,
const ioid &, unsigned level ) const;
short nativeType (
short nativeType (
epicsGuard < epicsMutex > & ) const;
caAccessRights accessRights (
epicsGuard < epicsMutex > & ) const;
@@ -264,7 +273,7 @@ private:
arrayElementCount nativeElementCount (
epicsGuard < epicsMutex > & ) const;
static void stringVerify ( const char *pStr, const unsigned count );
void ioCompletionNotify (
void ioCompletionNotify (
epicsGuard < epicsMutex > &, class baseNMIU & );
const char * pHostName (
epicsGuard < epicsMutex > & guard ) const throw ();
@@ -273,16 +282,16 @@ private:
void operator delete ( void * );
};
inline void * nciu::operator new ( size_t size,
inline void * nciu::operator new ( size_t size,
tsFreeList < class nciu, 1024, epicsMutexNOOP > & freeList )
{
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void nciu::operator delete ( void * pCadaver,
tsFreeList < class nciu, 1024, epicsMutexNOOP > & freeList )
{
{
freeList.release ( pCadaver, sizeof ( nciu ) );
}
#endif
@@ -300,19 +309,19 @@ inline ca_uint32_t nciu::getCID (
}
// this is to only be used by early protocol revisions
inline void nciu::connect ( epicsGuard < epicsMutex > & cbGuard,
inline void nciu::connect ( epicsGuard < epicsMutex > & cbGuard,
epicsGuard < epicsMutex > & guard )
{
this->connect ( this->typeCode, this->count,
this->connect ( this->typeCode, this->count,
this->sid, cbGuard, guard );
}
inline void nciu::searchReplySetUp ( netiiu &iiu, unsigned sidIn,
inline void nciu::searchReplySetUp ( netiiu &iiu, unsigned sidIn,
ca_uint16_t typeIn, arrayElementCount countIn,
epicsGuard < epicsMutex > & )
{
this->piiu = & iiu;
this->typeCode = typeIn;
this->typeCode = typeIn;
this->count = countIn;
this->sid = sidIn;
}
@@ -323,13 +332,13 @@ inline netiiu * nciu::getPIIU (
return this->piiu;
}
inline void nciu::writeException (
epicsGuard < epicsMutex > & /* cbGuard */,
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
inline void nciu::writeException (
epicsGuard < epicsMutex > & /* cbGuard */,
epicsGuard < epicsMutex > & guard,
int status, const char * pContext,
unsigned typeIn, arrayElementCount countIn )
{
this->notify().writeException ( guard,
this->notify().writeException ( guard,
status, pContext, typeIn, countIn );
}
@@ -357,15 +366,15 @@ inline channelNode::channelNode () :
inline bool channelNode::isConnected ( epicsGuard < epicsMutex > & ) const
{
return
this->listMember == cs_connected ||
return
this->listMember == cs_connected ||
this->listMember == cs_subscripReqPend ||
this->listMember == cs_subscripUpdateReqPend;
}
inline bool channelNode::isInstalledInServer ( epicsGuard < epicsMutex > & ) const
{
return
return
this->listMember == cs_connected ||
this->listMember == cs_subscripReqPend ||
this->listMember == cs_unrespCircuit ||

View File

@@ -5,19 +5,19 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
*
* Copyright, The Regents of the University of California.
*
*
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
@@ -48,92 +48,94 @@
struct oldChannelNotify : private cacChannelNotify {
public:
oldChannelNotify (
epicsGuard < epicsMutex > &, struct ca_client_context &,
const char * pName, caCh * pConnCallBackIn,
oldChannelNotify (
epicsGuard < epicsMutex > &, struct ca_client_context &,
const char * pName, caCh * pConnCallBackIn,
void * pPrivateIn, capri priority );
void destructor (
epicsGuard < epicsMutex > & guard );
void destructor (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & mutexGuard );
// legacy C API
friend unsigned epicsShareAPI ca_get_host_name (
friend unsigned epicsShareAPI ca_get_host_name (
chid pChan, char * pBuf, unsigned bufLength );
friend const char * epicsShareAPI ca_host_name (
friend const char * epicsShareAPI ca_host_name (
chid pChan );
friend const char * epicsShareAPI ca_name (
friend const char * epicsShareAPI ca_name (
chid pChan );
friend void epicsShareAPI ca_set_puser (
friend void epicsShareAPI ca_set_puser (
chid pChan, void * puser );
friend void * epicsShareAPI ca_puser (
friend void * epicsShareAPI ca_puser (
chid pChan );
friend int epicsShareAPI ca_change_connection_event (
friend int epicsShareAPI ca_change_connection_event (
chid pChan, caCh * pfunc );
friend int epicsShareAPI ca_replace_access_rights_event (
friend int epicsShareAPI ca_replace_access_rights_event (
chid pChan, caArh *pfunc );
friend int epicsShareAPI ca_array_get ( chtype type,
friend int epicsShareAPI ca_array_get ( chtype type,
arrayElementCount count, chid pChan, void * pValue );
friend int epicsShareAPI ca_array_get_callback ( chtype type,
friend int epicsShareAPI ca_array_get_callback ( chtype type,
arrayElementCount count, chid pChan,
caEventCallBackFunc *pfunc, void *arg );
friend int epicsShareAPI ca_array_put (
chtype type, arrayElementCount count,
friend int epicsShareAPI ca_array_put (
chtype type, arrayElementCount count,
chid pChan, const void * pValue );
friend int epicsShareAPI ca_array_put_callback (
chtype type, arrayElementCount count,
chid pChan, const void *pValue,
friend int epicsShareAPI ca_array_put_callback (
chtype type, arrayElementCount count,
chid pChan, const void *pValue,
caEventCallBackFunc *pfunc, void *usrarg );
friend double epicsShareAPI ca_beacon_period (
friend double epicsShareAPI ca_beacon_period (
chid pChan );
friend unsigned epicsShareAPI ca_search_attempts (
friend unsigned epicsShareAPI ca_search_attempts (
chid pChan );
friend unsigned epicsShareAPI ca_write_access (
friend unsigned epicsShareAPI ca_write_access (
chid pChan );
friend unsigned epicsShareAPI ca_read_access (
friend unsigned epicsShareAPI ca_read_access (
chid pChan );
friend short epicsShareAPI ca_field_type (
friend short epicsShareAPI ca_field_type (
chid pChan );
friend arrayElementCount epicsShareAPI ca_element_count (
friend arrayElementCount epicsShareAPI ca_element_count (
chid pChan );
friend int epicsShareAPI ca_v42_ok (
friend int epicsShareAPI ca_v42_ok (
chid pChan );
friend int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack,
friend int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack,
void * pCallBackArg, evid * monixptr );
friend enum channel_state epicsShareAPI ca_state (
chid pChan );
friend double epicsShareAPI ca_receive_watchdog_delay (
friend enum channel_state epicsShareAPI ca_state (
chid pChan );
friend double epicsShareAPI ca_receive_watchdog_delay (
chid pChan );
unsigned getName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw ();
void show (
void show (
epicsGuard < epicsMutex > &,
unsigned level ) const;
void initiateConnect (
epicsGuard < epicsMutex > & );
void read (
void read (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
cacReadNotify &notify, cacChannel::ioid *pId = 0 );
void write (
void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count, const void *pValue,
unsigned type, arrayElementCount count, const void *pValue,
cacWriteNotify &, cacChannel::ioid *pId = 0 );
void ioCancel (
epicsGuard < epicsMutex > & mutualExclusionGuard,
void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const cacChannel::ioid & );
void ioShow (
void ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid &, unsigned level ) const;
ca_client_context & getClientCtx ();
void eliminateExcessiveSendBacklog (
void eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & );
void * operator new ( size_t size,
void * operator new ( size_t size,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void * ,
epicsPlacementDeleteOperator (( void * ,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & ))
protected:
~oldChannelNotify ();
@@ -150,7 +152,7 @@ private:
void disconnectNotify ( epicsGuard < epicsMutex > & );
void serviceShutdownNotify (
epicsGuard < epicsMutex > & mutualExclusionGuard );
void accessRightsNotify (
void accessRightsNotify (
epicsGuard < epicsMutex > &, const caAccessRights & );
void exception ( epicsGuard < epicsMutex > &,
int status, const char * pContext );
@@ -160,24 +162,24 @@ private:
void writeException ( epicsGuard < epicsMutex > &,
int status, const char * pContext,
unsigned type, arrayElementCount count );
oldChannelNotify ( const oldChannelNotify & );
oldChannelNotify & operator = ( const oldChannelNotify & );
oldChannelNotify ( const oldChannelNotify & );
oldChannelNotify & operator = ( const oldChannelNotify & );
void operator delete ( void * );
};
class getCopy : public cacReadNotify {
public:
getCopy (
epicsGuard < epicsMutex > & guard,
ca_client_context & cacCtx,
oldChannelNotify &, unsigned type,
getCopy (
epicsGuard < epicsMutex > & guard,
ca_client_context & cacCtx,
oldChannelNotify &, unsigned type,
arrayElementCount count, void *pValue );
~getCopy ();
void show ( unsigned level ) const;
void cancel ();
void * operator new ( size_t size,
void * operator new ( size_t size,
tsFreeList < class getCopy, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < class getCopy, 1024, epicsMutexNOOP > & ))
private:
arrayElementCount count;
@@ -187,10 +189,10 @@ private:
unsigned ioSeqNo;
unsigned type;
void completion (
epicsGuard < epicsMutex > &, unsigned type,
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void *pData );
void exception (
epicsGuard < epicsMutex > &, int status,
void exception (
epicsGuard < epicsMutex > &, int status,
const char *pContext, unsigned type, arrayElementCount count );
getCopy ( const getCopy & );
getCopy & operator = ( const getCopy & );
@@ -199,23 +201,23 @@ private:
class getCallback : public cacReadNotify {
public:
getCallback (
oldChannelNotify & chanIn,
getCallback (
oldChannelNotify & chanIn,
caEventCallBackFunc *pFunc, void *pPrivate );
~getCallback ();
void * operator new ( size_t size,
~getCallback ();
void * operator new ( size_t size,
tsFreeList < class getCallback, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < class getCallback, 1024, epicsMutexNOOP > & ))
private:
oldChannelNotify & chan;
caEventCallBackFunc * pFunc;
void * pPrivate;
void completion (
epicsGuard < epicsMutex > &, unsigned type,
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void *pData);
void exception (
epicsGuard < epicsMutex > &, int status,
void exception (
epicsGuard < epicsMutex > &, int status,
const char * pContext, unsigned type, arrayElementCount count );
getCallback ( const getCallback & );
getCallback & operator = ( const getCallback & );
@@ -224,21 +226,21 @@ private:
class putCallback : public cacWriteNotify {
public:
putCallback (
oldChannelNotify &,
putCallback (
oldChannelNotify &,
caEventCallBackFunc *pFunc, void *pPrivate );
~putCallback ();
void * operator new ( size_t size,
void * operator new ( size_t size,
tsFreeList < class putCallback, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < class putCallback, 1024, epicsMutexNOOP > & ))
private:
oldChannelNotify & chan;
caEventCallBackFunc * pFunc;
void *pPrivate;
void completion ( epicsGuard < epicsMutex > & );
void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext,
void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext,
unsigned type, arrayElementCount count );
putCallback ( const putCallback & );
putCallback & operator = ( const putCallback & );
@@ -249,17 +251,25 @@ struct oldSubscription : private cacStateNotify {
public:
oldSubscription (
epicsGuard < epicsMutex > & guard,
oldChannelNotify & chanIn, cacChannel & io,
oldChannelNotify & chanIn, cacChannel & io,
unsigned type, arrayElementCount nElem, unsigned mask,
caEventCallBackFunc * pFuncIn, void * pPrivateIn,
evid * );
~oldSubscription ();
oldChannelNotify & channel () const;
void cancel (
epicsGuard < epicsMutex > & guard );
void * operator new ( size_t size,
// The primary mutex must be released when calling the user's
// callback, and therefore a finite interval exists when we are
// moving forward with the intent to call the users callback
// but the users IO could be deleted during this interval.
// To prevent the user's callback from being called after
// destroying his IO we must past a guard for the callback
// mutex here.
void cancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void * operator new ( size_t size,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & ))
private:
oldChannelNotify & chan;
@@ -267,10 +277,10 @@ private:
caEventCallBackFunc * pFunc;
void * pPrivate;
void current (
epicsGuard < epicsMutex > &, unsigned type,
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void *pData );
void exception (
epicsGuard < epicsMutex > &, int status,
void exception (
epicsGuard < epicsMutex > &, int status,
const char *pContext, unsigned type, arrayElementCount count );
oldSubscription ( const oldSubscription & );
oldSubscription & operator = ( const oldSubscription & );
@@ -285,16 +295,16 @@ struct ca_client_context : public cacContextNotify
public:
ca_client_context ( bool enablePreemptiveCallback = false );
virtual ~ca_client_context ();
void changeExceptionEvent (
void changeExceptionEvent (
caExceptionHandler * pfunc, void * arg );
void registerForFileDescriptorCallBack (
void registerForFileDescriptorCallBack (
CAFDHANDLER * pFunc, void * pArg );
void replaceErrLogHandler ( caPrintfFunc * ca_printf_func );
cacChannel & createChannel (
epicsGuard < epicsMutex > &, const char * pChannelName,
cacChannel & createChannel (
epicsGuard < epicsMutex > &, const char * pChannelName,
cacChannelNotify &, cacChannel::priLev pri );
void flush ( epicsGuard < epicsMutex > & );
void eliminateExcessiveSendBacklog (
void eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > &, cacChannel & );
int pendIO ( const double & timeout );
int pendEvent ( const double & timeout );
@@ -304,18 +314,18 @@ public:
unsigned sequenceNumberOfOutstandingIO (
epicsGuard < epicsMutex > & ) const;
unsigned beaconAnomaliesSinceProgramStart () const;
void incrementOutstandingIO (
void incrementOutstandingIO (
epicsGuard < epicsMutex > &, unsigned ioSeqNo );
void decrementOutstandingIO (
void decrementOutstandingIO (
epicsGuard < epicsMutex > &, unsigned ioSeqNo );
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo );
void exception (
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
const char * pFileName, unsigned lineNo );
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op );
void blockForEventAndEnableCallbacks (
void blockForEventAndEnableCallbacks (
epicsEvent & event, const double & timeout );
CASG * lookupCASG ( epicsGuard < epicsMutex > &, unsigned id );
static void installDefaultService ( cacService & );
@@ -325,9 +335,9 @@ public:
// perhaps these should be eliminated in deference to the exception mechanism
int printFormated ( const char * pformat, ... ) const;
int varArgsPrintFormated ( const char * pformat, va_list args ) const;
void signal ( int ca_status, const char * pfilenm,
void signal ( int ca_status, const char * pfilenm,
int lineno, const char * pFormat, ... );
void vSignal ( int ca_status, const char * pfilenm,
void vSignal ( int ca_status, const char * pfilenm,
int lineno, const char *pFormat, va_list args );
bool preemptiveCallbakIsEnabled () const;
void destroyGetCopy ( epicsGuard < epicsMutex > &, getCopy & );
@@ -336,25 +346,27 @@ public:
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
epicsMutex & mutexRef () const;
// legacy C API
template < class T >
void whenThereIsAnExceptionDestroySyncGroupIO ( epicsGuard < epicsMutex > &, T & );
// legacy C API
friend int epicsShareAPI ca_create_channel (
const char * name_str, caCh * conn_func, void * puser,
capri priority, chid * chanptr );
friend int epicsShareAPI ca_clear_channel ( chid pChan );
friend int epicsShareAPI ca_array_get ( chtype type,
friend int epicsShareAPI ca_array_get ( chtype type,
arrayElementCount count, chid pChan, void * pValue );
friend int epicsShareAPI ca_array_get_callback ( chtype type,
friend int epicsShareAPI ca_array_get_callback ( chtype type,
arrayElementCount count, chid pChan,
caEventCallBackFunc *pfunc, void *arg );
friend int epicsShareAPI ca_array_put ( chtype type,
friend int epicsShareAPI ca_array_put ( chtype type,
arrayElementCount count, chid pChan, const void * pValue );
friend int epicsShareAPI ca_array_put_callback ( chtype type,
arrayElementCount count, chid pChan, const void * pValue,
friend int epicsShareAPI ca_array_put_callback ( chtype type,
arrayElementCount count, chid pChan, const void * pValue,
caEventCallBackFunc *pfunc, void *usrarg );
friend int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
friend int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
evid *monixptr );
friend int epicsShareAPI ca_flush_io ();
friend int epicsShareAPI ca_clear_subscription ( evid pMon );
@@ -363,6 +375,17 @@ public:
friend int epicsShareAPI ca_sg_block ( const CA_SYNC_GID gid, ca_real timeout );
friend int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid );
friend int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid );
friend int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid,
chtype type, arrayElementCount count,
chid pChan, void *pValue );
friend int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid,
chtype type, arrayElementCount count,
chid pChan, const void *pValue );
friend int ca_sync_group_destroy ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard,
ca_client_context & cac, const CA_SYNC_GID gid );
friend void sync_group_reset ( ca_client_context & client,
CASG & sg );
// exceptions
class noSocket {};
@@ -375,11 +398,11 @@ private:
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > subscriptionFreeList;
tsFreeList < struct CASG, 128, epicsMutexNOOP > casgFreeList;
mutable epicsMutex mutex;
mutable epicsMutex cbMutex;
mutable epicsMutex cbMutex;
epicsEvent ioDone;
epicsEvent callbackThreadActivityComplete;
epicsThreadId createdByThread;
epics_auto_ptr < epicsGuard < epicsMutex > > pCallbackGuard;
epics_auto_ptr < CallbackGuard > pCallbackGuard;
epics_auto_ptr < cacContext > pServiceContext;
caExceptionHandler * ca_exception_func;
void * ca_exception_arg;
@@ -397,15 +420,15 @@ private:
void attachToClientCtx ();
void callbackProcessingInitiateNotify ();
void callbackProcessingCompleteNotify ();
cacContext & createNetworkContext (
cacContext & createNetworkContext (
epicsMutex & mutualExclusion, epicsMutex & callbackControl );
void _sendWakeupMsg ();
ca_client_context ( const ca_client_context & );
ca_client_context & operator = ( const ca_client_context & );
friend void cacOnceFunc ( void * );
friend void cacExitHandler ( void *);
ca_client_context ( const ca_client_context & );
ca_client_context & operator = ( const ca_client_context & );
friend void cacOnceFunc ( void * );
friend void cacExitHandler ( void *);
static cacService * pDefaultService;
static epicsMutex * pDefaultServiceInstallMutex;
static const unsigned flushBlockThreshold;
@@ -425,7 +448,7 @@ inline unsigned oldChannelNotify::getName (
return this->io.getName ( guard, pBuf, bufLen );
}
inline void oldChannelNotify::show (
inline void oldChannelNotify::show (
epicsGuard < epicsMutex > & guard,
unsigned level ) const
{
@@ -438,58 +461,60 @@ inline void oldChannelNotify::initiateConnect (
this->io.initiateConnect ( guard );
}
inline void oldChannelNotify::ioCancel (
epicsGuard < epicsMutex > & guard,
inline void oldChannelNotify::ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const cacChannel::ioid & id )
{
this->io.ioCancel ( guard, id );
this->io.ioCancel ( callbackGuard, mutualExclusionGuard, id );
}
inline void oldChannelNotify::ioShow (
inline void oldChannelNotify::ioShow (
epicsGuard < epicsMutex > & guard,
const cacChannel::ioid & id, unsigned level ) const
{
this->io.ioShow ( guard, id, level );
}
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
inline void oldChannelNotify::eliminateExcessiveSendBacklog (
epicsGuard < epicsMutex > & guard )
{
this->cacCtx.eliminateExcessiveSendBacklog ( guard, this->io );
}
inline void * oldChannelNotify::operator new ( size_t size,
inline void * oldChannelNotify::operator new ( size_t size,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void oldChannelNotify::operator delete ( void *pCadaver,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & freeList )
inline void oldChannelNotify::operator delete ( void *pCadaver,
tsFreeList < struct oldChannelNotify, 1024, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
#endif
inline void * oldSubscription::operator new ( size_t size,
inline void * oldSubscription::operator new ( size_t size,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void oldSubscription::operator delete ( void *pCadaver,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & freeList )
inline void oldSubscription::operator delete ( void *pCadaver,
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
#endif
inline void oldSubscription::cancel (
epicsGuard < epicsMutex > & guard )
inline void oldSubscription::cancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard )
{
this->chan.ioCancel ( guard, this->id );
this->chan.ioCancel ( callbackGuard, mutualExclusionGuard, this->id );
}
inline oldChannelNotify & oldSubscription::channel () const
@@ -497,43 +522,43 @@ inline oldChannelNotify & oldSubscription::channel () const
return this->chan;
}
inline void * getCopy::operator new ( size_t size,
inline void * getCopy::operator new ( size_t size,
tsFreeList < class getCopy, 1024, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void getCopy::operator delete ( void *pCadaver,
tsFreeList < class getCopy, 1024, epicsMutexNOOP > & freeList )
inline void getCopy::operator delete ( void *pCadaver,
tsFreeList < class getCopy, 1024, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
#endif
inline void * putCallback::operator new ( size_t size,
inline void * putCallback::operator new ( size_t size,
tsFreeList < class putCallback, 1024, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void putCallback::operator delete ( void * pCadaver,
tsFreeList < class putCallback, 1024, epicsMutexNOOP > & freeList )
inline void putCallback::operator delete ( void * pCadaver,
tsFreeList < class putCallback, 1024, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
#endif
inline void * getCallback::operator new ( size_t size,
inline void * getCallback::operator new ( size_t size,
tsFreeList < class getCallback, 1024, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#ifdef CXX_PLACEMENT_DELETE
inline void getCallback::operator delete ( void * pCadaver,
tsFreeList < class getCallback, 1024, epicsMutexNOOP > & freeList )
inline void getCallback::operator delete ( void * pCadaver,
tsFreeList < class getCallback, 1024, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
@@ -555,5 +580,32 @@ inline unsigned ca_client_context::sequenceNumberOfOutstandingIO (
// perhaps on SMP systems THERE should be lock/unlock around this
return this->ioSeqNo;
}
template < class T >
void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO (
epicsGuard < epicsMutex > & guard, T & io )
{
if ( this->pCallbackGuard.get() &&
this->createdByThread == epicsThreadGetIdSelf () ) {
io.destroy ( *this->pCallbackGuard.get(), guard );
}
else {
// dont reverse the lock hierarchy
epicsGuardRelease < epicsMutex > guardRelease ();
{
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( this->cbMutex );
epicsGuard < epicsMutex > guard ( this->mutex );
io.destroy ( cbGuard, guard );
}
}
}
#endif // ifndef oldAccessh

View File

@@ -5,18 +5,18 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* 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
@@ -43,13 +43,13 @@ extern "C" void cacNoopAccesRightsHandler ( struct access_rights_handler_args )
{
}
oldChannelNotify::oldChannelNotify (
epicsGuard < epicsMutex > & guard, ca_client_context & cacIn,
const char *pName, caCh * pConnCallBackIn,
oldChannelNotify::oldChannelNotify (
epicsGuard < epicsMutex > & guard, ca_client_context & cacIn,
const char *pName, caCh * pConnCallBackIn,
void * pPrivateIn, capri priority ) :
cacCtx ( cacIn ),
io ( cacIn.createChannel ( guard, pName, *this, priority ) ),
pConnCallBack ( pConnCallBackIn ),
cacCtx ( cacIn ),
io ( cacIn.createChannel ( guard, pName, *this, priority ) ),
pConnCallBack ( pConnCallBackIn ),
pPrivate ( pPrivateIn ), pAccessRightsFunc ( cacNoopAccesRightsHandler ),
ioSeqNo ( 0 ), currentlyConnected ( false ), prevConnected ( false )
{
@@ -65,19 +65,20 @@ oldChannelNotify::~oldChannelNotify ()
}
void oldChannelNotify::destructor (
epicsGuard < epicsMutex > & guard )
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & mutexGuard )
{
guard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
this->io.destroy ( guard );
mutexGuard.assertIdenticalMutex ( this->cacCtx.mutexRef () );
this->io.destroy ( cbGuard, mutexGuard );
// no need to worry about a connect preempting here because
// the io (the nciu) has been destroyed above
if ( this->pConnCallBack == 0 && ! this->currentlyConnected ) {
this->cacCtx.decrementOutstandingIO ( guard, this->ioSeqNo );
this->cacCtx.decrementOutstandingIO ( mutexGuard, this->ioSeqNo );
}
this->~oldChannelNotify ();
}
void oldChannelNotify::connectNotify (
void oldChannelNotify::connectNotify (
epicsGuard < epicsMutex > & guard )
{
this->currentlyConnected = true;
@@ -97,7 +98,7 @@ void oldChannelNotify::connectNotify (
}
}
void oldChannelNotify::disconnectNotify (
void oldChannelNotify::disconnectNotify (
epicsGuard < epicsMutex > & guard )
{
this->currentlyConnected = false;
@@ -112,7 +113,7 @@ void oldChannelNotify::disconnectNotify (
}
}
else {
this->cacCtx.incrementOutstandingIO (
this->cacCtx.incrementOutstandingIO (
guard, this->ioSeqNo );
}
}
@@ -123,7 +124,7 @@ void oldChannelNotify::serviceShutdownNotify (
this->disconnectNotify ( guard );
}
void oldChannelNotify::accessRightsNotify (
void oldChannelNotify::accessRightsNotify (
epicsGuard < epicsMutex > & guard, const caAccessRights & ar )
{
struct access_rights_handler_args args;
@@ -137,25 +138,25 @@ void oldChannelNotify::accessRightsNotify (
}
}
void oldChannelNotify::exception (
void oldChannelNotify::exception (
epicsGuard < epicsMutex > & guard, int status, const char * pContext )
{
this->cacCtx.exception ( guard, status, pContext, __FILE__, __LINE__ );
}
void oldChannelNotify::readException (
void oldChannelNotify::readException (
epicsGuard < epicsMutex > & guard, int status, const char *pContext,
unsigned type, arrayElementCount count, void * /* pValue */ )
{
this->cacCtx.exception ( guard, status, pContext,
this->cacCtx.exception ( guard, status, pContext,
__FILE__, __LINE__, *this, type, count, CA_OP_GET );
}
void oldChannelNotify::writeException (
void oldChannelNotify::writeException (
epicsGuard < epicsMutex > & guard, int status, const char *pContext,
unsigned type, arrayElementCount count )
{
this->cacCtx.exception ( guard, status, pContext,
this->cacCtx.exception ( guard, status, pContext,
__FILE__, __LINE__, *this, type, count, CA_OP_PUT );
}
@@ -173,7 +174,7 @@ void oldChannelNotify::operator delete ( void * )
/*
* ca_get_host_name ()
*/
unsigned epicsShareAPI ca_get_host_name (
unsigned epicsShareAPI ca_get_host_name (
chid pChan, char * pBuf, unsigned bufLength )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef() );
@@ -186,7 +187,7 @@ unsigned epicsShareAPI ca_get_host_name (
* !!!! not thread safe !!!!
*
*/
const char * epicsShareAPI ca_host_name (
const char * epicsShareAPI ca_host_name (
chid pChan )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
@@ -196,7 +197,7 @@ const char * epicsShareAPI ca_host_name (
/*
* ca_set_puser ()
*/
void epicsShareAPI ca_set_puser (
void epicsShareAPI ca_set_puser (
chid pChan, void * puser )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
@@ -206,7 +207,7 @@ void epicsShareAPI ca_set_puser (
/*
* ca_get_puser ()
*/
void * epicsShareAPI ca_puser (
void * epicsShareAPI ca_puser (
chid pChan )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
@@ -220,7 +221,7 @@ int epicsShareAPI ca_change_connection_event ( chid pChan, caCh * pfunc )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
if ( ! pChan->currentlyConnected ) {
if ( pfunc ) {
if ( pfunc ) {
if ( ! pChan->pConnCallBack ) {
pChan->cacCtx.decrementOutstandingIO ( guard, pChan->ioSeqNo );
}
@@ -238,7 +239,7 @@ int epicsShareAPI ca_change_connection_event ( chid pChan, caCh * pfunc )
/*
* ca_replace_access_rights_event
*/
int epicsShareAPI ca_replace_access_rights_event (
int epicsShareAPI ca_replace_access_rights_event (
chid pChan, caArh *pfunc )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
@@ -246,11 +247,11 @@ int epicsShareAPI ca_replace_access_rights_event (
// 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
// handler could be called twice here with the same access rights state, but
// that will not upset the application.
pChan->pAccessRightsFunc = pfunc ? pfunc : cacNoopAccesRightsHandler;
caAccessRights tmp = pChan->io.accessRights ( guard );
if ( pChan->currentlyConnected ) {
struct access_rights_handler_args args;
args.chid = pChan;
@@ -265,7 +266,7 @@ int epicsShareAPI ca_replace_access_rights_event (
/*
* ca_array_get ()
*/
int epicsShareAPI ca_array_get ( chtype type,
int epicsShareAPI ca_array_get ( chtype type,
arrayElementCount count, chid pChan, void *pValue )
{
int caStatus;
@@ -279,10 +280,10 @@ int epicsShareAPI ca_array_get ( chtype type,
unsigned tmpType = static_cast < unsigned > ( type );
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog ( guard );
autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
autoPtrFreeList < getCopy, 0x400, epicsMutexNOOP > pNotify
( pChan->getClientCtx().getCopyFreeList,
new ( pChan->getClientCtx().getCopyFreeList )
getCopy ( guard, pChan->getClientCtx(), *pChan,
new ( pChan->getClientCtx().getCopyFreeList )
getCopy ( guard, pChan->getClientCtx(), *pChan,
tmpType, count, pValue ) );
pChan->io.read ( guard, type, count, *pNotify, 0 );
pNotify.release ();
@@ -333,7 +334,7 @@ int epicsShareAPI ca_array_get ( chtype type,
/*
* ca_array_get_callback ()
*/
int epicsShareAPI ca_array_get_callback ( chtype type,
int epicsShareAPI ca_array_get_callback ( chtype type,
arrayElementCount count, chid pChan,
caEventCallBackFunc *pfunc, void *arg )
{
@@ -346,7 +347,7 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
pChan->eliminateExcessiveSendBacklog ( guard );
autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
autoPtrFreeList < getCallback, 0x400, epicsMutexNOOP > pNotify
( pChan->getClientCtx().getCallbackFreeList,
new ( pChan->getClientCtx().getCallbackFreeList )
getCallback ( *pChan, pfunc, arg ) );
@@ -396,9 +397,9 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
return caStatus;
}
void oldChannelNotify::read (
void oldChannelNotify::read (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount count,
unsigned type, arrayElementCount count,
cacReadNotify & notify, cacChannel::ioid * pId )
{
this->io.read ( guard, type, count, notify, pId );
@@ -407,7 +408,7 @@ void oldChannelNotify::read (
/*
* ca_array_put_callback ()
*/
int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
chid pChan, const void *pValue, caEventCallBackFunc *pfunc, void *usrarg )
{
int caStatus;
@@ -468,7 +469,7 @@ int epicsShareAPI ca_array_put_callback ( chtype type, arrayElementCount count,
/*
* ca_array_put ()
*/
int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
chid pChan, const void * pValue )
{
if ( type < 0 ) {
@@ -522,9 +523,9 @@ int epicsShareAPI ca_array_put ( chtype type, arrayElementCount count,
return caStatus;
}
int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
int epicsShareAPI ca_create_subscription (
chtype type, arrayElementCount count, chid pChan,
long mask, caEventCallBackFunc * pCallBack, void * pCallBackArg,
evid * monixptr )
{
if ( type < 0 ) {
@@ -552,7 +553,7 @@ int epicsShareAPI ca_create_subscription (
try {
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
try {
// if this stalls out on a live circuit then an exception
// if this stalls out on a live circuit then an exception
// can be forthcoming which we must ignore (this is a
// special case preserving legacy ca_create_subscription
// behavior)
@@ -562,7 +563,7 @@ int epicsShareAPI ca_create_subscription (
// intentionally ignored (its ok to subscribe when not connected)
}
new ( pChan->getClientCtx().subscriptionFreeList )
oldSubscription (
oldSubscription (
guard, *pChan, pChan->io, tmpType, count, mask,
pCallBack, pCallBackArg, monixptr );
// dont touch object created after above new because
@@ -603,8 +604,8 @@ int epicsShareAPI ca_create_subscription (
}
}
void oldChannelNotify::write (
epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount count,
void oldChannelNotify::write (
epicsGuard < epicsMutex > & guard, unsigned type, arrayElementCount count,
const void * pValue, cacWriteNotify & notify, cacChannel::ioid * pId )
{
this->io.write ( guard, type, count, pValue, notify, pId );
@@ -613,7 +614,7 @@ void oldChannelNotify::write (
/*
* ca_field_type()
*/
short epicsShareAPI ca_field_type ( chid pChan )
short epicsShareAPI ca_field_type ( chid pChan )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
return pChan->io.nativeType ( guard );
@@ -622,7 +623,7 @@ short epicsShareAPI ca_field_type ( chid pChan )
/*
* ca_element_count ()
*/
arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
return pChan->io.nativeElementCount ( guard );
@@ -674,7 +675,7 @@ const char * epicsShareAPI ca_name ( chid pChan )
unsigned epicsShareAPI ca_search_attempts ( chid pChan )
{
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
return pChan->io.searchAttempts ( guard );
}

View File

@@ -29,8 +29,7 @@
template < class T >
class sgAutoPtr {
public:
sgAutoPtr ( epicsGuard < epicsMutex > &,
struct CASG &, tsDLList < syncGroupNotify > & );
sgAutoPtr ( epicsGuard < epicsMutex > &, struct CASG & );
~sgAutoPtr ();
sgAutoPtr < T > & operator = ( T * );
T * operator -> ();
@@ -38,18 +37,16 @@ public:
T * get ();
T * release ();
private:
tsDLList < syncGroupNotify > & list;
T * pNotify;
struct CASG & sg;
epicsGuard < epicsMutex > & guard;
sgAutoPtr & operator = ( const sgAutoPtr & );
sgAutoPtr & operator = ( const sgAutoPtr & );
};
template < class T >
inline sgAutoPtr < T > :: sgAutoPtr (
epicsGuard < epicsMutex > & guardIn,
struct CASG & sgIn, tsDLList < syncGroupNotify > & listIn ) :
list ( listIn ), pNotify ( 0 ), sg ( sgIn ), guard ( guardIn )
epicsGuard < epicsMutex > & guardIn, struct CASG & sgIn ) :
pNotify ( 0 ), sg ( sgIn ), guard ( guardIn )
{
}
@@ -57,8 +54,9 @@ template < class T >
inline sgAutoPtr < T > :: ~sgAutoPtr ()
{
if ( this->pNotify ) {
list.remove ( *this->pNotify );
pNotify->destroy ( this->guard, this->sg );
this->sg.ioPendingList.remove ( *this->pNotify );
this->sg.client.
whenThereIsAnExceptionDestroySyncGroupIO ( this->guard, *this->pNotify );
}
}
@@ -66,11 +64,12 @@ template < class T >
inline sgAutoPtr < T > & sgAutoPtr < T > :: operator = ( T * pNotifyIn )
{
if ( this->pNotify ) {
list.remove ( *this->pNotify );
pNotify->destroy ( this->guard, this->sg );
this->sg.ioPendingList.remove ( *this->pNotify );
this->sg.client.
whenThereIsAnExceptionDestroySyncGroupIO ( this->guard, *this->pNotify );
}
this->pNotify = pNotifyIn;
list.add ( *this->pNotify );
this->sg.ioPendingList.add ( *this->pNotify );
return *this;
}

View File

@@ -5,24 +5,24 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
/*
*
*
*
* 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
*/
#ifndef syncGrouph
#ifndef syncGrouph
#define syncGrouph
#ifdef epicsExportSharedSymbols
@@ -46,152 +46,153 @@
static const unsigned CASG_MAGIC = 0xFAB4CAFE;
// used to control access to CASG's recycle routines which
// should only be indirectly invoked by CASG when its lock
// is applied
class casgRecycle {
public:
virtual void recycleSyncGroupWriteNotify (
epicsGuard < epicsMutex > &, class syncGroupWriteNotify & io ) = 0;
virtual void recycleSyncGroupReadNotify (
epicsGuard < epicsMutex > &, class syncGroupReadNotify & io ) = 0;
protected:
virtual ~casgRecycle ();
};
class syncGroupNotify : public tsDLNode < syncGroupNotify > {
public:
syncGroupNotify ();
virtual void destroy (
epicsGuard < epicsMutex > & guard,
casgRecycle & ) = 0;
virtual bool ioPending (
virtual void destroy (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard ) = 0;
virtual bool ioPending (
epicsGuard < epicsMutex > & guard ) = 0;
virtual void cancel (
epicsGuard < epicsMutex > & guard ) = 0;
virtual void show (
epicsGuard < epicsMutex > &,
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
virtual void show (
epicsGuard < epicsMutex > &,
unsigned level ) const = 0;
protected:
virtual ~syncGroupNotify ();
syncGroupNotify ( const syncGroupNotify & );
syncGroupNotify & operator = ( const syncGroupNotify & );
virtual ~syncGroupNotify ();
syncGroupNotify ( const syncGroupNotify & );
syncGroupNotify & operator = ( const syncGroupNotify & );
};
struct CASG;
class syncGroupReadNotify : public syncGroupNotify, public cacReadNotify {
public:
static syncGroupReadNotify * factory (
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &,
struct CASG &, chid, void *pValueIn );
void destroy (
epicsGuard < epicsMutex > & guard,
casgRecycle & );
bool ioPending (
typedef void ( CASG :: * PRecycleFunc )
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
static syncGroupReadNotify * factory (
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &,
CASG &, PRecycleFunc, chid, void *pValueIn );
void destroy (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void begin ( epicsGuard < epicsMutex > &,
bool ioPending (
epicsGuard < epicsMutex > & guard );
void begin ( epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count );
void cancel (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
protected:
syncGroupReadNotify ( struct CASG & sgIn, chid, void * pValueIn );
syncGroupReadNotify ( CASG & sgIn, PRecycleFunc, chid, void * pValueIn );
virtual ~syncGroupReadNotify ();
private:
chid chan;
struct CASG & sg;
PRecycleFunc pRecycleFunc;
CASG & sg;
void * pValue;
const unsigned magic;
cacChannel::ioid id;
bool idIsValid;
bool ioComplete;
void operator delete ( void * );
void * operator new ( size_t,
void * operator new ( size_t,
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & ))
void completion (
epicsGuard < epicsMutex > &, unsigned type,
epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pData );
void exception (
epicsGuard < epicsMutex > &, int status,
epicsGuard < epicsMutex > &, int status,
const char * pContext, unsigned type, arrayElementCount count );
syncGroupReadNotify ( const syncGroupReadNotify & );
syncGroupReadNotify & operator = ( const syncGroupReadNotify & );
syncGroupReadNotify ( const syncGroupReadNotify & );
syncGroupReadNotify & operator = ( const syncGroupReadNotify & );
};
class syncGroupWriteNotify : public syncGroupNotify, public cacWriteNotify {
public:
static syncGroupWriteNotify * factory (
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &,
struct CASG &, chid );
void destroy (
epicsGuard < epicsMutex > & guard,
casgRecycle & );
bool ioPending (
typedef void ( CASG :: * PRecycleFunc )
( epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
static syncGroupWriteNotify * factory (
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &,
CASG &, PRecycleFunc, chid );
void destroy (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void begin ( epicsGuard < epicsMutex > &, unsigned type,
bool ioPending (
epicsGuard < epicsMutex > & guard );
void begin ( epicsGuard < epicsMutex > &, unsigned type,
arrayElementCount count, const void * pValueIn );
void cancel (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
protected:
syncGroupWriteNotify ( struct CASG &, chid );
syncGroupWriteNotify ( struct CASG &, PRecycleFunc, chid );
virtual ~syncGroupWriteNotify (); // allocate only from pool
private:
chid chan;
struct CASG & sg;
PRecycleFunc pRecycleFunc;
CASG & sg;
const unsigned magic;
cacChannel::ioid id;
bool idIsValid;
bool ioComplete;
void operator delete ( void * );
void * operator new ( size_t,
void * operator new ( size_t,
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > & ))
void completion ( epicsGuard < epicsMutex > & );
void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext,
void exception (
epicsGuard < epicsMutex > &, int status, const char *pContext,
unsigned type, arrayElementCount count );
syncGroupWriteNotify ( const syncGroupWriteNotify & );
syncGroupWriteNotify & operator = ( const syncGroupWriteNotify & );
syncGroupWriteNotify ( const syncGroupWriteNotify & );
syncGroupWriteNotify & operator = ( const syncGroupWriteNotify & );
};
struct ca_client_context;
template < class T > class sgAutoPtr;
struct CASG : public chronIntIdRes < CASG >, private casgRecycle {
struct CASG : public chronIntIdRes < CASG > {
public:
CASG ( epicsGuard < epicsMutex > &, ca_client_context & cacIn );
void destructor (
void destructor (
CallbackGuard &,
epicsGuard < epicsMutex > & guard );
bool ioComplete (
bool ioComplete (
CallbackGuard &,
epicsGuard < epicsMutex > & guard );
bool verify ( epicsGuard < epicsMutex > & ) const;
int block ( epicsGuard < epicsMutex > * pcbGuard,
int block ( epicsGuard < epicsMutex > * pcbGuard,
epicsGuard < epicsMutex > & guard, double timeout );
void reset ( epicsGuard < epicsMutex > & guard );
void reset ( CallbackGuard &, epicsGuard < epicsMutex > & );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
void show ( unsigned level ) const;
void get ( epicsGuard < epicsMutex > &, chid pChan,
unsigned type, arrayElementCount count, void * pValue );
void put ( epicsGuard < epicsMutex > &, chid pChan,
unsigned type, arrayElementCount count, const void * pValue );
void completionNotify (
void completionNotify (
epicsGuard < epicsMutex > &, syncGroupNotify & );
int printFormated ( const char * pFormat, ... );
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo );
void exception (
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
const char * pFileName, unsigned lineNo );
void exception (
epicsGuard < epicsMutex > &, int status, const char * pContext,
const char * pFileName, unsigned lineNo, oldChannelNotify & chan,
unsigned type, arrayElementCount count, unsigned op );
void * operator new ( size_t size,
void * operator new ( size_t size,
tsFreeList < struct CASG, 128, epicsMutexNOOP > & );
epicsPlacementDeleteOperator (( void *,
epicsPlacementDeleteOperator (( void *,
tsFreeList < struct CASG, 128, epicsMutexNOOP > & ))
private:
tsDLList < syncGroupNotify > ioPendingList;
tsDLList < syncGroupNotify > ioCompletedList;
@@ -200,18 +201,20 @@ private:
unsigned magic;
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > freeListReadOP;
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > freeListWriteOP;
void recycleSyncGroupWriteNotify (
epicsGuard < epicsMutex > &, syncGroupWriteNotify & io );
void recycleSyncGroupReadNotify (
epicsGuard < epicsMutex > &, syncGroupReadNotify & io );
void destroyPendingIO (
void destroyPendingIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void destroyCompletedIO (
void destroyCompletedIO (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard );
void recycleReadNotifyIO ( epicsGuard < epicsMutex > &,
syncGroupReadNotify & );
void recycleWriteNotifyIO ( epicsGuard < epicsMutex > &,
syncGroupWriteNotify & );
CASG ( const CASG & );
CASG & operator = ( const CASG & );
CASG ( const CASG & );
CASG & operator = ( const CASG & );
void operator delete ( void * );
@@ -248,27 +251,27 @@ inline void boolFlagManager::release ()
this->pBool = 0;
}
inline void * CASG::operator new ( size_t size,
inline void * CASG::operator new ( size_t size,
tsFreeList < struct CASG, 128, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#if defined ( CXX_PLACEMENT_DELETE )
inline void CASG::operator delete ( void * pCadaver,
tsFreeList < struct CASG, 128, epicsMutexNOOP > & freeList )
inline void CASG::operator delete ( void * pCadaver,
tsFreeList < struct CASG, 128, epicsMutexNOOP > & freeList )
{
freeList.release ( pCadaver );
}
#endif
inline bool syncGroupWriteNotify::ioPending (
inline bool syncGroupWriteNotify::ioPending (
epicsGuard < epicsMutex > & /* guard */ )
{
return ! this->ioComplete;
}
inline bool syncGroupReadNotify::ioPending (
inline bool syncGroupReadNotify::ioPending (
epicsGuard < epicsMutex > & /* guard */ )
{
return ! this->ioComplete;

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -26,16 +26,18 @@
#include "syncGroup.h"
#include "oldAccess.h"
syncGroupReadNotify::syncGroupReadNotify (
CASG & sgIn, chid pChan, void * pValueIn ) :
chan ( pChan ), sg ( sgIn ), pValue ( pValueIn ),
magic ( CASG_MAGIC ), id ( 0u ),
syncGroupReadNotify::syncGroupReadNotify (
CASG & sgIn, PRecycleFunc pRecycleFuncIn,
chid pChan, void * pValueIn ) :
chan ( pChan ), pRecycleFunc ( pRecycleFuncIn ),
sg ( sgIn ), pValue ( pValueIn ),
magic ( CASG_MAGIC ), id ( 0u ),
idIsValid ( false ), ioComplete ( false )
{
}
void syncGroupReadNotify::begin (
epicsGuard < epicsMutex > & guard,
void syncGroupReadNotify::begin (
epicsGuard < epicsMutex > & guard,
unsigned type, arrayElementCount count )
{
this->chan->eliminateExcessiveSendBacklog ( guard );
@@ -45,28 +47,31 @@ void syncGroupReadNotify::begin (
mgr.release ();
}
void syncGroupReadNotify::cancel (
epicsGuard < epicsMutex > & guard )
void syncGroupReadNotify::cancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExcusionGuard )
{
if ( this->idIsValid ) {
this->chan->ioCancel ( guard, this->id );
this->chan->ioCancel ( callbackGuard, mutualExcusionGuard, this->id );
this->idIsValid = false;
}
}
syncGroupReadNotify * syncGroupReadNotify::factory (
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & freeList,
struct CASG & sg, chid chan, void * pValueIn )
syncGroupReadNotify * syncGroupReadNotify::factory (
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & freeList,
struct CASG & sg, PRecycleFunc pRecycleFunc, chid chan, void * pValueIn )
{
return new ( freeList )
syncGroupReadNotify ( sg, chan, pValueIn );
syncGroupReadNotify ( sg, pRecycleFunc, chan, pValueIn );
}
void syncGroupReadNotify::destroy (
epicsGuard < epicsMutex > & guard, casgRecycle & recycle )
void syncGroupReadNotify::destroy (
CallbackGuard &,
epicsGuard < epicsMutex > & guard )
{
CASG & sgRef ( this->sg );
this->~syncGroupReadNotify ();
recycle.recycleSyncGroupReadNotify ( guard, *this );
( sgRef.*pRecycleFunc ) ( guard, *this );
}
syncGroupReadNotify::~syncGroupReadNotify ()
@@ -75,11 +80,11 @@ syncGroupReadNotify::~syncGroupReadNotify ()
}
void syncGroupReadNotify::completion (
epicsGuard < epicsMutex > & guard, unsigned type,
epicsGuard < epicsMutex > & guard, unsigned type,
arrayElementCount count, const void * pData )
{
if ( this->magic != CASG_MAGIC ) {
this->sg.printFormated (
this->sg.printFormated (
"cac: sync group io_complete(): bad sync grp op magic number?\n" );
return;
}
@@ -94,16 +99,16 @@ void syncGroupReadNotify::completion (
}
void syncGroupReadNotify::exception (
epicsGuard < epicsMutex > & guard, int status, const char * pContext,
epicsGuard < epicsMutex > & guard, int status, const char * pContext,
unsigned type, arrayElementCount count )
{
if ( this->magic != CASG_MAGIC ) {
this->sg.printFormated (
this->sg.printFormated (
"cac: sync group io_complete(): bad sync grp op magic number?\n" );
return;
}
this->idIsValid = false;
this->sg.exception ( guard, status, pContext,
this->sg.exception ( guard, status, pContext,
__FILE__, __LINE__, *this->chan, type, count, CA_OP_GET );
//
// This notify is left installed at this point as a place holder indicating that
@@ -112,7 +117,7 @@ void syncGroupReadNotify::exception (
//
}
void syncGroupReadNotify::show (
void syncGroupReadNotify::show (
epicsGuard < epicsMutex > &, unsigned level ) const
{
::printf ( "pending sg read op: pVal=%p\n", this->pValue );
@@ -133,15 +138,15 @@ void syncGroupReadNotify::operator delete ( void * )
__FILE__, __LINE__ );
}
void * syncGroupReadNotify::operator new ( size_t size,
void * syncGroupReadNotify::operator new ( size_t size,
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#if defined ( CXX_PLACEMENT_DELETE )
void syncGroupReadNotify::operator delete ( void *pCadaver,
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &freeList )
void syncGroupReadNotify::operator delete ( void *pCadaver,
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &freeList )
{
freeList.release ( pCadaver );
}

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -26,45 +26,50 @@
#include "syncGroup.h"
#include "oldAccess.h"
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn, chid pChan ) :
chan ( pChan ), sg ( sgIn ), magic ( CASG_MAGIC ),
id ( 0u ), idIsValid ( false ), ioComplete ( false )
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn,
PRecycleFunc pRecycleFuncIn, chid pChan ) :
chan ( pChan ), pRecycleFunc ( pRecycleFuncIn ),
sg ( sgIn ), magic ( CASG_MAGIC ),
id ( 0u ), idIsValid ( false ), ioComplete ( false )
{
}
void syncGroupWriteNotify::begin (
epicsGuard < epicsMutex > & guard, unsigned type,
void syncGroupWriteNotify::begin (
epicsGuard < epicsMutex > & guard, unsigned type,
arrayElementCount count, const void * pValueIn )
{
this->chan->eliminateExcessiveSendBacklog ( guard );
this->ioComplete = false;
boolFlagManager mgr ( this->idIsValid );
this->chan->write ( guard, type, count,
this->chan->write ( guard, type, count,
pValueIn, *this, &this->id );
mgr.release ();
}
void syncGroupWriteNotify::cancel (
epicsGuard < epicsMutex > & guard )
void syncGroupWriteNotify::cancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExcusionGuard )
{
if ( this->idIsValid ) {
this->chan->ioCancel ( guard, this->id );
this->chan->ioCancel ( callbackGuard, mutualExcusionGuard, this->id );
this->idIsValid = false;
}
}
syncGroupWriteNotify * syncGroupWriteNotify::factory (
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &freeList,
struct CASG & sg, chid chan )
syncGroupWriteNotify * syncGroupWriteNotify::factory (
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &freeList,
struct CASG & sg, PRecycleFunc pRecycleFunc, chid chan )
{
return new ( freeList ) syncGroupWriteNotify ( sg, chan );
return new ( freeList ) syncGroupWriteNotify ( sg, pRecycleFunc, chan );
}
void syncGroupWriteNotify::destroy (
epicsGuard < epicsMutex > & guard, casgRecycle & recycle )
void syncGroupWriteNotify::destroy (
CallbackGuard &,
epicsGuard < epicsMutex > & guard )
{
CASG & sgRef ( this->sg );
this->~syncGroupWriteNotify ();
recycle.recycleSyncGroupWriteNotify ( guard, *this );
( sgRef.*pRecycleFunc ) ( guard, *this );
}
syncGroupWriteNotify::~syncGroupWriteNotify ()
@@ -72,7 +77,7 @@ syncGroupWriteNotify::~syncGroupWriteNotify ()
assert ( ! this->idIsValid );
}
void syncGroupWriteNotify::completion (
void syncGroupWriteNotify::completion (
epicsGuard < epicsMutex > & guard )
{
if ( this->magic != CASG_MAGIC ) {
@@ -85,14 +90,14 @@ void syncGroupWriteNotify::completion (
}
void syncGroupWriteNotify::exception (
epicsGuard < epicsMutex > & guard,
epicsGuard < epicsMutex > & guard,
int status, const char *pContext, unsigned type, arrayElementCount count )
{
if ( this->magic != CASG_MAGIC ) {
this->sg.printFormated ( "cac: sync group io_complete(): bad sync grp op magic number?\n" );
return;
}
this->sg.exception ( guard, status, pContext,
this->sg.exception ( guard, status, pContext,
__FILE__, __LINE__, *this->chan, type, count, CA_OP_PUT );
this->idIsValid = false;
//
@@ -102,7 +107,7 @@ void syncGroupWriteNotify::exception (
//
}
void syncGroupWriteNotify::show (
void syncGroupWriteNotify::show (
epicsGuard < epicsMutex > &, unsigned level ) const
{
::printf ( "pending write sg op\n" );
@@ -123,15 +128,15 @@ void syncGroupWriteNotify::operator delete ( void * )
__FILE__, __LINE__ );
}
void * syncGroupWriteNotify::operator new ( size_t size,
void * syncGroupWriteNotify::operator new ( size_t size,
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > & freeList )
{
return freeList.allocate ( size );
}
#if defined ( CXX_PLACEMENT_DELETE )
void syncGroupWriteNotify::operator delete ( void *pCadaver,
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &freeList )
void syncGroupWriteNotify::operator delete ( void *pCadaver,
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &freeList )
{
freeList.release ( pCadaver );
}

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author: Jeffrey O. Hill
@@ -48,6 +48,22 @@ extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid )
}
}
int ca_sync_group_destroy ( CallbackGuard & cbGuard, epicsGuard < epicsMutex > & guard,
ca_client_context & cac, const CA_SYNC_GID gid )
{
int caStatus;
CASG * pcasg = cac.lookupCASG ( guard, gid );
if ( pcasg ) {
pcasg->destructor ( cbGuard, guard );
cac.casgFreeList.release ( pcasg );
caStatus = ECA_NORMAL;
}
else {
caStatus = ECA_BADSYNCGRP;
}
return caStatus;
}
/*
* ca_sg_delete()
*/
@@ -56,42 +72,80 @@ extern "C" int epicsShareAPI ca_sg_delete ( const CA_SYNC_GID gid )
ca_client_context * pcac;
int caStatus = fetchClientContext ( & pcac );
if ( caStatus == ECA_NORMAL ) {
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
CASG * pcasg = pcac->lookupCASG ( guard, gid );
if ( pcasg ) {
pcasg->destructor ( guard );
pcac->casgFreeList.release ( pcasg );
if ( pcac->pCallbackGuard.get() &&
pcac->createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( pcac->mutex );
caStatus = ca_sync_group_destroy ( *pcac->pCallbackGuard.get(),
guard, *pcac, gid );
}
else {
caStatus = ECA_BADSYNCGRP;
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( pcac->cbMutex );
epicsGuard < epicsMutex > guard ( pcac->mutex );
caStatus = ca_sync_group_destroy ( cbGuard, guard, *pcac, gid );
}
}
return caStatus;
}
void sync_group_reset ( ca_client_context & client, CASG & sg )
{
if ( client.pCallbackGuard.get() &&
client.createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( client.mutex );
sg.reset ( *client.pCallbackGuard.get(), guard );
}
else {
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( client.cbMutex );
epicsGuard < epicsMutex > guard ( client.mutex );
sg.reset ( cbGuard, guard );
}
}
//
// ca_sg_block ()
//
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! This routine is only visible in the old interface - or in a new ST interface.
// !!!! In the old interface we restrict thread attach so that calls from threads
// !!!! other than the initializing thread are not allowed if preemptive callback
// !!!! is disabled. This prevents the preemptive callback lock from being released
// !!!! by other threads than the one that locked it.
//
extern "C" int epicsShareAPI ca_sg_block (
extern "C" int epicsShareAPI ca_sg_block (
const CA_SYNC_GID gid, ca_real timeout )
{
ca_client_context *pcac;
int status = fetchClientContext ( &pcac );
if ( status == ECA_NORMAL ) {
epicsGuard < epicsMutex > guard ( pcac->mutex );
CASG * pcasg = pcac->lookupCASG ( guard, gid );
if ( ! pcasg ) {
status = ECA_BADSYNCGRP;
CASG * pcasg;
{
epicsGuard < epicsMutex > guard ( pcac->mutex );
pcasg = pcac->lookupCASG ( guard, gid );
if ( pcasg ) {
status = pcasg->block (
pcac->pCallbackGuard.get (), guard, timeout );
}
else {
status = ECA_BADSYNCGRP;
}
}
else {
status = pcasg->block (
pcac->pCallbackGuard.get (), guard, timeout );
if ( pcasg ) {
sync_group_reset ( *pcac, *pcasg );
}
}
return status;
@@ -105,10 +159,14 @@ extern "C" int epicsShareAPI ca_sg_reset ( const CA_SYNC_GID gid )
ca_client_context *pcac;
int caStatus = fetchClientContext (&pcac);
if ( caStatus == ECA_NORMAL ) {
epicsGuard < epicsMutex > guard ( pcac->mutex );
CASG * pcasg = pcac->lookupCASG ( guard, gid );
CASG * pcasg;
{
epicsGuard < epicsMutex > guard ( pcac->mutex );
pcasg = pcac->lookupCASG ( guard, gid );
}
if ( pcasg ) {
pcasg->reset ( guard );
sync_group_reset ( *pcac, *pcasg );
caStatus = ECA_NORMAL;
}
else {
caStatus = ECA_BADSYNCGRP;
@@ -151,7 +209,26 @@ extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid )
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
CASG * pcasg = pcac->lookupCASG ( guard, gid );
if ( pcasg ) {
if ( pcasg->ioComplete ( guard ) ) {
bool isComplete;
if ( pcac->pCallbackGuard.get() &&
pcac->createdByThread == epicsThreadGetIdSelf () ) {
epicsGuard < epicsMutex > guard ( pcac->mutex );
isComplete = pcasg->ioComplete ( *pcac->pCallbackGuard.get(), guard );
}
else {
//
// we will definately stall out here if all of the
// following are true
//
// o user creates non-preemtive mode client library context
// o user doesnt periodically call a ca function
// o user calls this function from an auxiillary thread
//
CallbackGuard cbGuard ( pcac->cbMutex );
epicsGuard < epicsMutex > guard ( pcac->mutex );
isComplete = pcasg->ioComplete ( cbGuard, guard );
}
if ( isComplete ) {
caStatus = ECA_IODONE;
}
else{
@@ -172,17 +249,14 @@ extern "C" int epicsShareAPI ca_sg_array_put ( const CA_SYNC_GID gid, chtype typ
arrayElementCount count, chid pChan, const void *pValue )
{
ca_client_context *pcac;
CASG *pcasg;
int caStatus;
caStatus = fetchClientContext ( &pcac );
int caStatus = fetchClientContext ( &pcac );
if ( caStatus != ECA_NORMAL ) {
return caStatus;
}
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
pcasg = pcac->lookupCASG ( guard, gid );
CASG * const pcasg = pcac->lookupCASG ( guard, gid );
if ( ! pcasg ) {
return ECA_BADSYNCGRP;
}
@@ -237,17 +311,14 @@ extern "C" int epicsShareAPI ca_sg_array_get ( const CA_SYNC_GID gid, chtype typ
arrayElementCount count, chid pChan, void *pValue )
{
ca_client_context *pcac;
CASG *pcasg;
int caStatus;
caStatus = fetchClientContext ( &pcac );
int caStatus = fetchClientContext ( &pcac );
if ( caStatus != ECA_NORMAL ) {
return caStatus;
}
epicsGuard < epicsMutex > guard ( pcac->mutexRef() );
pcasg = pcac->lookupCASG ( guard, gid );
CASG * const pcasg = pcac->lookupCASG ( guard, gid );
if ( ! pcasg ) {
return ECA_BADSYNCGRP;
}

View File

@@ -87,9 +87,9 @@ public:
epicsGuard < epicsMutex > &, epicsMutex &,
dbContext &, dbChannelIO &, struct dbChannel *, cacStateNotify &,
unsigned type, unsigned long count, unsigned mask, dbEventCtx );
void destructor ( epicsGuard < epicsMutex > & );
void unsubscribe ( epicsGuard < epicsMutex > & );
void channelDeleteException ( epicsGuard < epicsMutex > & );
void destructor ( CallbackGuard &, epicsGuard < epicsMutex > & );
void unsubscribe ( CallbackGuard &, epicsGuard < epicsMutex > & );
void channelDeleteException ( CallbackGuard &, epicsGuard < epicsMutex > & );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
void show ( unsigned level ) const;
void * operator new ( size_t size,
@@ -165,7 +165,7 @@ public:
dbContext ( epicsMutex & cbMutex, epicsMutex & mutex,
cacContextNotify & notify );
virtual ~dbContext ();
void destroyChannel ( epicsGuard < epicsMutex > &, dbChannelIO & );
void destroyChannel ( CallbackGuard &,epicsGuard < epicsMutex > &, dbChannelIO & );
void callReadNotify ( epicsGuard < epicsMutex > &,
struct dbChannel * dbch, unsigned type, unsigned long count,
cacReadNotify & notify );
@@ -182,9 +182,9 @@ public:
cacWriteNotify & notify, cacChannel::ioid * pId );
void show ( unsigned level ) const;
void showAllIO ( const dbChannelIO & chan, unsigned level ) const;
void destroyAllIO (
epicsGuard < epicsMutex > &, dbChannelIO & chan );
void ioCancel ( epicsGuard < epicsMutex > &,
void destroyAllIO ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > &, dbChannelIO & chan );
void ioCancel ( CallbackGuard &, epicsGuard < epicsMutex > &,
dbChannelIO & chan, const cacChannel::ioid &id );
void ioShow ( epicsGuard < epicsMutex > &,
const cacChannel::ioid & id, unsigned level ) const;

View File

@@ -58,19 +58,21 @@ dbChannelIO::~dbChannelIO ()
{
}
void dbChannelIO::destructor ( epicsGuard < epicsMutex > & guard )
void dbChannelIO::destructor ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
this->serviceIO.destroyAllIO ( guard, *this );
this->serviceIO.destroyAllIO ( cbGuard, guard, *this );
dbChannelDelete ( this->dbch );
this->~dbChannelIO ();
}
void dbChannelIO::destroy (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
this->serviceIO.destroyChannel ( guard, *this );
this->serviceIO.destroyChannel ( cbGuard, guard, *this );
// don't access this pointer after above call because
// object no longer exists
}
@@ -130,11 +132,12 @@ void dbChannelIO::subscribe (
}
void dbChannelIO::ioCancel (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & id )
{
mutualExclusionGuard.assertIdenticalMutex ( this->mutex );
this->serviceIO.ioCancel ( mutualExclusionGuard, *this, id );
this->serviceIO.ioCancel ( cbGuard, mutualExclusionGuard, *this, id );
}
void dbChannelIO::ioShow (

View File

@@ -48,8 +48,10 @@ public:
epicsMutex &, cacChannelNotify &,
dbChannel *, dbContext & );
void destructor (
CallbackGuard &,
epicsGuard < epicsMutex > & );
void destroy (
CallbackGuard &,
epicsGuard < epicsMutex > & mutualExclusionGuard );
void callReadNotify (
epicsGuard < epicsMutex > &,
@@ -99,7 +101,8 @@ private:
unsigned type, unsigned long count,
unsigned mask, cacStateNotify &notify, ioid * );
void ioCancel (
epicsGuard < epicsMutex > & mutualExclusionGuard,
CallbackGuard &,
epicsGuard < epicsMutex > &,
const ioid & );
void ioShow (
epicsGuard < epicsMutex > &,
@@ -108,8 +111,8 @@ private:
epicsGuard < epicsMutex > & ) const;
unsigned long nativeElementCount (
epicsGuard < epicsMutex > & ) const;
dbChannelIO ( const dbChannelIO & );
dbChannelIO & operator = ( const dbChannelIO & );
dbChannelIO ( const dbChannelIO & );
dbChannelIO & operator = ( const dbChannelIO & );
void operator delete ( void * );
};

View File

@@ -120,18 +120,20 @@ cacChannel & dbContext::createChannel (
}
void dbContext::destroyChannel (
epicsGuard < epicsMutex > & guard, dbChannelIO & chan )
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard,
dbChannelIO & chan )
{
guard.assertIdenticalMutex ( this->mutex );
if ( chan.dbContextPrivateListOfIO::pBlocker ) {
this->ioTable.remove ( *chan.dbContextPrivateListOfIO::pBlocker );
chan.dbContextPrivateListOfIO::pBlocker->destructor ( guard );
chan.dbContextPrivateListOfIO::pBlocker->destructor ( cbGuard, guard );
this->dbPutNotifyBlockerFreeList.release ( chan.dbContextPrivateListOfIO::pBlocker );
chan.dbContextPrivateListOfIO::pBlocker = 0;
}
chan.destructor ( guard );
chan.destructor ( cbGuard, guard );
this->dbChannelIOFreeList.release ( & chan );
}
@@ -270,7 +272,9 @@ void dbContext::initiatePutNotify (
}
void dbContext::destroyAllIO (
epicsGuard < epicsMutex > & guard, dbChannelIO & chan )
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard,
dbChannelIO & chan )
{
guard.assertIdenticalMutex ( this->mutex );
dbSubscriptionIO * pIO;
@@ -287,24 +291,24 @@ void dbContext::destroyAllIO (
while ( ( pIO = tmp.get() ) ) {
// This prevents a db event callback from coming
// through after the notify IO is deleted
pIO->unsubscribe ( guard );
pIO->unsubscribe ( cbGuard, guard );
// If they call ioCancel() here it will be ignored
// because the IO has been unregistered above.
pIO->channelDeleteException ( guard );
pIO->destructor ( guard );
pIO->channelDeleteException ( cbGuard, guard );
pIO->destructor ( cbGuard, guard );
this->dbSubscriptionIOFreeList.release ( pIO );
}
if ( chan.dbContextPrivateListOfIO::pBlocker ) {
chan.dbContextPrivateListOfIO::pBlocker->destructor ( guard );
chan.dbContextPrivateListOfIO::pBlocker->destructor ( cbGuard, guard );
this->dbPutNotifyBlockerFreeList.release ( chan.dbContextPrivateListOfIO::pBlocker );
chan.dbContextPrivateListOfIO::pBlocker = 0;
}
}
void dbContext::ioCancel (
epicsGuard < epicsMutex > & guard, dbChannelIO & chan,
const cacChannel::ioid &id )
CallbackGuard & cbGuard, epicsGuard < epicsMutex > & guard,
dbChannelIO & chan, const cacChannel::ioid &id )
{
guard.assertIdenticalMutex ( this->mutex );
dbBaseIO * pIO = this->ioTable.remove ( id );
@@ -312,13 +316,13 @@ void dbContext::ioCancel (
dbSubscriptionIO *pSIO = pIO->isSubscription ();
if ( pSIO ) {
chan.dbContextPrivateListOfIO::eventq.remove ( *pSIO );
pSIO->unsubscribe ( guard );
pSIO->channelDeleteException ( guard );
pSIO->destructor ( guard );
pSIO->unsubscribe ( cbGuard, guard );
pSIO->channelDeleteException ( cbGuard, guard );
pSIO->destructor ( cbGuard, guard );
this->dbSubscriptionIOFreeList.release ( pSIO );
}
else if ( pIO == chan.dbContextPrivateListOfIO::pBlocker ) {
chan.dbContextPrivateListOfIO::pBlocker->cancel ( guard );
chan.dbContextPrivateListOfIO::pBlocker->cancel ( cbGuard, guard );
}
else {
errlogPrintf ( "dbContext::ioCancel() unrecognized IO was probably leaked or not canceled\n" );

View File

@@ -58,10 +58,11 @@ dbPutNotifyBlocker::~dbPutNotifyBlocker ()
{
}
void dbPutNotifyBlocker::destructor ( epicsGuard < epicsMutex > & guard )
void dbPutNotifyBlocker::destructor ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
this->cancel ( guard );
this->cancel ( cbGuard, guard );
if ( this->maxValueSize > sizeof ( this->dbrScalarValue ) ) {
char * pBuf = static_cast < char * > ( this->pbuffer );
delete [] pBuf;
@@ -70,6 +71,7 @@ void dbPutNotifyBlocker::destructor ( epicsGuard < epicsMutex > & guard )
}
void dbPutNotifyBlocker::cancel (
CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );

View File

@@ -42,11 +42,11 @@
class dbPutNotifyBlocker : public dbBaseIO {
public:
dbPutNotifyBlocker ( epicsMutex & );
void destructor ( epicsGuard < epicsMutex > & );
void destructor ( CallbackGuard &, epicsGuard < epicsMutex > & );
void initiatePutNotify ( epicsGuard < epicsMutex > &,
cacWriteNotify &, struct dbChannel *,
unsigned type, unsigned long count, const void * pValue );
void cancel ( epicsGuard < epicsMutex > & );
void cancel ( CallbackGuard &, epicsGuard < epicsMutex > & );
void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
void show ( unsigned level ) const;
void * operator new ( size_t size,

View File

@@ -66,14 +66,15 @@ dbSubscriptionIO::~dbSubscriptionIO ()
{
}
void dbSubscriptionIO::destructor ( epicsGuard < epicsMutex > & guard )
void dbSubscriptionIO::destructor ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
this->~dbSubscriptionIO ();
}
void dbSubscriptionIO::unsubscribe (
epicsGuard < epicsMutex > & guard )
void dbSubscriptionIO::unsubscribe ( CallbackGuard & cbGuard,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
if ( this->es ) {
@@ -87,6 +88,7 @@ void dbSubscriptionIO::unsubscribe (
}
void dbSubscriptionIO::channelDeleteException (
CallbackGuard &,
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );