From 02df98b82c5f3744c376552e733fc8b95bf395e4 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Fri, 25 Aug 2000 01:25:25 +0000 Subject: [PATCH] first cut --- src/libCom/misc/ipAddrToAsciiAsynchronous.cpp | 130 ++++++++++++++++++ src/libCom/misc/ipAddrToAsciiAsynchronous.h | 83 +++++++++++ 2 files changed, 213 insertions(+) create mode 100644 src/libCom/misc/ipAddrToAsciiAsynchronous.cpp create mode 100644 src/libCom/misc/ipAddrToAsciiAsynchronous.h diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp new file mode 100644 index 000000000..86658f781 --- /dev/null +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.cpp @@ -0,0 +1,130 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + */ + +#define epicsExportSharedSymbols +#include "osiThread.h" +#include "ipAddrToAsciiAsynchronous.h" + +osiMutex ipAddrToAsciiEngine::mutex; + +ipAddrToAsciiEngine::ipAddrToAsciiEngine ( const char *pName ) : + osiThread ( pName, 0x1000, threadPriorityLow ), nextId ( 0u ), + exitFlag ( false ) +{ + this->start (); // start the thread +} + +ipAddrToAsciiEngine::~ipAddrToAsciiEngine () +{ + ipAddrToAsciiAsynchronous * pItem = this->labor.first (); + + this->event.signal (); + this->exitFlag = true; + this->threadExit.wait (); + + // force IO completion for any items that remain + ipAddrToAsciiEngine::mutex.lock (); + while ( ( pItem = this->labor.first () ) ) { + pItem->pEngine = 0u; + sockAddrToA ( &pItem->addr.sa, this->nameTmp, + sizeof ( this->nameTmp ) ); + pItem->ioCompletionNotify ( this->nameTmp ); + } + ipAddrToAsciiEngine::mutex.unlock (); +} + +void ipAddrToAsciiEngine::entryPoint () +{ + osiSockAddr addr; + unsigned id; + + while ( ! this->exitFlag ) { + while ( true ) { + ipAddrToAsciiEngine::mutex.lock (); + ipAddrToAsciiAsynchronous * pItem = this->labor.first (); + if ( pItem ) { + addr = pItem->addr; + id = pItem->id; + } + else { + this->mutex.unlock (); + break; + } + ipAddrToAsciiEngine::mutex.unlock (); + + // knowing DNS, this could take a very long time + sockAddrToA ( &addr.sa, this->nameTmp, sizeof ( this->nameTmp ) ); + + ipAddrToAsciiEngine::mutex.lock (); + pItem = this->labor.get (); + if ( pItem ) { + if ( id == pItem->id ) { + pItem->ioCompletionNotify ( this->nameTmp ); + pItem->pEngine = 0u; + } + else { + this->labor.push ( *pItem ); + } + } + else { + ipAddrToAsciiEngine::mutex.unlock (); + break; + } + ipAddrToAsciiEngine::mutex.unlock (); + } + this->event.wait (); + } + this->threadExit.signal (); +} + +ipAddrToAsciiAsynchronous::ipAddrToAsciiAsynchronous + ( const osiSockAddr &addrIn ) : + addr ( addrIn ), pEngine ( 0u ) +{ +} + +ipAddrToAsciiAsynchronous::~ipAddrToAsciiAsynchronous () +{ + ipAddrToAsciiEngine::mutex.lock (); + if ( this->pEngine ) { + this->pEngine->labor.remove ( *this ); + } + ipAddrToAsciiEngine::mutex.unlock (); +} + +epicsShareFunc bool ipAddrToAsciiAsynchronous::ioInitiate ( ipAddrToAsciiEngine &engine ) +{ + bool success; + + ipAddrToAsciiEngine::mutex.lock (); + // put some reasonable limit on queue expansion + if ( engine.labor.count () < 16u ) { + this->id = engine.nextId++; + this->pEngine = &engine; + engine.labor.add ( *this ); + success = true; + } + else { + success = false; + } + ipAddrToAsciiEngine::mutex.unlock (); + + if ( success ) { + engine.event.signal (); + } + + return success; +} diff --git a/src/libCom/misc/ipAddrToAsciiAsynchronous.h b/src/libCom/misc/ipAddrToAsciiAsynchronous.h new file mode 100644 index 000000000..786120117 --- /dev/null +++ b/src/libCom/misc/ipAddrToAsciiAsynchronous.h @@ -0,0 +1,83 @@ + +/* + * $Id$ + * + * + * L O S A L A M O S + * Los Alamos National Laboratory + * Los Alamos, New Mexico 87545 + * + * Copyright, 1986, The Regents of the University of California. + * + * + * Author Jeffrey O. Hill + * johill@lanl.gov + */ + +#ifndef ipAddrToAsciiAsynchronous_h +#define ipAddrToAsciiAsynchronous_h + +#include "osiMutex.h" +#include "osiSock.h" +#include "tsDLList.h" +#include "shareLib.h" + +class ipAddrToAsciiAsynchronous; + +// - this class executes the synchronous DNS query +// - it creates one thread +class ipAddrToAsciiEngine : public osiThread { +public: + epicsShareFunc ipAddrToAsciiEngine ( const char *pName ); + epicsShareFunc ~ipAddrToAsciiEngine (); +private: + tsDLList < ipAddrToAsciiAsynchronous > labor; + osiEvent event; + osiEvent threadExit; + char nameTmp [1024]; + unsigned nextId; + bool exitFlag; + static osiMutex mutex; + void entryPoint (); + friend class ipAddrToAsciiAsynchronous; +}; + +// - this class implements the asynchronous DNS query +// - it completes early with the host name in dotted IP address form +// if the ipAddrToAsciiEngine is destroyed before IO completion +// - ioInitiate fails if there are too many items already in +// the engine's queue. +// +class ipAddrToAsciiAsynchronous : + public tsDLNode < ipAddrToAsciiAsynchronous > { +public: + epicsShareFunc ipAddrToAsciiAsynchronous ( const osiSockAddr &addr ); + epicsShareFunc virtual ~ipAddrToAsciiAsynchronous (); + epicsShareFunc bool ioInitiate ( ipAddrToAsciiEngine &engine ); + epicsShareFunc bool identicalAddress ( const osiSockAddr &addr ) const; + epicsShareFunc osiSockAddr address () const; + virtual void ioCompletionNotify ( const char *pHostName ) = 0; +private: + osiSockAddr addr; + ipAddrToAsciiEngine *pEngine; + unsigned id; + friend class ipAddrToAsciiEngine; +}; + +inline osiSockAddr ipAddrToAsciiAsynchronous::address () const +{ + return this->addr; +} + +inline bool ipAddrToAsciiAsynchronous::identicalAddress ( const osiSockAddr &addrIn ) const +{ + if ( this->addr.sa.sa_family == AF_INET && addrIn.sa.sa_family == AF_INET ) { + return this->addr.ia.sin_addr.s_addr == addrIn.ia.sin_addr.s_addr && + this->addr.ia.sin_port == addrIn.ia.sin_port; + } + else { + return false; + } +} + +#endif // ifdef ipAddrToAsciiAsynchronous_h