From 2ec12266ad1cf19a7fdb1763adb56fedfdd72fd9 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Tue, 13 Aug 1996 22:48:25 +0000 Subject: [PATCH] dfMgr =>fdManager --- src/libCom/Makefile.Unix | 6 +- src/libCom/Makefile.Vx | 15 +- src/libCom/{fdMgr.cc => fdManager.cc} | 28 ++-- src/libCom/{fdMgr.h => fdManager.h} | 47 +++--- src/libCom/fdmgr/fdManager.cpp | 210 ++++++++++++++++++++++++ src/libCom/fdmgr/fdManager.h | 219 ++++++++++++++++++++++++++ 6 files changed, 477 insertions(+), 48 deletions(-) rename src/libCom/{fdMgr.cc => fdManager.cc} (86%) rename src/libCom/{fdMgr.h => fdManager.h} (83%) create mode 100644 src/libCom/fdmgr/fdManager.cpp create mode 100644 src/libCom/fdmgr/fdManager.h diff --git a/src/libCom/Makefile.Unix b/src/libCom/Makefile.Unix index 6cfec714e..1fd29dbff 100644 --- a/src/libCom/Makefile.Unix +++ b/src/libCom/Makefile.Unix @@ -18,7 +18,7 @@ INC += memDebugLib.h INC += tsDefs.h INC += bucketLib.h INC += pal.h -INC += fdMgr.h +INC += fdManager.h INC += osiTime.h INC += osiTimer.h INC += macLib.h @@ -42,7 +42,7 @@ SRCS.c += ../postfix.c SRCS.c += ../realpath.c SRCS.c += ../tsSubr.c SRCS.c += ../assertUNIX.c -SRCS.c += ../fdMgr.cc +SRCS.c += ../fdManager.cc SRCS.c += ../osiTimer.cc SRCS.c += ../osiTimeOSD.cc SRCS.c += ../macCore.c @@ -67,7 +67,7 @@ LIBOBJS += postfix.o LIBOBJS += realpath.o LIBOBJS += tsSubr.o LIBOBJS += assertUNIX.o -LIBOBJS += fdMgr.o +LIBOBJS += fdManager.o LIBOBJS += osiTimer.o LIBOBJS += osiTimeOSD.o LIBOBJS += macCore.o diff --git a/src/libCom/Makefile.Vx b/src/libCom/Makefile.Vx index 54f1e0d0a..df9a0c94a 100644 --- a/src/libCom/Makefile.Vx +++ b/src/libCom/Makefile.Vx @@ -66,14 +66,23 @@ include $(TOP)/config/RULES.Vx clean:: @$(RM) errSymTbl.c envData.c +# In principle the simplified scripts in ../WIN32 +# should work on all archs, but I decided to +# keep the "originals" for now. -kuk- +ifeq ($(HOST_ARCH),WIN32) +TOOLDIR=../WIN32 +else +TOOLDIR=.. +endif + envData.c: ../envDefs.h $(TOP)/config/CONFIG_ENV \ $(TOP)/config/CONFIG_SITE_ENV - ../bldEnvData $(TOP)/config + $(TOOLDIR)/bldEnvData $(TOP)/config errSymTbl.o: errSymTbl.c $(COMPILE.c) -o $@ $< errSymTbl.c: $(ERR_S_FILES) - @/bin/rm -f errSymTbl.c ;\ - ../makeStatTbl $(ERR_S_FILES) >errSymTbl.c + @$(RM) errSymTbl.c ;\ + $(TOOLDIR)/makeStatTbl $(ERR_S_FILES) >errSymTbl.c diff --git a/src/libCom/fdMgr.cc b/src/libCom/fdManager.cc similarity index 86% rename from src/libCom/fdMgr.cc rename to src/libCom/fdManager.cc index 58b981b81..952aa94f2 100644 --- a/src/libCom/fdMgr.cc +++ b/src/libCom/fdManager.cc @@ -2,18 +2,8 @@ // // $Id$ // -// File descriptor management C++ class library // // $Log$ -// Revision 1.3 1996/07/24 23:01:03 jhill -// use iter.remove() -// -// Revision 1.2 1996/07/09 23:02:05 jhill -// mark fd entry in limbo during delete -// -// Revision 1.1 1996/06/21 01:08:53 jhill -// add fdMgr.h fdMgr.cc -// // // @@ -39,10 +29,10 @@ } //extern "C" #endif // __GNUC__ -#include +#include #include -fdMgr fileDescriptorManager; +fdManager fileDescriptorManager; inline int selectErrno() { @@ -50,9 +40,9 @@ inline int selectErrno() } // -// fdMgr::fdMgr() +// fdManager::fdManager() // -fdMgr::fdMgr() +fdManager::fdManager() { FD_ZERO (&this->read); FD_ZERO (&this->write); @@ -63,9 +53,9 @@ fdMgr::fdMgr() } // -// fdMgr::~fdMgr() +// fdManager::~fdManager() // -fdMgr::~fdMgr() +fdManager::~fdManager() { fdReg *pReg; @@ -80,9 +70,9 @@ fdMgr::~fdMgr() } // -// fdMgr::process() +// fdManager::process() // -void fdMgr::process (const osiTime &delay) +void fdManager::process (const osiTime &delay) { tsDLIter regIter(this->regList); osiTime minDelay; @@ -135,7 +125,7 @@ void fdMgr::process (const osiTime &delay) } else { fprintf(stderr, - "fdMgr: select failed because \"%s\"\n", + "fdManager: select failed because \"%s\"\n", strerror(selectErrno())); } } diff --git a/src/libCom/fdMgr.h b/src/libCom/fdManager.h similarity index 83% rename from src/libCom/fdMgr.h rename to src/libCom/fdManager.h index 588a4f9f8..a73b1e010 100644 --- a/src/libCom/fdMgr.h +++ b/src/libCom/fdManager.h @@ -32,22 +32,23 @@ * * History * $Log$ - * Revision 1.1 1996/06/21 01:08:54 jhill - * add fdMgr.h fdMgr.cc - * * */ -#ifndef fdMgrH_included -#define fdMgrH_included +#ifndef fdManagerH_included +#define fdManagerH_included #include #include +#ifdef WIN32 +#include +#else extern "C" { # include # include } // extern "C" +#endif #include @@ -59,7 +60,7 @@ enum fdRegState {fdrActive, fdrPending, fdrLimbo}; // file descriptor registration // class fdReg : public tsDLNode { - friend class fdMgr; + friend class fdManager; public: fdReg (const int fdIn, const fdRegType typ, const unsigned onceOnly=0); @@ -71,7 +72,7 @@ private: // // called when there is activity on the fd // NOTES - // 1) the fdMgr will call this only once during the + // 1) the fdManager will call this only once during the // lifetime of a fdReg object if the constructor // specified "onceOnly" // @@ -79,7 +80,7 @@ private: // // Called by the file descriptor manager: - // 1) If the fdMgr is deleted and there are still + // 1) If the fdManager is deleted and there are still // fdReg objects attached // 2) Immediately after calling "callBack()" if // the constructor specified "onceOnly" @@ -94,11 +95,11 @@ private: unsigned char onceOnly; }; -class fdMgr { +class fdManager { friend class fdReg; public: - fdMgr(); - ~fdMgr(); + fdManager(); + ~fdManager(); void process (const osiTime &delay); private: tsDLList regList; @@ -119,13 +120,13 @@ private: fd_set *pFDSet (fdRegType typIn); }; -extern fdMgr fileDescriptorManager; +extern fdManager fileDescriptorManager; // -// fdMgrMaxInt () +// fdManagerMaxInt () // -inline int fdMgrMaxInt (int a, int b) +inline int fdManagerMaxInt (int a, int b) { if (a>b) { return a; @@ -136,9 +137,9 @@ inline int fdMgrMaxInt (int a, int b) } // -// fdMgr::pFDSet() +// fdManager::pFDSet() // -inline fd_set *fdMgr::pFDSet (fdRegType typIn) +inline fd_set *fdManager::pFDSet (fdRegType typIn) { fd_set *pSet; @@ -159,22 +160,22 @@ inline fd_set *fdMgr::pFDSet (fdRegType typIn) } // -// fdMgr::installReg() +// fdManager::installReg() // -inline void fdMgr::installReg (fdReg ®) +inline void fdManager::installReg (fdReg ®) { - this->maxFD = fdMgrMaxInt(this->maxFD, reg.fd+1); + this->maxFD = fdManagerMaxInt(this->maxFD, reg.fd+1); this->regList.add(reg); reg.state = fdrPending; } // -// fdMgr::removeReg() +// fdManager::removeReg() // -inline void fdMgr::removeReg(fdReg ®) +inline void fdManager::removeReg(fdReg ®) { // - // signal fdMgr that the fdReg was deleted + // signal fdManager that the fdReg was deleted // during the call back // if (this->pCBReg == ®) { @@ -214,5 +215,5 @@ inline fdReg::fdReg (const int fdIn, const fdRegType typIn, fileDescriptorManager.installReg(*this); } -#endif // fdMgrH_included +#endif // fdManagerH_included diff --git a/src/libCom/fdmgr/fdManager.cpp b/src/libCom/fdmgr/fdManager.cpp new file mode 100644 index 000000000..952aa94f2 --- /dev/null +++ b/src/libCom/fdmgr/fdManager.cpp @@ -0,0 +1,210 @@ + +// +// $Id$ +// +// +// $Log$ +// + +// +// +// NOTES: +// 1) This isnt intended for a multi-threading environment +// +// + +// +// ANSI C +// +#include +#include +#include + +#if __GNUC__ + extern "C" { +# include + int select (int, fd_set *, fd_set *, + fd_set *, struct timeval *); + int bzero (char *b, int length); + } //extern "C" +#endif // __GNUC__ + +#include +#include + +fdManager fileDescriptorManager; + +inline int selectErrno() +{ + return errno; +} + +// +// fdManager::fdManager() +// +fdManager::fdManager() +{ + FD_ZERO (&this->read); + FD_ZERO (&this->write); + FD_ZERO (&this->exception); + this->maxFD = 0; + this->processInProg = 0; + this->pCBReg = 0; +} + +// +// fdManager::~fdManager() +// +fdManager::~fdManager() +{ + fdReg *pReg; + + while ( (pReg = this->regList.get()) ) { + pReg->state = fdrLimbo; + pReg->destroy(); + } + while ( (pReg = this->activeList.get()) ) { + pReg->state = fdrLimbo; + pReg->destroy(); + } +} + +// +// fdManager::process() +// +void fdManager::process (const osiTime &delay) +{ + tsDLIter regIter(this->regList); + osiTime minDelay; + osiTime zeroDelay; + fdReg *pReg; + struct timeval tv; + int status; + + // + // no recursion + // + if (this->processInProg) { + return; + } + this->processInProg = 1; + + while ( (pReg=regIter()) ) { + FD_SET(pReg->fd, &pReg->fdSet); + } + + // + // dont bother calling select if the delay to + // the first timer expire is zero + // + while (1) { + minDelay = staticTimerQueue.delayToFirstExpire(); + if (zeroDelay>=minDelay) { + staticTimerQueue.process(); + } + else { + break; + } + } + + if (minDelay>=delay) { + minDelay = delay; + } + minDelay.getTV (tv.tv_sec, tv.tv_usec); + status = select (this->maxFD, &this->read, + &this->write, &this->exception, &tv); + staticTimerQueue.process(); + if (status==0) { + this->processInProg = 0; + return; + } + else if (status<0) { + if (selectErrno() == EINTR) { + this->processInProg = 0; + return; + } + else { + fprintf(stderr, + "fdManager: select failed because \"%s\"\n", + strerror(selectErrno())); + } + } + + // + // Look for activity + // + regIter.reset(); + while ( (pReg=regIter()) ) { + if (FD_ISSET(pReg->fd, &pReg->fdSet)) { + FD_CLR(pReg->fd, &pReg->fdSet); + regIter.remove(); + this->activeList.add(*pReg); + pReg->state = fdrActive; + } + } + + // + // I am careful to prevent problems if they access the + // above list while in a "callBack()" routine + // + while ( (pReg = this->activeList.get()) ) { + pReg->state = fdrLimbo; + + // + // Tag current reg so that we + // can detect if it was deleted + // during the call back + // + this->pCBReg = pReg; + pReg->callBack(); + if (this->pCBReg == pReg) { + this->pCBReg = 0; + if (pReg->onceOnly) { + pReg->destroy(); + } + else { + this->regList.add(*pReg); + pReg->state = fdrPending; + } + } + else { + // + // no recursive calls to process allowed + // + assert(this->pCBReg == 0); + } + } + this->processInProg = 0; +} + +// +// fdReg::destroy() +// (default destroy method) +// +void fdReg::destroy() +{ + delete this; +} + +// +// fdReg::~fdReg() +// +fdReg::~fdReg() +{ + fileDescriptorManager.removeReg(*this); +} + +// +// fdReg::show() +// +void fdReg::show(unsigned level) +{ + printf ("fdReg at %x\n", (unsigned) this); + if (level>1u) { + printf ("\tfd = %d, fdSet at %x, state = %d, onceOnly = %d\n", + this->fd, (unsigned)&this->fdSet, + this->state, this->onceOnly); + } +} + + diff --git a/src/libCom/fdmgr/fdManager.h b/src/libCom/fdmgr/fdManager.h new file mode 100644 index 000000000..a73b1e010 --- /dev/null +++ b/src/libCom/fdmgr/fdManager.h @@ -0,0 +1,219 @@ +/* + * $Id$ + * + * File descriptor management C++ class library + * (for multiplexing IO in a single threaded environment) + * + * Author Jeffrey O. Hill + * johill@lanl.gov + * 505 665 1831 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * + * History + * $Log$ + * + */ + +#ifndef fdManagerH_included +#define fdManagerH_included + +#include +#include + +#ifdef WIN32 +#include +#else +extern "C" { +# include +# include +} // extern "C" +#endif + +#include + +enum fdRegType {fdrRead, fdrWrite, fdrExcp}; +enum fdRegState {fdrActive, fdrPending, fdrLimbo}; + +// +// fdReg +// file descriptor registration +// +class fdReg : public tsDLNode { + friend class fdManager; +public: + fdReg (const int fdIn, const fdRegType typ, + const unsigned onceOnly=0); + virtual ~fdReg (); + + virtual void show(unsigned level); +private: + + // + // called when there is activity on the fd + // NOTES + // 1) the fdManager will call this only once during the + // lifetime of a fdReg object if the constructor + // specified "onceOnly" + // + virtual void callBack ()=0; + + // + // Called by the file descriptor manager: + // 1) If the fdManager is deleted and there are still + // fdReg objects attached + // 2) Immediately after calling "callBack()" if + // the constructor specified "onceOnly" + // + // fdReg::destroy() does a "delete this" + // + virtual void destroy (); + + const int fd; + fd_set &fdSet; + unsigned char state; // fdRegState goes here + unsigned char onceOnly; +}; + +class fdManager { +friend class fdReg; +public: + fdManager(); + ~fdManager(); + void process (const osiTime &delay); +private: + tsDLList regList; + tsDLList activeList; + fd_set read; + fd_set write; + fd_set exception; + int maxFD; + unsigned processInProg; + // + // Set to fdreg when in call back + // and nill ortherwise + // + fdReg *pCBReg; + + void installReg (fdReg ®); + void removeReg (fdReg ®); + fd_set *pFDSet (fdRegType typIn); +}; + +extern fdManager fileDescriptorManager; + + +// +// fdManagerMaxInt () +// +inline int fdManagerMaxInt (int a, int b) +{ + if (a>b) { + return a; + } + else { + return b; + } +} + +// +// fdManager::pFDSet() +// +inline fd_set *fdManager::pFDSet (fdRegType typIn) +{ + fd_set *pSet; + + switch (typIn) { + case fdrRead: + pSet = &this->read; + break; + case fdrWrite: + pSet = &this->write; + break; + case fdrExcp: + pSet = &this->exception; + break; + default: + assert(0); + } + return pSet; +} + +// +// fdManager::installReg() +// +inline void fdManager::installReg (fdReg ®) +{ + this->maxFD = fdManagerMaxInt(this->maxFD, reg.fd+1); + this->regList.add(reg); + reg.state = fdrPending; +} + +// +// fdManager::removeReg() +// +inline void fdManager::removeReg(fdReg ®) +{ + // + // signal fdManager that the fdReg was deleted + // during the call back + // + if (this->pCBReg == ®) { + this->pCBReg = 0; + } + FD_CLR(reg.fd, ®.fdSet); + switch (reg.state) { + case fdrActive: + this->activeList.remove(reg); + reg.state = fdrLimbo; + break; + case fdrPending: + this->regList.remove(reg); + reg.state = fdrLimbo; + break; + case fdrLimbo: + break; + default: + assert(0); + } +} + +// +// fdReg::fdReg() +// +inline fdReg::fdReg (const int fdIn, const fdRegType typIn, + const unsigned onceOnlyIn) : + fd(fdIn), fdSet(*fileDescriptorManager.pFDSet(typIn)), + state(fdrLimbo), onceOnly(onceOnlyIn) +{ + assert (this->fd>=0); + if (this->fd>FD_SETSIZE) { + fprintf (stderr, "%s: fd > FD_SETSIZE ignored\n", + __FILE__); + return; + } + fileDescriptorManager.installReg(*this); +} + +#endif // fdManagerH_included +