// // $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 // // NOTES: // 1) the routines in this file provide backward compatibility with the original // "C" based file descriptor manager API // 2) This library is not thread safe // #define epicsExportSharedSymbols #include "epicsAssert.h" #include "osiTimer.h" #include "fdManager.h" #include "fdmgr.h" static const fdRegType fdiToFdRegType[] = {fdrRead, fdrWrite, fdrException}; static const unsigned fdiToFdRegTypeNElements = sizeof (fdiToFdRegType) / sizeof (fdiToFdRegType[0]); class fdRegForOldFdmgr : public fdReg { public: // // exceptions // class noFunctionSpecified {}; class doubleDelete {}; epicsShareFunc fdRegForOldFdmgr (const SOCKET fdIn, const fdRegType type, const bool onceOnly, fdManager &manager, void (*pFunc) (void *pParam), void *pParam); epicsShareFunc ~fdRegForOldFdmgr (); private: void (*pFunc) (void *pParam); void *pParam; epicsShareFunc virtual void callBack (); }; epicsShareFunc fdRegForOldFdmgr::fdRegForOldFdmgr (const SOCKET fdIn, const fdRegType typeIn, const bool onceOnlyIn, fdManager &managerIn, void (*pFuncIn) (void *pParam), void *pParamIn) : fdReg (fdIn, typeIn, onceOnlyIn, managerIn), pFunc (pFuncIn), pParam (pParamIn) { if (pFuncIn==NULL) { # ifdef noExceptionsFromCXX assert (0); # else throw noFunctionSpecified (); # endif } } epicsShareFunc fdRegForOldFdmgr::~fdRegForOldFdmgr () { if (this->pFunc==NULL) { # ifdef noExceptionsFromCXX assert (0); # else throw doubleDelete (); # endif } } epicsShareFunc void fdRegForOldFdmgr::callBack () { (*this->pFunc) (this->pParam); } class oldFdmgr : public fdManager { friend class osiTimerForOldFdmgr; friend extern epicsShareFunc int epicsShareAPI fdmgr_clear_timeout (fdctx *pfdctx, fdmgrAlarmId id); public: oldFdmgr (); private: chronIntIdResTable resTbl; }; // // osiTimer // class osiTimerForOldFdmgr : public osiTimer, public chronIntIdRes { public: // // exceptions // class noFunctionSpecified {}; class doubleDelete {}; // // create an active timer that will expire in delay seconds // epicsShareFunc osiTimerForOldFdmgr (oldFdmgr &fdmgr, double delay, void (*pFunc) (void *pParam), void *pParam); epicsShareFunc ~osiTimerForOldFdmgr (); // // called when the osiTimer expires // epicsShareFunc virtual void expire(); // // for diagnostics // epicsShareFunc virtual const char *name() const; private: oldFdmgr &fdmgr; void (*pFunc) (void *pParam); void *pParam; unsigned id; }; osiTimerForOldFdmgr::osiTimerForOldFdmgr (oldFdmgr &fdmgrIn, double delayIn, void (*pFuncIn) (void *pParam), void *pParamIn) : fdmgr (fdmgrIn), osiTimer (delayIn, fdmgrIn.timerQueueRef ()), pFunc (pFuncIn), pParam(pParamIn) { if (pFuncIn==NULL) { # ifdef noExceptionsFromCXX assert (0); # else throw noFunctionSpecified (); # endif } this->fdmgr.resTbl.add (*this); } osiTimerForOldFdmgr::~osiTimerForOldFdmgr () { if (this->pFunc==NULL) { # ifdef noExceptionsFromCXX assert (0); # else throw doubleDelete (); # endif } this->pFunc = NULL; this->pParam = NULL; this->fdmgr.resTbl.remove (this->getId()); } void osiTimerForOldFdmgr::expire () { (*this->pFunc) (this->pParam); } const char * osiTimerForOldFdmgr::name () const { return "osiTimerForOldFdmgr"; } oldFdmgr::oldFdmgr () : resTbl (1024) { } extern "C" epicsShareFunc fdctx * epicsShareAPI fdmgr_init (void) { oldFdmgr *pfdm; # ifdef noExceptionsFromCXX pfdm = new oldFdmgr(); # else try { pfdm = new oldFdmgr(); } catch (...) { pfdm = NULL; } # endif return (fdctx *) pfdm; } extern "C" epicsShareFunc fdmgrAlarmId epicsShareAPI fdmgr_add_timeout ( fdctx *pfdctx, struct timeval *ptimeout, void (*pFunc)(void *pParam), void *pParam) { double delay = ptimeout->tv_sec + ptimeout->tv_usec / static_cast (osiTime::uSecPerSec); oldFdmgr *pfdm = static_cast (pfdctx); osiTimerForOldFdmgr *pTimer; unsigned id; if (!pfdm) { return fdmgrNoAlarm; } while (true) { # ifdef noExceptionsFromCXX pTimer = new osiTimerForOldFdmgr (*pfdm, delay, pFunc, pParam); # else try { pTimer = new osiTimerForOldFdmgr (*pfdm, delay, pFunc, pParam); } catch (...) { pTimer = NULL; } # endif if (pTimer) { id = pTimer->getId (); if (id!=fdmgrNoAlarm) { break; } else { delete pTimer; } } else { id = fdmgrNoAlarm; break; } } return id; } extern "C" epicsShareFunc int epicsShareAPI fdmgr_clear_timeout (fdctx *pfdctx, fdmgrAlarmId id) { oldFdmgr *pfdm = static_cast (pfdctx); osiTimerForOldFdmgr *pTimer; # ifdef noExceptionsFromCXX pTimer = pfdm->resTbl.remove (id); # else try { pTimer = pfdm->resTbl.remove (id); } catch (...) { pTimer = NULL; } # endif if (pTimer==NULL) { return -1; } else { delete pTimer; return 0; } } extern "C" epicsShareFunc int epicsShareAPI fdmgr_add_callback ( fdctx *pfdctx, SOCKET fd, enum fdi_type fdi, void (*pFunc)(void *pParam), void *pParam) { oldFdmgr *pfdm = static_cast (pfdctx); fdRegForOldFdmgr *pfdrbc; bool onceOnly = (fdi==fdi_write); if (pfdm==NULL) { return -1; } if (pFunc==NULL) { return -1; } if (fdi<0 || fdi>=fdiToFdRegTypeNElements) { return -1; } # ifdef noExceptionsFromCXX pfdrbc = new fdRegForOldFdmgr (fd, fdiToFdRegType[fdi], onceOnly, *pfdm, pFunc, pParam); # else try { pfdrbc = new fdRegForOldFdmgr (fd, fdiToFdRegType[fdi], onceOnly, *pfdm, pFunc, pParam); } catch (...) { pfdrbc = NULL; } # endif if (pfdrbc==NULL) { return -1; } else { return 0; } } extern "C" epicsShareFunc int epicsShareAPI fdmgr_clear_callback ( fdctx *pfdctx, SOCKET fd, enum fdi_type fdi) { oldFdmgr *pfdm = static_cast (pfdctx); fdReg *pFDR; if (pfdm==NULL) { return -1; } # ifdef noExceptionsFromCXX pFDR = pfdm->lookUpFD (fd, fdiToFdRegType[fdi]); # else try { pFDR = pfdm->lookUpFD (fd, fdiToFdRegType[fdi]); } catch (...) { pFDR = NULL; } # endif if (pFDR==NULL) { return -1; } else { delete pFDR; return 0; } } extern "C" epicsShareFunc int epicsShareAPI fdmgr_pend_event (fdctx *pfdctx, struct timeval *ptimeout) { oldFdmgr *pfdm = static_cast (pfdctx); double delay = ptimeout->tv_sec + ptimeout->tv_usec / static_cast (osiTime::uSecPerSec); # ifdef noExceptionsFromCXX pfdm->process (delay); # else try { pfdm->process (delay); } catch (...) { return -1; } # endif return 0; } extern "C" epicsShareFunc int epicsShareAPI fdmgr_delete (fdctx *pfdctx) { oldFdmgr *pfdm = static_cast (pfdctx); delete pfdm; return 0; } /* * depricated interface */ extern "C" epicsShareFunc int epicsShareAPI fdmgr_clear_fd (fdctx *pfdctx, SOCKET fd) { return fdmgr_clear_callback(pfdctx, fd, fdi_read); } /* * depricated interface */ extern "C" epicsShareFunc int epicsShareAPI fdmgr_add_fd ( fdctx *pfdctx, SOCKET fd, void (*pfunc)(void *pParam), void *param) { return fdmgr_add_callback (pfdctx, fd, fdi_read, pfunc, param); }