This commit is contained in:
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 ()
|
||||
|
||||
@@ -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 ¬ify, 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;
|
||||
|
||||
@@ -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 ¬ify, 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 ||
|
||||
|
||||
@@ -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 ¬ify, 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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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 ¬ify, 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 * );
|
||||
};
|
||||
|
||||
|
||||
@@ -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" );
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user