ipAddrToAsciiAsync.: don't try to join the daemon thread

This isn't really necessary and may unnecessarily delay
things (~10 sec. on Linux) if a query to an unreachable
DNS server is in progress.
This commit is contained in:
Michael Davidsaver
2016-01-21 13:00:50 -05:00
parent ef90d2d3c7
commit 04fee51795

View File

@@ -82,7 +82,6 @@ template class tsFreeList
extern "C" {
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
static void ipAddrToAsciiEngineShutdownRequest ( void * );
}
// - this class executes the synchronous DNS query
@@ -108,10 +107,7 @@ private:
unsigned cancelPendingCount;
bool exitFlag;
bool callbackInProgress;
static epicsMutex * pGlobalMutex;
static ipAddrToAsciiEnginePrivate * pEngine;
static unsigned numberOfReferences;
static bool shutdownRequest;
ipAddrToAsciiTransaction & createTransaction ();
void release ();
void run ();
@@ -119,15 +115,11 @@ private:
ipAddrToAsciiEnginePrivate & operator = ( const ipAddrToAsciiEngine & );
friend class ipAddrToAsciiEngine;
friend class ipAddrToAsciiTransactionPrivate;
friend void ipAddrToAsciiEngineShutdownRequest ( void * );
friend void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
};
epicsMutex * ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
// the users are not required to supply a show routine
// for there transaction callback class
@@ -138,26 +130,13 @@ ipAddrToAsciiCallBack::~ipAddrToAsciiCallBack () {}
ipAddrToAsciiTransaction::~ipAddrToAsciiTransaction () {}
ipAddrToAsciiEngine::~ipAddrToAsciiEngine () {}
static void ipAddrToAsciiEngineShutdownRequest ( void * )
{
bool deleteGlobalMutexCondDetected = false;
{
epicsGuard < epicsMutex >
guard ( * ipAddrToAsciiEnginePrivate :: pGlobalMutex );
ipAddrToAsciiEnginePrivate :: shutdownRequest = true;
deleteGlobalMutexCondDetected =
( ipAddrToAsciiEnginePrivate :: numberOfReferences == 0 );
}
if ( deleteGlobalMutexCondDetected ) {
delete ipAddrToAsciiEnginePrivate :: pGlobalMutex;
ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
}
}
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * )
{
ipAddrToAsciiEnginePrivate :: pGlobalMutex = new epicsMutex ();
epicsAtExit ( ipAddrToAsciiEngineShutdownRequest, 0 );
try{
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
}catch(std::exception& e){
errlogPrintf("ipAddrToAsciiEnginePrivate ctor fails with: %s\n", e.what());
}
}
// for now its probably sufficent to allocate one
@@ -169,21 +148,8 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate ()
epicsThreadOnce (
& ipAddrToAsciiEngineGlobalMutexOnceFlag,
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
// since we must not own lock when checking this flag
// this diagnostic has imperfect detection, but never
// incorrect detection
if ( ipAddrToAsciiEnginePrivate :: shutdownRequest ) {
throw std :: runtime_error (
"ipAddrToAsciiEngine::allocate (): "
"attempts to create an "
"ipAddrToAsciiEngine while the exit "
"handlers are running are rejected");
}
epicsGuard < epicsMutex > guard ( * ipAddrToAsciiEnginePrivate::pGlobalMutex );
if ( ! ipAddrToAsciiEnginePrivate::pEngine ) {
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
}
ipAddrToAsciiEnginePrivate::numberOfReferences++;
if(!ipAddrToAsciiEnginePrivate::pEngine)
throw std::runtime_error("ipAddrToAsciiEngine::allocate fails");
return * ipAddrToAsciiEnginePrivate::pEngine;
}
@@ -207,32 +173,8 @@ ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate ()
this->thread.exitWait ();
}
// for now its probably sufficent to allocate one
// DNS transaction thread for all codes sharing
// the same process that need DNS services but we
// leave our options open for the future
void ipAddrToAsciiEnginePrivate::release ()
{
bool deleteGlobalMutexCondDetected = false;
epicsThreadOnce (
& ipAddrToAsciiEngineGlobalMutexOnceFlag,
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
{
epicsGuard < epicsMutex >
guard ( * ipAddrToAsciiEnginePrivate::pGlobalMutex );
assert ( ipAddrToAsciiEnginePrivate::numberOfReferences > 0u );
ipAddrToAsciiEnginePrivate::numberOfReferences--;
if ( ipAddrToAsciiEnginePrivate::numberOfReferences == 0u ) {
deleteGlobalMutexCondDetected =
ipAddrToAsciiEnginePrivate :: shutdownRequest;
delete ipAddrToAsciiEnginePrivate :: pEngine;
ipAddrToAsciiEnginePrivate :: pEngine = 0;
}
}
if ( deleteGlobalMutexCondDetected ) {
delete ipAddrToAsciiEnginePrivate :: pGlobalMutex;
ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
}
}
void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
@@ -373,6 +315,8 @@ ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
if ( this->engine.pCurrent == this &&
this->engine.callbackInProgress &&
! this->engine.thread.isCurrentThread() ) {
// cancel from another thread while callback in progress
// waits for callback to complete
assert ( this->engine.cancelPendingCount < UINT_MAX );
this->engine.cancelPendingCount++;
{
@@ -390,9 +334,11 @@ ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
}
else {
if ( this->engine.pCurrent == this ) {
// cancel from callback, or while lookup in progress
this->engine.pCurrent = 0;
}
else {
// cancel before lookup starts
this->engine.labor.remove ( *this );
}
this->pending = false;