/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * SPDX-License-Identifier: EPICS * EPICS Base is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ // // File descriptor management C++ class library // (for multiplexing IO in a single threaded environment) // // Author Jeffrey O. Hill // johill@lanl.gov // 505 665 1831 // // 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 // #include #include "locationException.h" #include "epicsAssert.h" #include "fdManager.h" #include "fdmgr.h" static const fdRegType fdiToFdRegType[] = {fdrRead, fdrWrite, fdrException}; static const unsigned fdiToFdRegTypeNElements = sizeof (fdiToFdRegType) / sizeof (fdiToFdRegType[0]); const unsigned mSecPerSec = 1000u; const unsigned uSecPerSec = 1000u * mSecPerSec; class fdRegForOldFdmgr : public fdReg { public: // // exceptions // class noFunctionSpecified {}; LIBCOM_API fdRegForOldFdmgr (SOCKET fdIn, fdRegType type, bool onceOnly, fdManager &manager, pCallBackFDMgr pFunc, void *pParam); LIBCOM_API ~fdRegForOldFdmgr (); private: pCallBackFDMgr pFunc; void *pParam; LIBCOM_API virtual void callBack (); fdRegForOldFdmgr ( const fdRegForOldFdmgr & ); fdRegForOldFdmgr & operator = ( const fdRegForOldFdmgr & ); }; class oldFdmgr; // // timerForOldFdmgr // class timerForOldFdmgr : public epicsTimerNotify, public chronIntIdRes { public: LIBCOM_API timerForOldFdmgr (oldFdmgr &fdmgr, double delay, pCallBackFDMgr pFunc, void *pParam); LIBCOM_API virtual ~timerForOldFdmgr (); // // exceptions // class noFunctionSpecified {}; private: epicsTimer &timer; oldFdmgr &fdmgr; pCallBackFDMgr pFunc; void *pParam; unsigned id; LIBCOM_API expireStatus expire ( const epicsTime & currentTime ); timerForOldFdmgr ( const timerForOldFdmgr & ); timerForOldFdmgr & operator = ( const timerForOldFdmgr & ); }; class oldFdmgr : public fdManager { friend class timerForOldFdmgr; friend LIBCOM_API int epicsStdCall fdmgr_clear_timeout (fdctx *pfdctx, fdmgrAlarmId id); public: oldFdmgr (); private: chronIntIdResTable resTbl; oldFdmgr ( const oldFdmgr & ); oldFdmgr & operator = ( const oldFdmgr & ); }; #ifdef _MSC_VER # pragma warning ( push ) # pragma warning ( disable:4660 ) #endif template class chronIntIdResTable ; template class resTable; #ifdef _MSC_VER # pragma warning ( pop ) #endif LIBCOM_API fdRegForOldFdmgr::fdRegForOldFdmgr (const SOCKET fdIn, const fdRegType typeIn, const bool onceOnlyIn, fdManager &managerIn, pCallBackFDMgr pFuncIn, void *pParamIn) : fdReg (fdIn, typeIn, onceOnlyIn, managerIn), pFunc (pFuncIn), pParam (pParamIn) { if (pFuncIn==NULL) { throwWithLocation ( noFunctionSpecified () ); } } LIBCOM_API fdRegForOldFdmgr::~fdRegForOldFdmgr () {} LIBCOM_API void fdRegForOldFdmgr::callBack () { (*this->pFunc) (this->pParam); } timerForOldFdmgr::timerForOldFdmgr ( oldFdmgr &fdmgrIn, double delayIn, pCallBackFDMgr pFuncIn, void * pParamIn ) : timer ( fdmgrIn.createTimer() ), fdmgr ( fdmgrIn ), pFunc ( pFuncIn ), pParam( pParamIn ) { if ( pFuncIn == NULL ) { throwWithLocation ( noFunctionSpecified () ); } this->fdmgr.resTbl.idAssignAdd (*this); this->timer.start ( *this, delayIn ); } timerForOldFdmgr::~timerForOldFdmgr () { this->fdmgr.resTbl.remove ( this->getId() ); this->timer.destroy (); } epicsTimerNotify::expireStatus timerForOldFdmgr::expire ( const epicsTime & ) { (*this->pFunc) (this->pParam); return noRestart; } oldFdmgr::oldFdmgr () {} extern "C" LIBCOM_API fdctx * epicsStdCall fdmgr_init (void) { oldFdmgr *pfdm; try { pfdm = new oldFdmgr(); } catch (...) { pfdm = NULL; } return (fdctx *) pfdm; } extern "C" LIBCOM_API fdmgrAlarmId epicsStdCall fdmgr_add_timeout ( fdctx *pfdctx, struct timeval *ptimeout, pCallBackFDMgr pFunc, void *pParam) { double delay = ptimeout->tv_sec + ptimeout->tv_usec / static_cast (uSecPerSec); oldFdmgr *pfdm = static_cast (pfdctx); timerForOldFdmgr *pTimer; unsigned id = fdmgrNoAlarm; if (!pfdm) { return fdmgrNoAlarm; } while (true) { try { pTimer = new timerForOldFdmgr (*pfdm, delay, pFunc, pParam); } catch (...) { pTimer = NULL; } if (pTimer) { id = pTimer->getId (); if (id!=fdmgrNoAlarm) { break; } else { delete pTimer; } } else { break; } } return id; } extern "C" LIBCOM_API int epicsStdCall fdmgr_clear_timeout (fdctx *pfdctx, fdmgrAlarmId id) { oldFdmgr *pfdm = static_cast (pfdctx); timerForOldFdmgr *pTimer; try { pTimer = pfdm->resTbl.remove (id); } catch (...) { pTimer = NULL; } if (pTimer==NULL) { return -1; } delete pTimer; return 0; } extern "C" LIBCOM_API int epicsStdCall fdmgr_add_callback ( fdctx *pfdctx, SOCKET fd, enum fdi_type fdi, pCallBackFDMgr pFunc, void *pParam) { oldFdmgr *pfdm = static_cast (pfdctx); fdRegForOldFdmgr *pfdrbc; bool onceOnly = (fdi==fdi_write); unsigned fdiType; if (pfdm==NULL) { return -1; } if (pFunc==NULL) { return -1; } if (fdi<0) { return -1; } fdiType = (unsigned) fdi; if (fdiType>=fdiToFdRegTypeNElements) { return -1; } try { pfdrbc = new fdRegForOldFdmgr (fd, fdiToFdRegType[fdiType], onceOnly, *pfdm, pFunc, pParam); } catch (...) { pfdrbc = NULL; } if (pfdrbc==NULL) { return -1; } else { return 0; } } extern "C" LIBCOM_API int epicsStdCall fdmgr_clear_callback ( fdctx *pfdctx, SOCKET fd, enum fdi_type fdi) { oldFdmgr *pfdm = static_cast (pfdctx); fdReg *pFDR; if (pfdm==NULL) { return -1; } try { pFDR = pfdm->lookUpFD (fd, fdiToFdRegType[fdi]); } catch (...) { pFDR = NULL; } if (pFDR==NULL) { return -1; } else { delete pFDR; return 0; } } extern "C" LIBCOM_API int epicsStdCall fdmgr_pend_event (fdctx *pfdctx, struct timeval *ptimeout) { oldFdmgr *pfdm = static_cast (pfdctx); double delay = ptimeout->tv_sec + ptimeout->tv_usec / static_cast (uSecPerSec); try { pfdm->process (delay); } catch (...) { return -1; } return 0; } extern "C" LIBCOM_API int epicsStdCall fdmgr_delete (fdctx *pfdctx) { oldFdmgr *pfdm = static_cast (pfdctx); delete pfdm; return 0; } /* * deprecated interface */ extern "C" LIBCOM_API int epicsStdCall fdmgr_clear_fd (fdctx *pfdctx, SOCKET fd) { return fdmgr_clear_callback(pfdctx, fd, fdi_read); } /* * deprecated interface */ extern "C" LIBCOM_API int epicsStdCall fdmgr_add_fd ( fdctx *pfdctx, SOCKET fd, void (*pfunc)(void *pParam), void *param) { return fdmgr_add_callback (pfdctx, fd, fdi_read, pfunc, param); }