330 lines
7.7 KiB
C++
330 lines
7.7 KiB
C++
/*************************************************************************\
|
|
* 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 <stddef.h>
|
|
#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<timerForOldFdmgr> {
|
|
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 <timerForOldFdmgr> resTbl;
|
|
oldFdmgr ( const oldFdmgr & );
|
|
oldFdmgr & operator = ( const oldFdmgr & );
|
|
};
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning ( push )
|
|
# pragma warning ( disable:4660 )
|
|
#endif
|
|
|
|
template class chronIntIdResTable <timerForOldFdmgr>;
|
|
template class resTable<timerForOldFdmgr, chronIntId>;
|
|
|
|
#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 <const double> (uSecPerSec);
|
|
oldFdmgr *pfdm = static_cast <oldFdmgr *> (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 <oldFdmgr *> (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 <oldFdmgr *> (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 <oldFdmgr *> (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 <oldFdmgr *> (pfdctx);
|
|
double delay = ptimeout->tv_sec + ptimeout->tv_usec / static_cast <const double> (uSecPerSec);
|
|
|
|
try {
|
|
pfdm->process (delay);
|
|
}
|
|
catch (...) {
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern "C" LIBCOM_API int epicsStdCall fdmgr_delete (fdctx *pfdctx)
|
|
{
|
|
oldFdmgr *pfdm = static_cast <oldFdmgr *> (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);
|
|
}
|