merged in fix for https://bugs.launchpad.net/epics-base/+bug/1179642
also merged in removal of c++ support for old HPUX compiler
This commit is contained in:
+25
-31
@@ -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 )
|
||||
{
|
||||
@@ -38,12 +36,13 @@ CASG::~CASG ()
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -127,36 +126,37 @@ int CASG::block (
|
||||
delay = cur_time - beg_time;
|
||||
}
|
||||
|
||||
this->reset ( guard );
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
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 (
|
||||
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 (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->client.mutexRef() );
|
||||
while ( syncGroupNotify * pNotify = this->ioPendingList.first () ) {
|
||||
pNotify->cancel ( guard );
|
||||
pNotify->cancel ( cbGuard, guard );
|
||||
// cancel must release the guard while
|
||||
// canceling put callbacks so we
|
||||
// must double check list membership
|
||||
@@ -166,7 +166,7 @@ void CASG::destroyPendingIO (
|
||||
else {
|
||||
this->ioCompletedList.remove ( *pNotify );
|
||||
}
|
||||
pNotify->destroy ( guard, *this );
|
||||
pNotify->destroy ( cbGuard, guard );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,9 +224,9 @@ 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 ();
|
||||
}
|
||||
@@ -241,20 +242,20 @@ 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;
|
||||
@@ -295,13 +296,6 @@ void CASG::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * CASG::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void CASG::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
+30
-10
@@ -376,15 +376,35 @@ int epicsShareAPI ca_create_channel (
|
||||
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
|
||||
}
|
||||
pChan->destructor ( guard );
|
||||
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 );
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
@@ -433,7 +453,7 @@ chid epicsShareAPI ca_evid_to_chid ( evid pMon )
|
||||
}
|
||||
|
||||
// extern "C"
|
||||
int epicsShareAPI ca_pend ( ca_real timeout, int early ) // X aCC 361
|
||||
int epicsShareAPI ca_pend ( ca_real timeout, int early )
|
||||
{
|
||||
if ( early ) {
|
||||
return ca_pend_io ( timeout );
|
||||
@@ -516,7 +536,7 @@ int epicsShareAPI ca_flush_io ()
|
||||
/*
|
||||
* CA_TEST_IO ()
|
||||
*/
|
||||
int epicsShareAPI ca_test_io () // X aCC 361
|
||||
int epicsShareAPI ca_test_io ()
|
||||
{
|
||||
ca_client_context *pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
@@ -551,7 +571,7 @@ void epicsShareAPI ca_signal ( long ca_status, const char *message )
|
||||
* (if they call this routine again).
|
||||
*/
|
||||
// extern "C"
|
||||
const char * epicsShareAPI ca_message ( long ca_status ) // X aCC 361
|
||||
const char * epicsShareAPI ca_message ( long ca_status )
|
||||
{
|
||||
unsigned msgNo = CA_EXTRACT_MSG_NO ( ca_status );
|
||||
|
||||
|
||||
+158
@@ -13,6 +13,7 @@
|
||||
* Authors:
|
||||
* Jeff Hill
|
||||
* Murali Shankar - initial versions of verifyMultithreadSubscr
|
||||
* Michael Abbott - initial versions of multiSubscrDestroyNoLateCallbackTest
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1328,6 +1329,158 @@ void test_sync_groups ( chid chan, unsigned interestLevel )
|
||||
showProgressEnd ( interestLevel );
|
||||
}
|
||||
|
||||
#define multiSubscrDestroyNoLateCallbackEventCount 500
|
||||
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData {
|
||||
evid m_id;
|
||||
size_t m_nCallback;
|
||||
int m_callbackIsOk;
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * m_pTestData;
|
||||
};
|
||||
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData {
|
||||
const char * m_pChanName;
|
||||
chid m_chan;
|
||||
epicsMutexId m_mutex;
|
||||
epicsEventId m_testDoneEvent;
|
||||
unsigned m_interestLevel;
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData
|
||||
m_eventData [multiSubscrDestroyNoLateCallbackEventCount];
|
||||
};
|
||||
|
||||
static void noLateCallbackDetect ( struct event_handler_args args )
|
||||
{
|
||||
int callbackIsOk;
|
||||
struct MultiSubscrDestroyNoLateCallbackEventData * const pEventData = args.usr;
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pEventData->m_pTestData->m_mutex );
|
||||
callbackIsOk = pEventData->m_callbackIsOk;
|
||||
pEventData->m_nCallback++;
|
||||
epicsMutexUnlock ( pEventData->m_pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
verify ( callbackIsOk );
|
||||
}
|
||||
|
||||
static void multiSubscrDestroyNoLateCallbackThread ( void * pParm )
|
||||
{
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * const pTestData =
|
||||
( struct MultiSubscrDestroyNoLateCallbackTestData * ) pParm;
|
||||
unsigned i, j;
|
||||
int status;
|
||||
|
||||
status = ca_context_create ( ca_enable_preemptive_callback );
|
||||
verify ( status == ECA_NORMAL );
|
||||
|
||||
status = ca_create_channel ( pTestData->m_pChanName, 0, 0,
|
||||
CA_PRIORITY_DEFAULT, &pTestData->m_chan );
|
||||
status = ca_pend_io ( timeoutToPendIO );
|
||||
SEVCHK ( status, "multiSubscrDestroyLateNoCallbackTest: channel connect failed" );
|
||||
verify ( status == ECA_NORMAL );
|
||||
|
||||
/*
|
||||
* create a set of subscriptions
|
||||
*/
|
||||
for ( i=0; i < 10000; i++ ) {
|
||||
unsigned int priorityOfTestThread;
|
||||
for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
pTestData->m_eventData[j].m_nCallback = 0;
|
||||
pTestData->m_eventData[j].m_callbackIsOk = TRUE;
|
||||
pTestData->m_eventData[j].m_pTestData = pTestData;
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
SEVCHK ( ca_add_event ( DBR_GR_FLOAT, pTestData->m_chan, noLateCallbackDetect,
|
||||
&pTestData->m_eventData[j], &pTestData->m_eventData[j].m_id ) , NULL );
|
||||
}
|
||||
SEVCHK ( ca_flush_io(), NULL );
|
||||
|
||||
/*
|
||||
* raise the priority of the current thread hoping to improve our
|
||||
* likelyhood of detecting a bug
|
||||
*/
|
||||
priorityOfTestThread = epicsThreadGetPrioritySelf ();
|
||||
epicsThreadSetPriority ( epicsThreadGetIdSelf(), epicsThreadPriorityHigh );
|
||||
|
||||
|
||||
/*
|
||||
* wait for the first subscription update to arrive
|
||||
*/
|
||||
{
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
while ( pTestData->m_eventData[0].m_nCallback == 0 ) {
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
epicsThreadSleep ( 50e-6 );
|
||||
lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
}
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
}
|
||||
/*
|
||||
* try to destroy all of the subscriptions at precisely the same time that
|
||||
* their first callbacks are running
|
||||
*/
|
||||
for ( j=0; j < multiSubscrDestroyNoLateCallbackEventCount; j++ ) {
|
||||
SEVCHK ( ca_clear_event ( pTestData->m_eventData[j].m_id ) , NULL );
|
||||
epicsMutexLockStatus lockStatus = epicsMutexLock ( pTestData->m_mutex );
|
||||
verify ( lockStatus == epicsMutexLockOK );
|
||||
pTestData->m_eventData[j].m_callbackIsOk = FALSE;
|
||||
epicsMutexUnlock ( pTestData->m_mutex );
|
||||
}
|
||||
/*
|
||||
* return to the original priority
|
||||
*/
|
||||
epicsThreadSetPriority ( epicsThreadGetIdSelf(), priorityOfTestThread );
|
||||
|
||||
if ( i % 1000 == 0 ) {
|
||||
showProgress ( pTestData->m_interestLevel );
|
||||
}
|
||||
}
|
||||
|
||||
SEVCHK ( ca_clear_channel ( pTestData->m_chan ), NULL );
|
||||
|
||||
ca_context_destroy ();
|
||||
|
||||
epicsEventSignal ( pTestData->m_testDoneEvent );
|
||||
}
|
||||
|
||||
/*
|
||||
* verify that, in a preemtive callback mode client, a subscription callback never
|
||||
* comes after the subscription is destroyed
|
||||
*/
|
||||
static void multiSubscrDestroyNoLateCallbackTest ( const char *pName, unsigned interestLevel )
|
||||
{
|
||||
struct MultiSubscrDestroyNoLateCallbackTestData * pTestData;
|
||||
|
||||
showProgressBegin ( "multiSubscrDestroyNoLateCallbackTest", interestLevel );
|
||||
|
||||
pTestData = calloc ( 1u, sizeof ( struct MultiSubscrDestroyNoLateCallbackTestData ) );
|
||||
verify ( pTestData );
|
||||
pTestData->m_mutex = epicsMutexMustCreate ();
|
||||
pTestData->m_testDoneEvent = epicsEventMustCreate ( epicsEventEmpty );
|
||||
pTestData->m_pChanName = pName;
|
||||
pTestData->m_interestLevel = interestLevel;
|
||||
epicsThreadMustCreate (
|
||||
"multiSubscrDestroyNoLateCallbackTest",
|
||||
epicsThreadPriorityLow,
|
||||
epicsThreadGetStackSize ( epicsThreadStackMedium ),
|
||||
multiSubscrDestroyNoLateCallbackThread,
|
||||
pTestData );
|
||||
|
||||
/*
|
||||
* wait for test to complete
|
||||
*/
|
||||
epicsEventMustWait ( pTestData->m_testDoneEvent );
|
||||
|
||||
/*
|
||||
* cleanup
|
||||
*/
|
||||
epicsMutexDestroy ( pTestData->m_mutex );
|
||||
epicsEventDestroy ( pTestData->m_testDoneEvent );
|
||||
free ( pTestData );
|
||||
|
||||
showProgressEnd ( interestLevel );
|
||||
}
|
||||
|
||||
/*
|
||||
* multiSubscriptionDeleteTest
|
||||
*
|
||||
@@ -3263,6 +3416,11 @@ int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
|
||||
epicsEnvSet ( "EPICS_CA_MAX_ARRAY_BYTES", tmpString );
|
||||
}
|
||||
|
||||
/*
|
||||
* this test creates, and then destroys, a private CA context
|
||||
*/
|
||||
multiSubscrDestroyNoLateCallbackTest ( pName, interestLevel );
|
||||
|
||||
status = ca_context_create ( select );
|
||||
SEVCHK ( status, NULL );
|
||||
|
||||
|
||||
@@ -332,13 +332,6 @@ void bhe::unregisterIIU (
|
||||
}
|
||||
}
|
||||
|
||||
void * bhe::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void bhe::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -87,7 +87,6 @@ private:
|
||||
const epicsTime & currentTime );
|
||||
bhe ( const bhe & );
|
||||
bhe & operator = ( const bhe & );
|
||||
void * operator new ( size_t size );
|
||||
epicsShareFunc void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
|
||||
{
|
||||
osiSockIoctl_t yes = true;
|
||||
int status = socket_ioctl ( this->sock, // X aCC 392
|
||||
int status = socket_ioctl ( this->sock,
|
||||
FIONBIO, & yes);
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -126,7 +126,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
|
||||
memset ( (char *)&addr, 0 , sizeof ( addr ) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY ); // X aCC 818
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
int status = bind (this->sock, &addr.sa, sizeof (addr) );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -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
|
||||
@@ -277,7 +277,7 @@ int ca_client_context :: printFormated (
|
||||
}
|
||||
|
||||
int ca_client_context :: varArgsPrintFormated (
|
||||
const char *pformat, va_list args ) const // X aCC 361
|
||||
const char *pformat, va_list args ) const
|
||||
{
|
||||
caPrintfFunc * pFunc;
|
||||
{
|
||||
@@ -751,6 +751,8 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
|
||||
{
|
||||
oldChannelNotify & chan = pMon->channel ();
|
||||
ca_client_context & cac = chan.getClientCtx ();
|
||||
// !!!! 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
|
||||
@@ -761,7 +763,25 @@ epicsShareFunc int epicsShareAPI ca_clear_subscription ( evid pMon )
|
||||
catch ( cacChannel::notConnected & ) {
|
||||
// intentionally ignored
|
||||
}
|
||||
pMon->cancel ( guard );
|
||||
}
|
||||
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 );
|
||||
}
|
||||
return ECA_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -568,7 +568,7 @@ bool cac::findOrCreateVirtCircuit (
|
||||
}
|
||||
|
||||
void cac::transferChanToVirtCircuit (
|
||||
unsigned cid, unsigned sid, // X aCC 431
|
||||
unsigned cid, unsigned sid,
|
||||
ca_uint16_t typeCode, arrayElementCount count,
|
||||
unsigned minorVersionNumber, const osiSockAddr & addr,
|
||||
const epicsTime & currentTime )
|
||||
@@ -711,6 +711,7 @@ netReadNotifyIO & cac::readNotifyRequest (
|
||||
}
|
||||
|
||||
bool cac::destroyIO (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::ioid & idIn, nciu & chan )
|
||||
{
|
||||
@@ -787,7 +788,7 @@ void cac::recycleSubscription (
|
||||
netSubscription & cac::subscriptionRequest (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, privateInterfaceForIO & privChan,
|
||||
unsigned type, // X aCC 361
|
||||
unsigned type,
|
||||
arrayElementCount nElem, unsigned mask,
|
||||
cacStateNotify & notifyIn,
|
||||
bool chanIsInstalled )
|
||||
@@ -1021,7 +1022,7 @@ bool cac::readExcep ( callbackManager &, tcpiiu &,
|
||||
}
|
||||
|
||||
bool cac::writeExcep (
|
||||
callbackManager & mgr, // X aCC 431
|
||||
callbackManager & mgr,
|
||||
tcpiiu &, const caHdrLargeArray & hdr,
|
||||
const char * pCtx, unsigned status )
|
||||
{
|
||||
@@ -1093,7 +1094,7 @@ bool cac::exceptionRespAction ( callbackManager & cbMutexIn, tcpiiu & iiu,
|
||||
}
|
||||
|
||||
bool cac::accessRightsRespAction (
|
||||
callbackManager & mgr, tcpiiu &, // X aCC 431
|
||||
callbackManager & mgr, tcpiiu &,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -1110,7 +1111,7 @@ bool cac::accessRightsRespAction (
|
||||
}
|
||||
|
||||
bool cac::createChannelRespAction (
|
||||
callbackManager & mgr, tcpiiu & iiu, // X aCC 431
|
||||
callbackManager & mgr, tcpiiu & iiu,
|
||||
const epicsTime &, const caHdrLargeArray & hdr, void * /* pMsgBody */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
@@ -1157,7 +1158,7 @@ bool cac::verifyAndDisconnectChan (
|
||||
}
|
||||
|
||||
void cac::disconnectChannel (
|
||||
epicsGuard < epicsMutex > & cbGuard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard, nciu & chan )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
+3
-7
@@ -55,7 +55,7 @@ class netSubscription;
|
||||
// used to control access to cac's recycle routines which
|
||||
// should only be indirectly invoked by CAC when its lock
|
||||
// is applied
|
||||
class cacRecycle { // X aCC 655
|
||||
class cacRecycle {
|
||||
public:
|
||||
virtual void recycleReadNotifyIO (
|
||||
epicsGuard < epicsMutex > &, netReadNotifyIO &io ) = 0;
|
||||
@@ -155,7 +155,8 @@ public:
|
||||
unsigned type, arrayElementCount nElem, unsigned mask,
|
||||
cacStateNotify &, bool channelIsInstalled );
|
||||
bool destroyIO (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & idIn,
|
||||
nciu & chan );
|
||||
void disconnectAllIO (
|
||||
@@ -167,11 +168,6 @@ public:
|
||||
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,
|
||||
|
||||
+26
-7
@@ -69,7 +69,7 @@ typedef unsigned long arrayElementCount;
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacWriteNotify { // X aCC 655
|
||||
class epicsShareClass cacWriteNotify {
|
||||
public:
|
||||
virtual ~cacWriteNotify () = 0;
|
||||
virtual void completion ( epicsGuard < epicsMutex > & ) = 0;
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacReadNotify { // X aCC 655
|
||||
class epicsShareClass cacReadNotify {
|
||||
public:
|
||||
virtual ~cacReadNotify () = 0;
|
||||
virtual void completion (
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
|
||||
// 1) this should not be passing caerr.h status to the exception callback
|
||||
// 2) needless-to-say the data should be passed here using the new data access API
|
||||
class epicsShareClass cacStateNotify { // X aCC 655
|
||||
class epicsShareClass cacStateNotify {
|
||||
public:
|
||||
virtual ~cacStateNotify () = 0;
|
||||
virtual void current (
|
||||
@@ -131,7 +131,7 @@ private:
|
||||
bool f_operatorConfirmationRequest:1;
|
||||
};
|
||||
|
||||
class epicsShareClass cacChannelNotify { // X aCC 655
|
||||
class epicsShareClass cacChannelNotify {
|
||||
public:
|
||||
virtual ~cacChannelNotify () = 0;
|
||||
virtual void connectNotify ( epicsGuard < epicsMutex > & ) = 0;
|
||||
@@ -152,6 +152,16 @@ public:
|
||||
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,6 +184,7 @@ public:
|
||||
|
||||
cacChannel ( cacChannelNotify & );
|
||||
virtual void destroy (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
cacChannelNotify & notify () const; // required ?????
|
||||
virtual unsigned getName (
|
||||
@@ -207,7 +218,15 @@ public:
|
||||
epicsGuard < epicsMutex > &, unsigned type,
|
||||
arrayElementCount count, unsigned mask, cacStateNotify &,
|
||||
ioid * = 0 ) = 0;
|
||||
// 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 (
|
||||
@@ -258,7 +277,7 @@ private:
|
||||
cacChannel & operator = ( const cacChannel & );
|
||||
};
|
||||
|
||||
class epicsShareClass cacContext { // X aCC 655
|
||||
class epicsShareClass cacContext {
|
||||
public:
|
||||
virtual ~cacContext ();
|
||||
virtual cacChannel & createChannel (
|
||||
@@ -277,7 +296,7 @@ public:
|
||||
epicsGuard < epicsMutex > &, unsigned level ) const = 0;
|
||||
};
|
||||
|
||||
class epicsShareClass cacContextNotify { // X aCC 655
|
||||
class epicsShareClass cacContextNotify {
|
||||
public:
|
||||
virtual ~cacContextNotify () = 0;
|
||||
virtual cacContext & createNetworkContext (
|
||||
@@ -297,7 +316,7 @@ public:
|
||||
// **** Lock Hierarchy ****
|
||||
// callbackControl must be taken before mutualExclusion if both are held at
|
||||
// the same time
|
||||
class epicsShareClass cacService { // X aCC 655
|
||||
class epicsShareClass cacService {
|
||||
public:
|
||||
virtual ~cacService () = 0;
|
||||
virtual cacContext & contextCreate (
|
||||
|
||||
+2
-2
@@ -131,7 +131,7 @@ int main ( int argc, char ** argv )
|
||||
}
|
||||
|
||||
osiSockIoctl_t yes = true;
|
||||
status = socket_ioctl ( sock, FIONBIO, &yes ); // X aCC 392
|
||||
status = socket_ioctl ( sock, FIONBIO, &yes );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
@@ -166,7 +166,7 @@ int main ( int argc, char ** argv )
|
||||
}
|
||||
|
||||
osiSockIoctl_t no = false;
|
||||
status = socket_ioctl ( sock, FIONBIO, &no ); // X aCC 392
|
||||
status = socket_ioctl ( sock, FIONBIO, &no );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
|
||||
+2
-3
@@ -44,7 +44,7 @@ public:
|
||||
virtual void release ( void * ) = 0;
|
||||
};
|
||||
|
||||
class wireSendAdapter { // X aCC 655
|
||||
class wireSendAdapter {
|
||||
public:
|
||||
virtual unsigned sendBytes ( const void * pBuf,
|
||||
unsigned nBytesInBuf,
|
||||
@@ -65,7 +65,7 @@ struct statusWireIO {
|
||||
swioCircuitState circuitState;
|
||||
};
|
||||
|
||||
class wireRecvAdapter { // X aCC 655
|
||||
class wireRecvAdapter {
|
||||
public:
|
||||
virtual void recvBytes ( void * pBuf,
|
||||
unsigned nBytesInBuf, statusWireIO & ) = 0;
|
||||
@@ -114,7 +114,6 @@ private:
|
||||
unsigned nextWriteIndex;
|
||||
unsigned nextReadIndex;
|
||||
epicsUInt8 buf [ comBufSize ];
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
template < class T >
|
||||
bool push ( const T * ); // disabled
|
||||
|
||||
@@ -155,7 +155,7 @@ epicsUInt32 comQueRecv::multiBufferPopUInt32 ()
|
||||
unsigned byte3 = this->popUInt8();
|
||||
unsigned byte4 = this->popUInt8();
|
||||
tmp = static_cast <epicsUInt32>
|
||||
( ( byte1 << 24u ) | ( byte2 << 16u ) | //X aCC 392
|
||||
( ( byte1 << 24u ) | ( byte2 << 16u ) |
|
||||
( byte3 << 8u ) | byte4 );
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -368,7 +368,7 @@ void comQueSend::insertRequestWithPayLoad (
|
||||
// the above checks verify that the total size
|
||||
// is lest that 0xffffffff
|
||||
size = static_cast < ca_uint32_t >
|
||||
( dbr_size_n ( dataType, nElem ) ); // X aCC 392
|
||||
( dbr_size_n ( dataType, nElem ) );
|
||||
payloadSize = CA_MESSAGE_ALIGN ( size );
|
||||
this->insertRequestHeader ( request, payloadSize,
|
||||
static_cast <ca_uint16_t> ( dataType ),
|
||||
|
||||
@@ -65,7 +65,7 @@ void disconnectGovernorTimer::shutdown (
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus disconnectGovernorTimer::expire (
|
||||
const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
const epicsTime & /* currentTime */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
while ( nciu * pChan = chanList.get () ) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "caProto.h"
|
||||
#include "netiiu.h"
|
||||
|
||||
class disconnectGovernorNotify { // X aCC 655
|
||||
class disconnectGovernorNotify {
|
||||
public:
|
||||
virtual ~disconnectGovernorNotify () = 0;
|
||||
virtual void govExpireNotify (
|
||||
|
||||
@@ -90,13 +90,6 @@ void getCallback::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * getCallback::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void getCallback::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -105,13 +105,6 @@ void getCopy::show ( unsigned level ) const
|
||||
}
|
||||
}
|
||||
|
||||
void * getCopy::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void getCopy::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
+10
-10
@@ -133,7 +133,7 @@ extern "C" void epicsShareAPI removeDuplicateAddresses
|
||||
|
||||
if ( pNode->addr.sa.sa_family == AF_INET ) {
|
||||
|
||||
pTmpNode = (osiSockAddrNode *) ellFirst (pDestList); // X aCC 749
|
||||
pTmpNode = (osiSockAddrNode *) ellFirst (pDestList);
|
||||
while ( pTmpNode ) {
|
||||
if (pTmpNode->addr.sa.sa_family == AF_INET) {
|
||||
if ( pNode->addr.ia.sin_addr.s_addr == pTmpNode->addr.ia.sin_addr.s_addr &&
|
||||
@@ -149,7 +149,7 @@ extern "C" void epicsShareAPI removeDuplicateAddresses
|
||||
break;
|
||||
}
|
||||
}
|
||||
pTmpNode = (osiSockAddrNode *) ellNext (&pTmpNode->node); // X aCC 749
|
||||
pTmpNode = (osiSockAddrNode *) ellNext (&pTmpNode->node);
|
||||
}
|
||||
if (pNode) {
|
||||
ellAdd (pDestList, &pNode->node);
|
||||
@@ -168,12 +168,12 @@ static void forcePort ( ELLLIST *pList, unsigned short port )
|
||||
{
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
pNode = ( osiSockAddrNode * ) ellFirst ( pList ); // X aCC 749
|
||||
pNode = ( osiSockAddrNode * ) ellFirst ( pList );
|
||||
while ( pNode ) {
|
||||
if ( pNode->addr.sa.sa_family == AF_INET ) {
|
||||
pNode->addr.ia.sin_port = htons ( port );
|
||||
}
|
||||
pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node ); // X aCC 749
|
||||
pNode = ( osiSockAddrNode * ) ellNext ( &pNode->node );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,9 +192,9 @@ extern "C" void epicsShareAPI configureChannelAccessAddressList
|
||||
/*
|
||||
* dont load the list twice
|
||||
*/
|
||||
assert ( ellCount (pList) == 0 ); // X aCC 392
|
||||
assert ( ellCount (pList) == 0 );
|
||||
|
||||
ellInit ( &tmpList ); // X aCC 392
|
||||
ellInit ( &tmpList );
|
||||
|
||||
/*
|
||||
* Check to see if the user has disabled
|
||||
@@ -217,12 +217,12 @@ extern "C" void epicsShareAPI configureChannelAccessAddressList
|
||||
if (yes) {
|
||||
ELLLIST bcastList;
|
||||
osiSockAddr addr;
|
||||
ellInit ( &bcastList ); // X aCC 392
|
||||
ellInit ( &bcastList );
|
||||
addr.ia.sin_family = AF_UNSPEC;
|
||||
osiSockDiscoverBroadcastAddresses ( &bcastList, sock, &addr );
|
||||
forcePort ( &bcastList, port );
|
||||
removeDuplicateAddresses ( &tmpList, &bcastList, 1 );
|
||||
if ( ellCount ( &tmpList ) == 0 ) { // X aCC 392
|
||||
if ( ellCount ( &tmpList ) == 0 ) {
|
||||
osiSockAddrNode *pNewNode;
|
||||
pNewNode = (osiSockAddrNode *) calloc ( 1, sizeof (*pNewNode) );
|
||||
if ( pNewNode ) {
|
||||
@@ -254,11 +254,11 @@ extern "C" void epicsShareAPI printChannelAccessAddressList ( const ELLLIST *pLi
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
::printf ( "Channel Access Address List\n" );
|
||||
pNode = (osiSockAddrNode *) ellFirst ( pList ); // X aCC 749
|
||||
pNode = (osiSockAddrNode *) ellFirst ( pList );
|
||||
while (pNode) {
|
||||
char buf[64];
|
||||
ipAddrToA ( &pNode->addr.ia, buf, sizeof ( buf ) );
|
||||
::printf ( "%s\n", buf );
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node ); // X aCC 749
|
||||
pNode = (osiSockAddrNode *) ellNext ( &pNode->node );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,13 +73,6 @@ void msgForMultiplyDefinedPV::operator delete ( void *pCadaver,
|
||||
}
|
||||
#endif
|
||||
|
||||
void * msgForMultiplyDefinedPV::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void msgForMultiplyDefinedPV::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
# define epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
class callbackForMultiplyDefinedPV { // X aCC 655
|
||||
class callbackForMultiplyDefinedPV {
|
||||
public:
|
||||
virtual ~callbackForMultiplyDefinedPV () = 0;
|
||||
virtual void pvMultiplyDefinedNotify (
|
||||
@@ -64,7 +64,6 @@ private:
|
||||
void transactionComplete ( const char * pHostName );
|
||||
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
|
||||
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
+14
-16
@@ -76,29 +76,24 @@ 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 );
|
||||
}
|
||||
|
||||
void * nciu::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
this->piiu->uninstallChan ( mutualExcusionGuard, *this );
|
||||
this->cacCtx.destroyChannel ( mutualExcusionGuard, *this );
|
||||
}
|
||||
|
||||
void nciu::operator delete ( void * )
|
||||
@@ -387,9 +382,12 @@ void nciu::subscribe (
|
||||
}
|
||||
|
||||
void nciu::ioCancel (
|
||||
epicsGuard < epicsMutex > & guard, const ioid & idIn )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const ioid & idIn )
|
||||
{
|
||||
this->cacCtx.destroyIO ( guard, idIn, *this );
|
||||
this->cacCtx.destroyIO ( callbackGuard,
|
||||
mutualExclusionGuard, idIn, *this );
|
||||
}
|
||||
|
||||
void nciu::ioShow (
|
||||
|
||||
+10
-2
@@ -121,7 +121,7 @@ private:
|
||||
friend class disconnectGovernorTimer;
|
||||
};
|
||||
|
||||
class privateInterfaceForIO { // X aCC 655
|
||||
class privateInterfaceForIO {
|
||||
public:
|
||||
virtual void ioCompletionNotify (
|
||||
epicsGuard < epicsMutex > &, class baseNMIU & ) = 0;
|
||||
@@ -220,6 +220,7 @@ private:
|
||||
ca_uint16_t typeCode;
|
||||
ca_uint8_t priority;
|
||||
virtual void destroy (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void initiateConnect (
|
||||
epicsGuard < epicsMutex > & );
|
||||
@@ -243,7 +244,15 @@ private:
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
unsigned type, arrayElementCount nElem,
|
||||
unsigned mask, cacStateNotify ¬ify, ioid * );
|
||||
// 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 (
|
||||
@@ -270,7 +279,6 @@ private:
|
||||
epicsGuard < epicsMutex > & guard ) const throw ();
|
||||
nciu ( const nciu & );
|
||||
nciu & operator = ( const nciu & );
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
+5
-8
@@ -42,7 +42,7 @@
|
||||
|
||||
class privateInterfaceForIO;
|
||||
|
||||
class baseNMIU : public tsDLNode < baseNMIU >, // X aCC 655
|
||||
class baseNMIU : public tsDLNode < baseNMIU >,
|
||||
public chronIntIdRes < baseNMIU > {
|
||||
public:
|
||||
virtual void destroy (
|
||||
@@ -106,7 +106,6 @@ private:
|
||||
const unsigned mask;
|
||||
bool subscribed;
|
||||
class netSubscription * isSubscription ();
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netSubscription, 1024, epicsMutexNOOP > & );
|
||||
@@ -147,7 +146,6 @@ protected:
|
||||
private:
|
||||
cacReadNotify & notify;
|
||||
class privateInterfaceForIO & privateChanForIO;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netReadNotifyIO, 1024, epicsMutexNOOP > & );
|
||||
@@ -190,7 +188,6 @@ protected:
|
||||
private:
|
||||
cacWriteNotify & notify;
|
||||
privateInterfaceForIO & privateChanForIO;
|
||||
void * operator new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class netWriteNotifyIO, 1024, epicsMutexNOOP > & );
|
||||
@@ -237,12 +234,12 @@ inline netSubscription * netSubscription::factory (
|
||||
class privateInterfaceForIO & chan, unsigned type, arrayElementCount count,
|
||||
unsigned mask, cacStateNotify ¬ify )
|
||||
{
|
||||
return new ( freeList ) netSubscription ( chan, type, // X aCC 930
|
||||
return new ( freeList ) netSubscription ( chan, type,
|
||||
count, mask, notify );
|
||||
}
|
||||
|
||||
inline arrayElementCount netSubscription::getCount (
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & guard, bool allow_zero ) const
|
||||
{
|
||||
//guard.assertIdenticalMutex ( this->mutex );
|
||||
arrayElementCount nativeCount = this->privateChanForIO.nativeElementCount ( guard );
|
||||
@@ -268,7 +265,7 @@ inline netReadNotifyIO * netReadNotifyIO::factory (
|
||||
tsFreeList < class netReadNotifyIO, 1024, epicsMutexNOOP > & freeList,
|
||||
privateInterfaceForIO & ioComplNotifIntf, cacReadNotify & notify )
|
||||
{
|
||||
return new ( freeList ) netReadNotifyIO ( ioComplNotifIntf, notify ); // X aCC 930
|
||||
return new ( freeList ) netReadNotifyIO ( ioComplNotifIntf, notify );
|
||||
}
|
||||
|
||||
inline void * netReadNotifyIO::operator new ( size_t size,
|
||||
@@ -289,7 +286,7 @@ inline netWriteNotifyIO * netWriteNotifyIO::factory (
|
||||
tsFreeList < class netWriteNotifyIO, 1024, epicsMutexNOOP > & freeList,
|
||||
privateInterfaceForIO & ioComplNotifyIntf, cacWriteNotify & notify )
|
||||
{
|
||||
return new ( freeList ) netWriteNotifyIO ( ioComplNotifyIntf, notify ); // X aCC 930
|
||||
return new ( freeList ) netWriteNotifyIO ( ioComplNotifyIntf, notify );
|
||||
}
|
||||
|
||||
inline void * netWriteNotifyIO::operator new ( size_t size,
|
||||
|
||||
@@ -119,13 +119,6 @@ void netReadNotifyIO::forceSubscriptionUpdate (
|
||||
{
|
||||
}
|
||||
|
||||
void * netReadNotifyIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netReadNotifyIO::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -170,13 +170,6 @@ void netSubscription::forceSubscriptionUpdate (
|
||||
guard, chan, *this );
|
||||
}
|
||||
|
||||
void * netSubscription::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netSubscription::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -117,14 +117,6 @@ void netWriteNotifyIO::forceSubscriptionUpdate (
|
||||
{
|
||||
}
|
||||
|
||||
void * netWriteNotifyIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error (
|
||||
"why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void netWriteNotifyIO::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ union osiSockAddr;
|
||||
class cac;
|
||||
class nciu;
|
||||
|
||||
class netiiu { // X aCC 655
|
||||
class netiiu {
|
||||
public:
|
||||
virtual ~netiiu () = 0;
|
||||
virtual unsigned getHostName (
|
||||
|
||||
+59
-12
@@ -53,7 +53,8 @@ public:
|
||||
const char * pName, caCh * pConnCallBackIn,
|
||||
void * pPrivateIn, capri priority );
|
||||
void destructor (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & mutexGuard );
|
||||
|
||||
// legacy C API
|
||||
friend unsigned epicsShareAPI ca_get_host_name (
|
||||
@@ -122,6 +123,7 @@ public:
|
||||
unsigned type, arrayElementCount count, const void *pValue,
|
||||
cacWriteNotify &, cacChannel::ioid *pId = 0 );
|
||||
void ioCancel (
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & );
|
||||
void ioShow (
|
||||
@@ -162,7 +164,6 @@ private:
|
||||
unsigned type, arrayElementCount count );
|
||||
oldChannelNotify ( const oldChannelNotify & );
|
||||
oldChannelNotify & operator = ( const oldChannelNotify & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -195,7 +196,6 @@ private:
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
getCopy ( const getCopy & );
|
||||
getCopy & operator = ( const getCopy & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
const char * pContext, unsigned type, arrayElementCount count );
|
||||
getCallback ( const getCallback & );
|
||||
getCallback & operator = ( const getCallback & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -245,7 +244,6 @@ private:
|
||||
unsigned type, arrayElementCount count );
|
||||
putCallback ( const putCallback & );
|
||||
putCallback & operator = ( const putCallback & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -259,8 +257,16 @@ public:
|
||||
evid * );
|
||||
~oldSubscription ();
|
||||
oldChannelNotify & channel () const;
|
||||
// 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 (
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void * operator new ( size_t size,
|
||||
tsFreeList < struct oldSubscription, 1024, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
@@ -278,7 +284,6 @@ private:
|
||||
const char *pContext, unsigned type, arrayElementCount count );
|
||||
oldSubscription ( const oldSubscription & );
|
||||
oldSubscription & operator = ( const oldSubscription & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -341,6 +346,8 @@ public:
|
||||
void destroySubscription ( epicsGuard < epicsMutex > &, oldSubscription & );
|
||||
epicsMutex & mutexRef () const;
|
||||
|
||||
template < class T >
|
||||
void whenThereIsAnExceptionDestroySyncGroupIO ( epicsGuard < epicsMutex > &, T & );
|
||||
|
||||
// legacy C API
|
||||
friend int epicsShareAPI ca_create_channel (
|
||||
@@ -368,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 {};
|
||||
@@ -384,7 +402,7 @@ private:
|
||||
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;
|
||||
@@ -444,10 +462,11 @@ inline void oldChannelNotify::initiateConnect (
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioCancel (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard,
|
||||
const cacChannel::ioid & id )
|
||||
{
|
||||
this->io.ioCancel ( guard, id );
|
||||
this->io.ioCancel ( callbackGuard, mutualExclusionGuard, id );
|
||||
}
|
||||
|
||||
inline void oldChannelNotify::ioShow (
|
||||
@@ -492,9 +511,10 @@ inline void oldSubscription::operator delete ( void *pCadaver,
|
||||
#endif
|
||||
|
||||
inline void oldSubscription::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
CallbackGuard & callbackGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard )
|
||||
{
|
||||
this->chan.ioCancel ( guard, this->id );
|
||||
this->chan.ioCancel ( callbackGuard, mutualExclusionGuard, this->id );
|
||||
}
|
||||
|
||||
inline oldChannelNotify & oldSubscription::channel () const
|
||||
@@ -560,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
|
||||
|
||||
@@ -65,14 +65,15 @@ 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 ();
|
||||
}
|
||||
@@ -159,13 +160,6 @@ void oldChannelNotify::writeException (
|
||||
__FILE__, __LINE__, *this, type, count, CA_OP_PUT );
|
||||
}
|
||||
|
||||
void * oldChannelNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void oldChannelNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
@@ -638,7 +632,7 @@ arrayElementCount epicsShareAPI ca_element_count ( chid pChan )
|
||||
/*
|
||||
* ca_state ()
|
||||
*/
|
||||
enum channel_state epicsShareAPI ca_state ( chid pChan ) // X aCC 361
|
||||
enum channel_state epicsShareAPI ca_state ( chid pChan )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pChan->cacCtx.mutexRef () );
|
||||
if ( pChan->io.connected ( guard ) ) {
|
||||
|
||||
@@ -90,13 +90,6 @@ void putCallback::exception (
|
||||
}
|
||||
}
|
||||
|
||||
void * putCallback::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void putCallback::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
+3
-10
@@ -178,7 +178,7 @@ bool repeaterClient::connect ()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool repeaterClient::sendConfirm () // X aCC 361
|
||||
bool repeaterClient::sendConfirm ()
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -204,7 +204,7 @@ bool repeaterClient::sendConfirm () // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
bool repeaterClient::sendMessage ( const void *pBuf, unsigned bufSize ) // X aCC 361
|
||||
bool repeaterClient::sendMessage ( const void *pBuf, unsigned bufSize )
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -245,13 +245,6 @@ repeaterClient::~repeaterClient ()
|
||||
#endif
|
||||
}
|
||||
|
||||
void * repeaterClient::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void repeaterClient::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
@@ -304,7 +297,7 @@ inline bool repeaterClient::identicalPort ( const osiSockAddr &fromIn )
|
||||
return false;
|
||||
}
|
||||
|
||||
bool repeaterClient::verify () // X aCC 361
|
||||
bool repeaterClient::verify ()
|
||||
{
|
||||
SOCKET tmpSock;
|
||||
bool success = makeSocket ( this->port (), false, & tmpSock );
|
||||
|
||||
@@ -64,7 +64,6 @@ private:
|
||||
osiSockAddr from;
|
||||
SOCKET sock;
|
||||
unsigned short port () const;
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void repeaterSubscribeTimer::shutdown (
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus repeaterSubscribeTimer::
|
||||
expire ( const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
static const unsigned nTriesToMsg = 50;
|
||||
if ( this->attempts > nTriesToMsg && ! this->once ) {
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
class epicsMutex;
|
||||
class cacContextNotify;
|
||||
|
||||
class repeaterTimerNotify { // X aCC 655
|
||||
class repeaterTimerNotify {
|
||||
public:
|
||||
virtual ~repeaterTimerNotify () = 0;
|
||||
virtual void repeaterRegistrationMessage (
|
||||
|
||||
@@ -124,7 +124,7 @@ void searchTimer::moveChannels (
|
||||
// searchTimer::expire ()
|
||||
//
|
||||
epicsTimerNotify::expireStatus searchTimer::expire (
|
||||
const epicsTime & currentTime ) // X aCC 361
|
||||
const epicsTime & currentTime )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include "caProto.h"
|
||||
#include "netiiu.h"
|
||||
|
||||
class searchTimerNotify { // X aCC 655
|
||||
class searchTimerNotify {
|
||||
public:
|
||||
virtual ~searchTimerNotify () = 0;
|
||||
virtual void boostChannel (
|
||||
|
||||
+10
-11
@@ -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,7 +37,6 @@ public:
|
||||
T * get ();
|
||||
T * release ();
|
||||
private:
|
||||
tsDLList < syncGroupNotify > & list;
|
||||
T * pNotify;
|
||||
struct CASG & sg;
|
||||
epicsGuard < epicsMutex > & guard;
|
||||
@@ -47,9 +45,8 @@ private:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+35
-35
@@ -46,29 +46,17 @@
|
||||
|
||||
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 { // X aCC 655
|
||||
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;
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual bool ioPending (
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
virtual void cancel (
|
||||
epicsGuard < epicsMutex > & guard ) = 0;
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard ) = 0;
|
||||
virtual void show (
|
||||
epicsGuard < epicsMutex > &,
|
||||
unsigned level ) const = 0;
|
||||
@@ -78,33 +66,38 @@ protected:
|
||||
syncGroupNotify & operator = ( const syncGroupNotify & );
|
||||
};
|
||||
|
||||
struct CASG;
|
||||
|
||||
class syncGroupReadNotify : public syncGroupNotify, public cacReadNotify {
|
||||
public:
|
||||
typedef void ( CASG :: * PRecycleFunc )
|
||||
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
|
||||
static syncGroupReadNotify * factory (
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > &,
|
||||
struct CASG &, chid, void *pValueIn );
|
||||
CASG &, PRecycleFunc, chid, void *pValueIn );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
casgRecycle & );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
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 new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupReadNotify, 128, epicsMutexNOOP > & );
|
||||
@@ -122,30 +115,33 @@ private:
|
||||
|
||||
class syncGroupWriteNotify : public syncGroupNotify, public cacWriteNotify {
|
||||
public:
|
||||
typedef void ( CASG :: * PRecycleFunc )
|
||||
( epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
|
||||
static syncGroupWriteNotify * factory (
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > &,
|
||||
struct CASG &, chid );
|
||||
CASG &, PRecycleFunc, chid );
|
||||
void destroy (
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
casgRecycle & );
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
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 new ( size_t );
|
||||
void operator delete ( void * );
|
||||
void * operator new ( size_t,
|
||||
tsFreeList < class syncGroupWriteNotify, 128, epicsMutexNOOP > & );
|
||||
@@ -163,17 +159,19 @@ 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 (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool ioComplete (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
bool verify ( epicsGuard < epicsMutex > & ) const;
|
||||
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,
|
||||
@@ -194,6 +192,7 @@ public:
|
||||
tsFreeList < struct CASG, 128, epicsMutexNOOP > & );
|
||||
epicsPlacementDeleteOperator (( void *,
|
||||
tsFreeList < struct CASG, 128, epicsMutexNOOP > & ))
|
||||
|
||||
private:
|
||||
tsDLList < syncGroupNotify > ioPendingList;
|
||||
tsDLList < syncGroupNotify > ioCompletedList;
|
||||
@@ -202,20 +201,21 @@ 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 (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void destroyCompletedIO (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard );
|
||||
void recycleReadNotifyIO ( epicsGuard < epicsMutex > &,
|
||||
syncGroupReadNotify & );
|
||||
void recycleWriteNotifyIO ( epicsGuard < epicsMutex > &,
|
||||
syncGroupWriteNotify & );
|
||||
|
||||
CASG ( const CASG & );
|
||||
CASG & operator = ( const CASG & );
|
||||
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
|
||||
~CASG ();
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupReadNotify::syncGroupReadNotify (
|
||||
CASG & sgIn, chid pChan, void * pValueIn ) :
|
||||
chan ( pChan ), sg ( sgIn ), pValue ( pValueIn ),
|
||||
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 )
|
||||
{
|
||||
@@ -46,27 +48,30 @@ void syncGroupReadNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
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 )
|
||||
struct CASG & sg, PRecycleFunc pRecycleFunc, chid chan, void * pValueIn )
|
||||
{
|
||||
return new ( freeList ) // X aCC 930
|
||||
syncGroupReadNotify ( sg, chan, pValueIn );
|
||||
return new ( freeList )
|
||||
syncGroupReadNotify ( sg, pRecycleFunc, chan, pValueIn );
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::destroy (
|
||||
epicsGuard < epicsMutex > & guard, casgRecycle & recycle )
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
CASG & sgRef ( this->sg );
|
||||
this->~syncGroupReadNotify ();
|
||||
recycle.recycleSyncGroupReadNotify ( guard, *this );
|
||||
( sgRef.*pRecycleFunc ) ( guard, *this );
|
||||
}
|
||||
|
||||
syncGroupReadNotify::~syncGroupReadNotify ()
|
||||
@@ -122,13 +127,6 @@ void syncGroupReadNotify::show (
|
||||
}
|
||||
}
|
||||
|
||||
void * syncGroupReadNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void syncGroupReadNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
@@ -26,8 +26,10 @@
|
||||
#include "syncGroup.h"
|
||||
#include "oldAccess.h"
|
||||
|
||||
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn, chid pChan ) :
|
||||
chan ( pChan ), sg ( sgIn ), magic ( CASG_MAGIC ),
|
||||
syncGroupWriteNotify::syncGroupWriteNotify ( CASG & sgIn,
|
||||
PRecycleFunc pRecycleFuncIn, chid pChan ) :
|
||||
chan ( pChan ), pRecycleFunc ( pRecycleFuncIn ),
|
||||
sg ( sgIn ), magic ( CASG_MAGIC ),
|
||||
id ( 0u ), idIsValid ( false ), ioComplete ( false )
|
||||
{
|
||||
}
|
||||
@@ -45,26 +47,29 @@ void syncGroupWriteNotify::begin (
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::cancel (
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
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 )
|
||||
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 )
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
CASG & sgRef ( this->sg );
|
||||
this->~syncGroupWriteNotify ();
|
||||
recycle.recycleSyncGroupWriteNotify ( guard, *this );
|
||||
( sgRef.*pRecycleFunc ) ( guard, *this );
|
||||
}
|
||||
|
||||
syncGroupWriteNotify::~syncGroupWriteNotify ()
|
||||
@@ -112,13 +117,6 @@ void syncGroupWriteNotify::show (
|
||||
}
|
||||
}
|
||||
|
||||
void * syncGroupWriteNotify::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void syncGroupWriteNotify::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
+97
-26
@@ -23,7 +23,7 @@
|
||||
/*
|
||||
* ca_sg_create()
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid ) // X aCC 361
|
||||
extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid )
|
||||
{
|
||||
ca_client_context * pcac;
|
||||
int caStatus;
|
||||
@@ -48,6 +48,22 @@ extern "C" int epicsShareAPI ca_sg_create ( CA_SYNC_GID * pgid ) // X aCC 361
|
||||
}
|
||||
}
|
||||
|
||||
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,19 +72,51 @@ 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 ()
|
||||
//
|
||||
@@ -84,14 +132,20 @@ extern "C" int epicsShareAPI ca_sg_block (
|
||||
ca_client_context *pcac;
|
||||
int status = fetchClientContext ( &pcac );
|
||||
if ( status == ECA_NORMAL ) {
|
||||
CASG * pcasg;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( ! pcasg ) {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
else {
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
if ( pcasg ) {
|
||||
status = pcasg->block (
|
||||
pcac->pCallbackGuard.get (), guard, timeout );
|
||||
}
|
||||
else {
|
||||
status = ECA_BADSYNCGRP;
|
||||
}
|
||||
}
|
||||
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 ) {
|
||||
CASG * pcasg;
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( pcac->mutex );
|
||||
CASG * pcasg = pcac->lookupCASG ( guard, gid );
|
||||
pcasg = pcac->lookupCASG ( guard, gid );
|
||||
}
|
||||
if ( pcasg ) {
|
||||
pcasg->reset ( guard );
|
||||
sync_group_reset ( *pcac, *pcasg );
|
||||
caStatus = ECA_NORMAL;
|
||||
}
|
||||
else {
|
||||
caStatus = ECA_BADSYNCGRP;
|
||||
@@ -143,7 +201,7 @@ extern "C" int epicsShareAPI ca_sg_stat ( const CA_SYNC_GID gid )
|
||||
/*
|
||||
* ca_sg_test
|
||||
*/
|
||||
extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) // X aCC 361
|
||||
extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid )
|
||||
{
|
||||
ca_client_context * pcac;
|
||||
int caStatus = fetchClientContext ( &pcac );
|
||||
@@ -151,7 +209,26 @@ extern "C" int epicsShareAPI ca_sg_test ( const CA_SYNC_GID gid ) // X aCC 361
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ tcpRecvWatchdog::~tcpRecvWatchdog ()
|
||||
}
|
||||
|
||||
epicsTimerNotify::expireStatus
|
||||
tcpRecvWatchdog::expire ( const epicsTime & /* currentTime */ ) // X aCC 361
|
||||
tcpRecvWatchdog::expire ( const epicsTime & /* currentTime */ )
|
||||
{
|
||||
epicsGuard < epicsMutex > guard ( this->mutex );
|
||||
if ( this->shuttingDown ) {
|
||||
|
||||
+16
-19
@@ -1135,7 +1135,7 @@ void tcpiiu::show ( unsigned level ) const
|
||||
}
|
||||
}
|
||||
|
||||
bool tcpiiu::setEchoRequestPending ( epicsGuard < epicsMutex > & guard ) // X aCC 361
|
||||
bool tcpiiu::setEchoRequestPending ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1275,12 +1275,9 @@ bool tcpiiu::processIncoming (
|
||||
this->msgHeaderAvailable = false;
|
||||
this->curDataBytes = 0u;
|
||||
}
|
||||
# if defined ( __HP_aCC ) && _HP_aCC <= 033300
|
||||
return false; // to make hpux compiler happy...
|
||||
# endif
|
||||
}
|
||||
|
||||
void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1310,7 +1307,7 @@ void tcpiiu::hostNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 4
|
||||
/*
|
||||
* tcpiiu::userNameSetRequest ()
|
||||
*/
|
||||
void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1338,7 +1335,7 @@ void tcpiiu::userNameSetRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 4
|
||||
}
|
||||
|
||||
void tcpiiu::disableFlowControlRequest (
|
||||
epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1354,7 +1351,7 @@ void tcpiiu::disableFlowControlRequest (
|
||||
}
|
||||
|
||||
void tcpiiu::enableFlowControlRequest (
|
||||
epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1369,7 +1366,7 @@ void tcpiiu::enableFlowControlRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard,
|
||||
const cacChannel::priLev & priority )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1389,7 +1386,7 @@ void tcpiiu::versionMessage ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1410,7 +1407,7 @@ void tcpiiu::echoRequest ( epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu &chan, unsigned type, arrayElementCount nElem, const void *pValue )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1425,7 +1422,7 @@ void tcpiiu::writeRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
}
|
||||
|
||||
|
||||
void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu &chan, netWriteNotifyIO &io, unsigned type,
|
||||
arrayElementCount nElem, const void *pValue )
|
||||
{
|
||||
@@ -1444,7 +1441,7 @@ void tcpiiu::writeNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 43
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netReadNotifyIO & io,
|
||||
unsigned dataType, arrayElementCount nElem )
|
||||
{
|
||||
@@ -1477,7 +1474,7 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
}
|
||||
|
||||
void tcpiiu::createChannelRequest (
|
||||
nciu & chan, epicsGuard < epicsMutex > & guard ) // X aCC 431
|
||||
nciu & chan, epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
|
||||
@@ -1525,7 +1522,7 @@ void tcpiiu::createChannelRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard,
|
||||
ca_uint32_t sid, ca_uint32_t cid )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1547,7 +1544,7 @@ void tcpiiu::clearChannelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 4
|
||||
// is to try again the next time that we reconnect
|
||||
//
|
||||
void tcpiiu::subscriptionRequest (
|
||||
epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1599,7 +1596,7 @@ void tcpiiu::subscriptionRequest (
|
||||
// is to try again the next time that we reconnect
|
||||
//
|
||||
void tcpiiu::subscriptionUpdateRequest (
|
||||
epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -1634,7 +1631,7 @@ void tcpiiu::subscriptionUpdateRequest (
|
||||
minder.commit ();
|
||||
}
|
||||
|
||||
void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard, // X aCC 431
|
||||
void tcpiiu::subscriptionCancelRequest ( epicsGuard < epicsMutex > & guard,
|
||||
nciu & chan, netSubscription & subscr )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -2052,7 +2049,7 @@ bool tcpiiu::bytesArePendingInOS () const
|
||||
return false;
|
||||
#else
|
||||
osiSockIoctl_t bytesPending = 0; /* shut up purifys yapping */
|
||||
int status = socket_ioctl ( this->sock, // X aCC 392
|
||||
int status = socket_ioctl ( this->sock,
|
||||
FIONREAD, & bytesPending );
|
||||
if ( status >= 0 ) {
|
||||
if ( bytesPending > 0 ) {
|
||||
|
||||
@@ -78,7 +78,7 @@ extern "C" void epicsShareAPI ca_dump_dbr (
|
||||
dbr_short_t *pvalue = (dbr_short_t *)pbuffer;
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
if(count!=1 && (i%10 == 0)) printf("\n");
|
||||
printf("%d ",* (short *)pvalue); // X aCC 392
|
||||
printf("%d ",* (short *)pvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ extern "C" void epicsShareAPI ca_dump_dbr (
|
||||
dbr_float_t *pvalue = (dbr_float_t *)pbuffer;
|
||||
for (i = 0; i < count; i++,pvalue++){
|
||||
if(count!=1 && (i%10 == 0)) printf("\n");
|
||||
printf("%6.4f ",*(float *)pvalue); // X aCC 392
|
||||
printf("%6.4f ",*(float *)pvalue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-2
@@ -201,7 +201,7 @@ udpiiu::udpiiu (
|
||||
memset ( (char *)&addr, 0 , sizeof (addr) );
|
||||
addr.ia.sin_family = AF_INET;
|
||||
addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY );
|
||||
addr.ia.sin_port = htons ( PORT_ANY ); // X aCC 818
|
||||
addr.ia.sin_port = htons ( PORT_ANY );
|
||||
status = bind (this->sock, &addr.sa, sizeof (addr) );
|
||||
if ( status < 0 ) {
|
||||
char sockErrBuf[64];
|
||||
@@ -471,7 +471,7 @@ void epicsShareAPI caRepeaterRegistrationMessage (
|
||||
}
|
||||
|
||||
memset ( (char *) &msg, 0, sizeof (msg) );
|
||||
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = REPEATER_REGISTER; // X aCC 818
|
||||
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = REPEATER_REGISTER;
|
||||
msg.m_available = saddr.ia.sin_addr.s_addr;
|
||||
|
||||
/*
|
||||
|
||||
@@ -335,7 +335,6 @@ private:
|
||||
|
||||
tcpiiu ( const tcpiiu & );
|
||||
tcpiiu & operator = ( const tcpiiu & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -372,7 +371,7 @@ inline bool tcpiiu::ca_v49_ok (
|
||||
}
|
||||
|
||||
inline bool tcpiiu::alive (
|
||||
epicsGuard < epicsMutex > & ) const // X aCC 361
|
||||
epicsGuard < epicsMutex > & ) const
|
||||
{
|
||||
return ( this->state == iiucs_connecting ||
|
||||
this->state == iiucs_connected );
|
||||
|
||||
+7
-8
@@ -62,7 +62,7 @@ class dbChannelIO;
|
||||
class dbPutNotifyBlocker;
|
||||
class dbSubscriptionIO;
|
||||
|
||||
class dbBaseIO // X aCC 655
|
||||
class dbBaseIO
|
||||
: public chronIntIdRes < dbBaseIO > {
|
||||
public:
|
||||
virtual dbSubscriptionIO * isSubscription () = 0;
|
||||
@@ -86,9 +86,9 @@ public:
|
||||
epicsGuard < epicsMutex > &, epicsMutex &,
|
||||
dbContext &, dbChannelIO &, struct dbAddr &, 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,
|
||||
@@ -110,7 +110,6 @@ private:
|
||||
dbSubscriptionIO ( const dbSubscriptionIO & );
|
||||
dbSubscriptionIO & operator = ( const dbSubscriptionIO & );
|
||||
virtual ~dbSubscriptionIO ();
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
@@ -165,7 +164,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 dbAddr & addr, unsigned type, unsigned long count,
|
||||
cacReadNotify & notify );
|
||||
@@ -182,9 +181,9 @@ public:
|
||||
cacWriteNotify & notify, cacChannel::ioid * pId );
|
||||
void show ( unsigned level ) const;
|
||||
void showAllIO ( const dbChannelIO & chan, unsigned level ) const;
|
||||
void destroyAllIO (
|
||||
void destroyAllIO ( CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > &, dbChannelIO & chan );
|
||||
void ioCancel ( epicsGuard < epicsMutex > &,
|
||||
void ioCancel ( CallbackGuard &, epicsGuard < epicsMutex > &,
|
||||
dbChannelIO & chan, const cacChannel::ioid &id );
|
||||
void ioShow ( epicsGuard < epicsMutex > &,
|
||||
const cacChannel::ioid & id, unsigned level ) const;
|
||||
|
||||
+8
-12
@@ -61,19 +61,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 );
|
||||
this->~dbChannelIO ();
|
||||
}
|
||||
|
||||
void dbChannelIO::destroy (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
this->serviceIO.destroyChannel ( guard, *this );
|
||||
// dont access this pointer after above call because
|
||||
this->serviceIO.destroyChannel ( cbGuard, guard, *this );
|
||||
// don't access this pointer after above call because
|
||||
// object nolonger exists
|
||||
}
|
||||
|
||||
@@ -132,11 +134,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 (
|
||||
@@ -204,13 +207,6 @@ void * dbChannelIO::operator new ( size_t size,
|
||||
return freeList.allocate ( size );
|
||||
}
|
||||
|
||||
void * dbChannelIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
#ifdef CXX_PLACEMENT_DELETE
|
||||
void dbChannelIO::operator delete ( void *pCadaver,
|
||||
tsFreeList < dbChannelIO, 256, epicsMutexNOOP > & freeList )
|
||||
|
||||
@@ -48,8 +48,10 @@ public:
|
||||
epicsMutex &, cacChannelNotify &,
|
||||
const dbAddr &, dbContext & );
|
||||
void destructor (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & );
|
||||
void destroy (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & mutualExclusionGuard );
|
||||
void callReadNotify (
|
||||
epicsGuard < epicsMutex > &,
|
||||
@@ -100,7 +102,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 > &,
|
||||
@@ -111,7 +114,6 @@ private:
|
||||
epicsGuard < epicsMutex > & ) const;
|
||||
dbChannelIO ( const dbChannelIO & );
|
||||
dbChannelIO & operator = ( const dbChannelIO & );
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
+19
-15
@@ -83,7 +83,7 @@ dbContext::~dbContext ()
|
||||
}
|
||||
}
|
||||
|
||||
cacChannel & dbContext::createChannel ( // X aCC 361
|
||||
cacChannel & dbContext::createChannel (
|
||||
epicsGuard < epicsMutex > & guard, const char * pName,
|
||||
cacChannelNotify & notifyIn, cacChannel::priLev priority )
|
||||
{
|
||||
@@ -119,18 +119,20 @@ cacChannel & dbContext::createChannel ( // X aCC 361
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -269,7 +271,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;
|
||||
@@ -286,24 +290,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 );
|
||||
@@ -311,13 +315,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" );
|
||||
|
||||
@@ -59,10 +59,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->pn.pbuffer );
|
||||
delete [] pBuf;
|
||||
@@ -71,6 +72,7 @@ void dbPutNotifyBlocker::destructor ( epicsGuard < epicsMutex > & guard )
|
||||
}
|
||||
|
||||
void dbPutNotifyBlocker::cancel (
|
||||
CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -212,13 +214,6 @@ void * dbPutNotifyBlocker::operator new ( size_t size,
|
||||
return freeList.allocate ( size );
|
||||
}
|
||||
|
||||
void * dbPutNotifyBlocker::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
#ifdef CXX_PLACEMENT_DELETE
|
||||
void dbPutNotifyBlocker::operator delete ( void *pCadaver,
|
||||
tsFreeList < dbPutNotifyBlocker, 64, epicsMutexNOOP > & freeList )
|
||||
|
||||
@@ -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 dbAddr &,
|
||||
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,
|
||||
@@ -82,7 +82,6 @@ private:
|
||||
dbPutNotifyBlocker ( const dbPutNotifyBlocker & );
|
||||
dbPutNotifyBlocker & operator = ( const dbPutNotifyBlocker & );
|
||||
virtual ~dbPutNotifyBlocker ();
|
||||
void * operator new ( size_t size );
|
||||
void operator delete ( void * );
|
||||
};
|
||||
|
||||
|
||||
@@ -66,13 +66,14 @@ 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 (
|
||||
void dbSubscriptionIO::unsubscribe ( CallbackGuard & cbGuard,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -87,6 +88,7 @@ void dbSubscriptionIO::unsubscribe (
|
||||
}
|
||||
|
||||
void dbSubscriptionIO::channelDeleteException (
|
||||
CallbackGuard &,
|
||||
epicsGuard < epicsMutex > & guard )
|
||||
{
|
||||
guard.assertIdenticalMutex ( this->mutex );
|
||||
@@ -94,13 +96,6 @@ void dbSubscriptionIO::channelDeleteException (
|
||||
this->chan.pName(guard), this->type, this->count );
|
||||
}
|
||||
|
||||
void * dbSubscriptionIO::operator new ( size_t ) // X aCC 361
|
||||
{
|
||||
// The HPUX compiler seems to require this even though no code
|
||||
// calls it directly
|
||||
throw std::logic_error ( "why is the compiler calling private operator new" );
|
||||
}
|
||||
|
||||
void dbSubscriptionIO::operator delete ( void * )
|
||||
{
|
||||
// Visual C++ .net appears to require operator delete if
|
||||
|
||||
Reference in New Issue
Block a user