updated to reflect resource table API changes
This commit is contained in:
@@ -1,52 +1,38 @@
|
||||
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.14 1998/06/16 02:06:32 jhill
|
||||
// lazy init sock lib when its a static build & recoverfrom select differences in winsock
|
||||
//
|
||||
// Revision 1.13 1998/05/29 20:22:44 jhill
|
||||
// made hashing routine portable
|
||||
//
|
||||
// Revision 1.12 1998/02/05 21:12:09 jhill
|
||||
// removed questionable inline
|
||||
//
|
||||
// Revision 1.11 1997/08/05 00:37:00 jhill
|
||||
// removed warnings
|
||||
//
|
||||
// Revision 1.10 1997/06/25 05:45:49 jhill
|
||||
// cleaned up pc port
|
||||
//
|
||||
// Revision 1.9 1997/06/13 09:39:09 jhill
|
||||
// fixed warnings
|
||||
//
|
||||
// Revision 1.8 1997/05/29 21:37:38 tang
|
||||
// add ifdef for select call to support HP-UX
|
||||
//
|
||||
// Revision 1.7 1997/05/27 14:53:11 tang
|
||||
// fd_set cast in select for both Hp and Sun
|
||||
//
|
||||
// Revision 1.6 1997/05/08 19:49:12 tang
|
||||
// added int * cast in select for HP port compatibility
|
||||
//
|
||||
// Revision 1.5 1997/04/23 17:22:57 jhill
|
||||
// fixed WIN32 DLL symbol exports
|
||||
//
|
||||
// Revision 1.4 1997/04/10 19:45:33 jhill
|
||||
// API changes and include with not <>
|
||||
//
|
||||
// Revision 1.3 1996/11/02 02:04:42 jhill
|
||||
// fixed several subtle bugs
|
||||
//
|
||||
// Revision 1.2 1996/09/04 21:50:16 jhill
|
||||
// added hashed fd to fdi convert
|
||||
//
|
||||
// Revision 1.1 1996/08/13 22:48:23 jhill
|
||||
// dfMgr =>fdManager
|
||||
//
|
||||
//
|
||||
/*
|
||||
* $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
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
//
|
||||
@@ -67,8 +53,9 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#define instantiateRecourceLib
|
||||
#include "osiTimer.h"
|
||||
#include "fdManager.h"
|
||||
#include "osiSleep.h"
|
||||
#include "tsMinMax.h"
|
||||
#include "fdManager.h"
|
||||
#include "bsdSocketResource.h"
|
||||
|
||||
//
|
||||
@@ -83,7 +70,6 @@
|
||||
// This explicitly instantiates the template class's member
|
||||
// functions used by fdManager
|
||||
//
|
||||
//
|
||||
// instantiated by "fdManager fileDescriptorManager;" statement below?
|
||||
// (according to ms vis C++)
|
||||
//
|
||||
@@ -95,7 +81,8 @@ epicsShareDef fdManager fileDescriptorManager;
|
||||
//
|
||||
// fdManager::fdManager()
|
||||
//
|
||||
epicsShareFunc fdManager::fdManager()
|
||||
epicsShareFunc fdManager::fdManager() :
|
||||
fdTbl (1<<hashTableIndexBits)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@@ -107,12 +94,6 @@ epicsShareFunc fdManager::fdManager()
|
||||
this->maxFD = 0;
|
||||
this->processInProg = 0u;
|
||||
this->pCBReg = 0;
|
||||
//
|
||||
// should throw an exception here
|
||||
// when most compilers are implementing
|
||||
// exceptions
|
||||
//
|
||||
assert (this->fdTbl.init(0x100)>=0);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -123,11 +104,11 @@ epicsShareFunc fdManager::~fdManager()
|
||||
fdReg *pReg;
|
||||
|
||||
while ( (pReg = this->regList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
bsdSockRelease();
|
||||
@@ -136,13 +117,10 @@ epicsShareFunc fdManager::~fdManager()
|
||||
//
|
||||
// fdManager::process()
|
||||
//
|
||||
epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
epicsShareFunc void fdManager::process (double delay)
|
||||
{
|
||||
static const tsDLIterBD<fdReg> eol; // end of list
|
||||
tsDLIterBD<fdReg> iter;
|
||||
tsDLIterBD<fdReg> tmp;
|
||||
osiTime minDelay;
|
||||
osiTime zeroDelay;
|
||||
static const tsDLIterBD<fdReg> eol (0); // end of list
|
||||
double minDelay;
|
||||
fdReg *pReg;
|
||||
struct timeval tv;
|
||||
int status;
|
||||
@@ -163,23 +141,25 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
// more than once here so that fd activity get serviced
|
||||
// in a reasonable length of time.
|
||||
//
|
||||
minDelay = staticTimerQueue.delayToFirstExpire();
|
||||
if (zeroDelay>=minDelay) {
|
||||
staticTimerQueue.process();
|
||||
minDelay = staticTimerQueue.delayToFirstExpire();
|
||||
minDelay = osiDefaultTimerQueue.delayToFirstExpire();
|
||||
if (minDelay<=0.0) {
|
||||
osiDefaultTimerQueue.process();
|
||||
minDelay = osiDefaultTimerQueue.delayToFirstExpire();
|
||||
}
|
||||
|
||||
if (minDelay>=delay) {
|
||||
minDelay = delay;
|
||||
}
|
||||
|
||||
for (iter=this->regList.first(); iter!=eol; ++iter) {
|
||||
tsDLIterBD<fdReg> iter (this->regList.first());
|
||||
while (iter!=eol) {
|
||||
FD_SET(iter->getFD(), &this->fdSets[iter->getType()]);
|
||||
ioPending = 1;
|
||||
++iter;
|
||||
}
|
||||
|
||||
tv.tv_sec = minDelay.getSecTruncToLong ();
|
||||
tv.tv_usec = minDelay.getUSecTruncToLong ();
|
||||
tv.tv_sec = static_cast<long> (minDelay);
|
||||
tv.tv_usec = static_cast<long> ((minDelay-tv.tv_sec)*osiTime::uSecPerSec);
|
||||
|
||||
/*
|
||||
* win32 requires this (others will
|
||||
@@ -198,10 +178,10 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
}
|
||||
else {
|
||||
status = select (this->maxFD, &this->fdSets[fdrRead],
|
||||
&this->fdSets[fdrWrite], &this->fdSets[fdrExcp], &tv);
|
||||
&this->fdSets[fdrWrite], &this->fdSets[fdrException], &tv);
|
||||
}
|
||||
|
||||
staticTimerQueue.process();
|
||||
osiDefaultTimerQueue.process();
|
||||
if (status==0) {
|
||||
this->processInProg = 0;
|
||||
return;
|
||||
@@ -223,13 +203,13 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
//
|
||||
iter=this->regList.first();
|
||||
while (iter!=eol) {
|
||||
tmp = iter;
|
||||
tsDLIterBD<fdReg> tmp = iter;
|
||||
tmp++;
|
||||
if (FD_ISSET(iter->getFD(), &this->fdSets[iter->getType()])) {
|
||||
FD_CLR(iter->getFD(), &this->fdSets[iter->getType()]);
|
||||
this->regList.remove(*iter);
|
||||
this->activeList.add(*iter);
|
||||
iter->state = fdrActive;
|
||||
iter->state = fdReg::active;
|
||||
}
|
||||
iter=tmp;
|
||||
}
|
||||
@@ -239,10 +219,10 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
// above list while in a "callBack()" routine
|
||||
//
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
|
||||
//
|
||||
// Tag current reg so that we
|
||||
// Tag current fdReg so that we
|
||||
// can detect if it was deleted
|
||||
// during the call back
|
||||
//
|
||||
@@ -261,7 +241,7 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
}
|
||||
else {
|
||||
this->regList.add(*pReg);
|
||||
pReg->state = fdrPending;
|
||||
pReg->state = fdReg::pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +262,7 @@ epicsShareFunc void fdReg::destroy()
|
||||
//
|
||||
epicsShareFunc fdReg::~fdReg()
|
||||
{
|
||||
fileDescriptorManager.removeReg(*this);
|
||||
this->manager.removeReg(*this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -311,66 +291,27 @@ void fdRegId::show(unsigned level) const
|
||||
}
|
||||
|
||||
//
|
||||
// fdRegId::resourceHash()
|
||||
//
|
||||
resTableIndex fdRegId::resourceHash (unsigned) const
|
||||
{
|
||||
resTableIndex hashid = (unsigned) this->fd;
|
||||
|
||||
//
|
||||
// This assumes worst case hash table index width of 1 bit.
|
||||
// We will iterate this loop 5 times on a 32 bit architecture.
|
||||
//
|
||||
// A good optimizer will unroll this loop?
|
||||
// Experiments using the microsoft compiler show that this isnt
|
||||
// slower than switching on the architecture size and urolling the
|
||||
// loop explicitly (that solution has resulted in portability
|
||||
// problems in the past).
|
||||
//
|
||||
for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) {
|
||||
hashid ^= (hashid>>i);
|
||||
}
|
||||
|
||||
//
|
||||
// evenly distribute based on the type of interest also
|
||||
//
|
||||
hashid ^= this->type;
|
||||
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::installReg()
|
||||
// fdManager::installReg ()
|
||||
//
|
||||
epicsShareFunc void fdManager::installReg (fdReg ®)
|
||||
{
|
||||
int status;
|
||||
|
||||
this->maxFD = fdManagerMaxInt(this->maxFD, reg.getFD()+1);
|
||||
this->regList.add(reg);
|
||||
reg.state = fdrPending;
|
||||
status = this->fdTbl.add(reg);
|
||||
if (status) {
|
||||
fprintf (stderr,
|
||||
"**** Warning - duplicate fdReg object\n");
|
||||
fprintf (stderr,
|
||||
"**** will not be seen by fdManager::lookUpFD()\n");
|
||||
}
|
||||
this->maxFD = tsMax(this->maxFD, reg.getFD()+1);
|
||||
this->regList.add (reg);
|
||||
reg.state = fdReg::pending;
|
||||
if (this->fdTbl.add (reg)!=0) {
|
||||
throw fdInterestSubscriptionAlreadyExits();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::removeReg()
|
||||
// fdManager::removeReg ()
|
||||
//
|
||||
void fdManager::removeReg(fdReg ®)
|
||||
void fdManager::removeReg (fdReg ®In)
|
||||
{
|
||||
fdReg *pItemFound;
|
||||
|
||||
pItemFound = this->fdTbl.remove(reg);
|
||||
if (pItemFound!=®) {
|
||||
pItemFound = this->fdTbl.remove (regIn);
|
||||
if (pItemFound!=®In) {
|
||||
fprintf(stderr,
|
||||
"fdManager::removeReg() bad fd registration object\n");
|
||||
return;
|
||||
@@ -380,18 +321,18 @@ void fdManager::removeReg(fdReg ®)
|
||||
// signal fdManager that the fdReg was deleted
|
||||
// during the call back
|
||||
//
|
||||
if (this->pCBReg == ®) {
|
||||
if (this->pCBReg == ®In) {
|
||||
this->pCBReg = 0;
|
||||
}
|
||||
|
||||
switch (reg.state) {
|
||||
case fdrActive:
|
||||
this->activeList.remove(reg);
|
||||
switch (regIn.state) {
|
||||
case fdReg::active:
|
||||
this->activeList.remove (regIn);
|
||||
break;
|
||||
case fdrPending:
|
||||
this->regList.remove(reg);
|
||||
case fdReg::pending:
|
||||
this->regList.remove (regIn);
|
||||
break;
|
||||
case fdrLimbo:
|
||||
case fdReg::limbo:
|
||||
break;
|
||||
default:
|
||||
//
|
||||
@@ -399,15 +340,15 @@ void fdManager::removeReg(fdReg ®)
|
||||
//
|
||||
assert(0);
|
||||
}
|
||||
reg.state = fdrLimbo;
|
||||
regIn.state = fdReg::limbo;
|
||||
|
||||
FD_CLR(reg.getFD(), &this->fdSets[reg.getType()]);
|
||||
FD_CLR(regIn.getFD(), &this->fdSets[regIn.getType()]);
|
||||
}
|
||||
|
||||
//
|
||||
// lookUpFD()
|
||||
//
|
||||
epicsShareFunc fdReg *fdManager::lookUpFD(const SOCKET fd, const fdRegType type)
|
||||
epicsShareFunc fdReg *fdManager::lookUpFD (const SOCKET fd, const fdRegType type)
|
||||
{
|
||||
if (fd<0) {
|
||||
return NULL;
|
||||
@@ -420,13 +361,14 @@ epicsShareFunc fdReg *fdManager::lookUpFD(const SOCKET fd, const fdRegType type)
|
||||
// fdReg::fdReg()
|
||||
//
|
||||
fdReg::fdReg (const SOCKET fdIn, const fdRegType typIn,
|
||||
const unsigned onceOnlyIn) :
|
||||
fdRegId(fdIn,typIn), state(fdrLimbo), onceOnly(onceOnlyIn)
|
||||
{
|
||||
const bool onceOnlyIn, fdManager &managerIn) :
|
||||
fdRegId (fdIn,typIn), state (limbo),
|
||||
onceOnly (onceOnlyIn), manager (managerIn)
|
||||
{
|
||||
if (!FD_IN_FDSET(fdIn)) {
|
||||
fprintf (stderr, "%s: fd > FD_SETSIZE ignored\n",
|
||||
__FILE__);
|
||||
return;
|
||||
}
|
||||
fileDescriptorManager.installReg(*this);
|
||||
this->manager.installReg (*this);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* File descriptor management C++ class library
|
||||
* (for multiplexing IO in a single threaded environment)
|
||||
* File descriptor management C++ class library
|
||||
* (for multiplexing IO in a single threaded environment)
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
@@ -30,96 +30,93 @@
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.10 1998/10/23 19:47:12 jhill
|
||||
* fixed inline is too big warning
|
||||
*
|
||||
* Revision 1.9 1998/06/16 02:04:07 jhill
|
||||
* fixed spelling
|
||||
*
|
||||
* Revision 1.8 1998/02/05 21:12:10 jhill
|
||||
* removed questionable inline
|
||||
*
|
||||
* Revision 1.7 1997/08/05 00:37:01 jhill
|
||||
* removed warnings
|
||||
*
|
||||
* Revision 1.6 1997/06/25 05:45:50 jhill
|
||||
* cleaned up pc port
|
||||
*
|
||||
* Revision 1.5 1997/04/23 17:22:58 jhill
|
||||
* fixed WIN32 DLL symbol exports
|
||||
*
|
||||
* Revision 1.4 1997/04/10 19:45:38 jhill
|
||||
* API changes and include with not <>
|
||||
*
|
||||
* Revision 1.3 1996/11/02 02:04:41 jhill
|
||||
* fixed several subtle bugs
|
||||
*
|
||||
* Revision 1.2 1996/09/04 21:50:16 jhill
|
||||
* added hashed fd to fdi convert
|
||||
*
|
||||
* Revision 1.1 1996/08/13 22:48:21 jhill
|
||||
* dfMgr =>fdManager
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef fdManagerH_included
|
||||
#define fdManagerH_included
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shareLib.h" // reset share lib defines
|
||||
#include "tsDLList.h"
|
||||
#include "resourceLib.h"
|
||||
#include "osiTime.h"
|
||||
#include "osiSock.h"
|
||||
|
||||
enum fdRegType {fdrRead, fdrWrite, fdrExcp, fdRegTypeNElem};
|
||||
enum fdRegState {fdrActive, fdrPending, fdrLimbo};
|
||||
static const unsigned hashTableIndexBits = 8;
|
||||
|
||||
enum fdRegType {fdrRead, fdrWrite, fdrException, fdrNEnums};
|
||||
|
||||
//
|
||||
// fdRegId
|
||||
//
|
||||
// file descriptor interest id
|
||||
//
|
||||
class epicsShareClass fdRegId
|
||||
{
|
||||
public:
|
||||
|
||||
fdRegId (const SOCKET fdIn, const fdRegType typeIn) :
|
||||
fd(fdIn), type(typeIn) {}
|
||||
|
||||
SOCKET getFD ()
|
||||
SOCKET getFD () const
|
||||
{
|
||||
return this->fd;
|
||||
}
|
||||
|
||||
fdRegType getType ()
|
||||
fdRegType getType () const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
int operator == (const fdRegId &idIn)
|
||||
bool operator == (const fdRegId &idIn) const
|
||||
{
|
||||
return this->fd == idIn.fd && this->type==idIn.type;
|
||||
}
|
||||
|
||||
resTableIndex resourceHash (unsigned nBitsId) const;
|
||||
resTableIndex hash (unsigned nBitsId) const;
|
||||
|
||||
//
|
||||
// this must allow at least enough bits for all states
|
||||
// in type "fdRegType". The actual size of the table
|
||||
// is used because it improves performance.
|
||||
//
|
||||
static unsigned minIndexBitWidth ()
|
||||
{
|
||||
return hashTableIndexBits;
|
||||
}
|
||||
|
||||
static unsigned maxIndexBitWidth ()
|
||||
{
|
||||
return sizeof(SOCKET)*CHAR_BIT;
|
||||
}
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
private:
|
||||
const SOCKET fd;
|
||||
const fdRegType type;
|
||||
const SOCKET fd;
|
||||
const fdRegType type;
|
||||
};
|
||||
|
||||
class fdManager;
|
||||
|
||||
//
|
||||
// default file descriptor manager
|
||||
//
|
||||
epicsShareExtern fdManager fileDescriptorManager;
|
||||
|
||||
//
|
||||
// fdReg
|
||||
//
|
||||
// file descriptor registration
|
||||
//
|
||||
class fdReg : public tsDLNode<fdReg>, public fdRegId, public tsSLNode<fdReg> {
|
||||
friend class fdManager;
|
||||
class fdReg : public fdRegId, private tsDLNode<fdReg>, private tsSLNode<fdReg> {
|
||||
friend class fdManager;
|
||||
public:
|
||||
epicsShareFunc fdReg (const SOCKET fdIn, const fdRegType typ,
|
||||
const unsigned onceOnly=0);
|
||||
|
||||
epicsShareFunc fdReg (const SOCKET fdIn, const fdRegType type,
|
||||
const bool onceOnly=false, fdManager &manager = fileDescriptorManager);
|
||||
epicsShareFunc virtual ~fdReg ();
|
||||
|
||||
epicsShareFunc virtual void show(unsigned level) const;
|
||||
epicsShareFunc virtual void show (unsigned level) const;
|
||||
|
||||
//
|
||||
// Called by the file descriptor manager:
|
||||
@@ -131,7 +128,9 @@ public:
|
||||
// fdReg::destroy() does a "delete this"
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
enum state {active, pending, limbo};
|
||||
|
||||
//
|
||||
// called when there is activity on the fd
|
||||
@@ -142,57 +141,72 @@ private:
|
||||
//
|
||||
epicsShareFunc virtual void callBack ()=0;
|
||||
|
||||
unsigned char state; // fdRegState goes here
|
||||
unsigned char onceOnly;
|
||||
unsigned char state; // state enums go here
|
||||
unsigned char onceOnly;
|
||||
fdManager &manager;
|
||||
};
|
||||
|
||||
//
|
||||
// fdManager
|
||||
//
|
||||
// file descriptor manager
|
||||
//
|
||||
class fdManager {
|
||||
friend class fdReg;
|
||||
public:
|
||||
//
|
||||
// exceptions
|
||||
//
|
||||
class fdInterestSubscriptionAlreadyExits {};
|
||||
|
||||
epicsShareFunc fdManager();
|
||||
epicsShareFunc ~fdManager();
|
||||
epicsShareFunc void process (const osiTime &delay);
|
||||
epicsShareFunc void process (double delay); // delay parameter is in seconds
|
||||
|
||||
//
|
||||
// returns NULL if the fd is unknown
|
||||
//
|
||||
epicsShareFunc fdReg *lookUpFD(const SOCKET fd, const fdRegType type);
|
||||
private:
|
||||
tsDLList<fdReg> regList;
|
||||
tsDLList<fdReg> activeList;
|
||||
resTable<fdReg,fdRegId> fdTbl;
|
||||
fd_set fdSets[fdRegTypeNElem];
|
||||
epicsShareFunc fdReg *lookUpFD(const SOCKET fd, const fdRegType type);
|
||||
|
||||
int maxFD;
|
||||
unsigned processInProg;
|
||||
private:
|
||||
tsDLList<fdReg> regList;
|
||||
tsDLList<fdReg> activeList;
|
||||
resTable<fdReg, fdRegId> fdTbl;
|
||||
fd_set fdSets[fdrNEnums];
|
||||
|
||||
SOCKET maxFD;
|
||||
unsigned processInProg;
|
||||
//
|
||||
// Set to fdreg when in call back
|
||||
// and nill otherwise
|
||||
//
|
||||
fdReg *pCBReg;
|
||||
fdReg *pCBReg;
|
||||
|
||||
epicsShareFunc void installReg (fdReg ®);
|
||||
void removeReg (fdReg ®);
|
||||
epicsShareFunc void removeReg (fdReg ®);
|
||||
};
|
||||
|
||||
epicsShareExtern fdManager fileDescriptorManager;
|
||||
|
||||
//
|
||||
// fdManagerMaxInt ()
|
||||
// fdRegId::hash()
|
||||
//
|
||||
inline int fdManagerMaxInt (int a, int b)
|
||||
inline resTableIndex fdRegId::hash (unsigned) const
|
||||
{
|
||||
if (a>b) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = resTableIntHash
|
||||
<SOCKET, hashTableIndexBits, sizeof(SOCKET)*CHAR_BIT> (this->fd);
|
||||
|
||||
//
|
||||
// also evenly distribute based on the type of fdRegType
|
||||
//
|
||||
hashid ^= this->type;
|
||||
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
#endif // fdManagerH_included
|
||||
|
||||
|
||||
@@ -1,52 +1,38 @@
|
||||
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.14 1998/06/16 02:06:32 jhill
|
||||
// lazy init sock lib when its a static build & recoverfrom select differences in winsock
|
||||
//
|
||||
// Revision 1.13 1998/05/29 20:22:44 jhill
|
||||
// made hashing routine portable
|
||||
//
|
||||
// Revision 1.12 1998/02/05 21:12:09 jhill
|
||||
// removed questionable inline
|
||||
//
|
||||
// Revision 1.11 1997/08/05 00:37:00 jhill
|
||||
// removed warnings
|
||||
//
|
||||
// Revision 1.10 1997/06/25 05:45:49 jhill
|
||||
// cleaned up pc port
|
||||
//
|
||||
// Revision 1.9 1997/06/13 09:39:09 jhill
|
||||
// fixed warnings
|
||||
//
|
||||
// Revision 1.8 1997/05/29 21:37:38 tang
|
||||
// add ifdef for select call to support HP-UX
|
||||
//
|
||||
// Revision 1.7 1997/05/27 14:53:11 tang
|
||||
// fd_set cast in select for both Hp and Sun
|
||||
//
|
||||
// Revision 1.6 1997/05/08 19:49:12 tang
|
||||
// added int * cast in select for HP port compatibility
|
||||
//
|
||||
// Revision 1.5 1997/04/23 17:22:57 jhill
|
||||
// fixed WIN32 DLL symbol exports
|
||||
//
|
||||
// Revision 1.4 1997/04/10 19:45:33 jhill
|
||||
// API changes and include with not <>
|
||||
//
|
||||
// Revision 1.3 1996/11/02 02:04:42 jhill
|
||||
// fixed several subtle bugs
|
||||
//
|
||||
// Revision 1.2 1996/09/04 21:50:16 jhill
|
||||
// added hashed fd to fdi convert
|
||||
//
|
||||
// Revision 1.1 1996/08/13 22:48:23 jhill
|
||||
// dfMgr =>fdManager
|
||||
//
|
||||
//
|
||||
/*
|
||||
* $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
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
//
|
||||
@@ -67,8 +53,9 @@
|
||||
#define epicsExportSharedSymbols
|
||||
#define instantiateRecourceLib
|
||||
#include "osiTimer.h"
|
||||
#include "fdManager.h"
|
||||
#include "osiSleep.h"
|
||||
#include "tsMinMax.h"
|
||||
#include "fdManager.h"
|
||||
#include "bsdSocketResource.h"
|
||||
|
||||
//
|
||||
@@ -83,7 +70,6 @@
|
||||
// This explicitly instantiates the template class's member
|
||||
// functions used by fdManager
|
||||
//
|
||||
//
|
||||
// instantiated by "fdManager fileDescriptorManager;" statement below?
|
||||
// (according to ms vis C++)
|
||||
//
|
||||
@@ -95,7 +81,8 @@ epicsShareDef fdManager fileDescriptorManager;
|
||||
//
|
||||
// fdManager::fdManager()
|
||||
//
|
||||
epicsShareFunc fdManager::fdManager()
|
||||
epicsShareFunc fdManager::fdManager() :
|
||||
fdTbl (1<<hashTableIndexBits)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
@@ -107,12 +94,6 @@ epicsShareFunc fdManager::fdManager()
|
||||
this->maxFD = 0;
|
||||
this->processInProg = 0u;
|
||||
this->pCBReg = 0;
|
||||
//
|
||||
// should throw an exception here
|
||||
// when most compilers are implementing
|
||||
// exceptions
|
||||
//
|
||||
assert (this->fdTbl.init(0x100)>=0);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -123,11 +104,11 @@ epicsShareFunc fdManager::~fdManager()
|
||||
fdReg *pReg;
|
||||
|
||||
while ( (pReg = this->regList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
pReg->destroy();
|
||||
}
|
||||
bsdSockRelease();
|
||||
@@ -136,13 +117,10 @@ epicsShareFunc fdManager::~fdManager()
|
||||
//
|
||||
// fdManager::process()
|
||||
//
|
||||
epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
epicsShareFunc void fdManager::process (double delay)
|
||||
{
|
||||
static const tsDLIterBD<fdReg> eol; // end of list
|
||||
tsDLIterBD<fdReg> iter;
|
||||
tsDLIterBD<fdReg> tmp;
|
||||
osiTime minDelay;
|
||||
osiTime zeroDelay;
|
||||
static const tsDLIterBD<fdReg> eol (0); // end of list
|
||||
double minDelay;
|
||||
fdReg *pReg;
|
||||
struct timeval tv;
|
||||
int status;
|
||||
@@ -163,23 +141,25 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
// more than once here so that fd activity get serviced
|
||||
// in a reasonable length of time.
|
||||
//
|
||||
minDelay = staticTimerQueue.delayToFirstExpire();
|
||||
if (zeroDelay>=minDelay) {
|
||||
staticTimerQueue.process();
|
||||
minDelay = staticTimerQueue.delayToFirstExpire();
|
||||
minDelay = osiDefaultTimerQueue.delayToFirstExpire();
|
||||
if (minDelay<=0.0) {
|
||||
osiDefaultTimerQueue.process();
|
||||
minDelay = osiDefaultTimerQueue.delayToFirstExpire();
|
||||
}
|
||||
|
||||
if (minDelay>=delay) {
|
||||
minDelay = delay;
|
||||
}
|
||||
|
||||
for (iter=this->regList.first(); iter!=eol; ++iter) {
|
||||
tsDLIterBD<fdReg> iter (this->regList.first());
|
||||
while (iter!=eol) {
|
||||
FD_SET(iter->getFD(), &this->fdSets[iter->getType()]);
|
||||
ioPending = 1;
|
||||
++iter;
|
||||
}
|
||||
|
||||
tv.tv_sec = minDelay.getSecTruncToLong ();
|
||||
tv.tv_usec = minDelay.getUSecTruncToLong ();
|
||||
tv.tv_sec = static_cast<long> (minDelay);
|
||||
tv.tv_usec = static_cast<long> ((minDelay-tv.tv_sec)*osiTime::uSecPerSec);
|
||||
|
||||
/*
|
||||
* win32 requires this (others will
|
||||
@@ -198,10 +178,10 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
}
|
||||
else {
|
||||
status = select (this->maxFD, &this->fdSets[fdrRead],
|
||||
&this->fdSets[fdrWrite], &this->fdSets[fdrExcp], &tv);
|
||||
&this->fdSets[fdrWrite], &this->fdSets[fdrException], &tv);
|
||||
}
|
||||
|
||||
staticTimerQueue.process();
|
||||
osiDefaultTimerQueue.process();
|
||||
if (status==0) {
|
||||
this->processInProg = 0;
|
||||
return;
|
||||
@@ -223,13 +203,13 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
//
|
||||
iter=this->regList.first();
|
||||
while (iter!=eol) {
|
||||
tmp = iter;
|
||||
tsDLIterBD<fdReg> tmp = iter;
|
||||
tmp++;
|
||||
if (FD_ISSET(iter->getFD(), &this->fdSets[iter->getType()])) {
|
||||
FD_CLR(iter->getFD(), &this->fdSets[iter->getType()]);
|
||||
this->regList.remove(*iter);
|
||||
this->activeList.add(*iter);
|
||||
iter->state = fdrActive;
|
||||
iter->state = fdReg::active;
|
||||
}
|
||||
iter=tmp;
|
||||
}
|
||||
@@ -239,10 +219,10 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
// above list while in a "callBack()" routine
|
||||
//
|
||||
while ( (pReg = this->activeList.get()) ) {
|
||||
pReg->state = fdrLimbo;
|
||||
pReg->state = fdReg::limbo;
|
||||
|
||||
//
|
||||
// Tag current reg so that we
|
||||
// Tag current fdReg so that we
|
||||
// can detect if it was deleted
|
||||
// during the call back
|
||||
//
|
||||
@@ -261,7 +241,7 @@ epicsShareFunc void fdManager::process (const osiTime &delay)
|
||||
}
|
||||
else {
|
||||
this->regList.add(*pReg);
|
||||
pReg->state = fdrPending;
|
||||
pReg->state = fdReg::pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +262,7 @@ epicsShareFunc void fdReg::destroy()
|
||||
//
|
||||
epicsShareFunc fdReg::~fdReg()
|
||||
{
|
||||
fileDescriptorManager.removeReg(*this);
|
||||
this->manager.removeReg(*this);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -311,66 +291,27 @@ void fdRegId::show(unsigned level) const
|
||||
}
|
||||
|
||||
//
|
||||
// fdRegId::resourceHash()
|
||||
//
|
||||
resTableIndex fdRegId::resourceHash (unsigned) const
|
||||
{
|
||||
resTableIndex hashid = (unsigned) this->fd;
|
||||
|
||||
//
|
||||
// This assumes worst case hash table index width of 1 bit.
|
||||
// We will iterate this loop 5 times on a 32 bit architecture.
|
||||
//
|
||||
// A good optimizer will unroll this loop?
|
||||
// Experiments using the microsoft compiler show that this isnt
|
||||
// slower than switching on the architecture size and urolling the
|
||||
// loop explicitly (that solution has resulted in portability
|
||||
// problems in the past).
|
||||
//
|
||||
for (unsigned i=(CHAR_BIT*sizeof(unsigned))/2u; i>0u; i >>= 1u) {
|
||||
hashid ^= (hashid>>i);
|
||||
}
|
||||
|
||||
//
|
||||
// evenly distribute based on the type of interest also
|
||||
//
|
||||
hashid ^= this->type;
|
||||
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::installReg()
|
||||
// fdManager::installReg ()
|
||||
//
|
||||
epicsShareFunc void fdManager::installReg (fdReg ®)
|
||||
{
|
||||
int status;
|
||||
|
||||
this->maxFD = fdManagerMaxInt(this->maxFD, reg.getFD()+1);
|
||||
this->regList.add(reg);
|
||||
reg.state = fdrPending;
|
||||
status = this->fdTbl.add(reg);
|
||||
if (status) {
|
||||
fprintf (stderr,
|
||||
"**** Warning - duplicate fdReg object\n");
|
||||
fprintf (stderr,
|
||||
"**** will not be seen by fdManager::lookUpFD()\n");
|
||||
}
|
||||
this->maxFD = tsMax(this->maxFD, reg.getFD()+1);
|
||||
this->regList.add (reg);
|
||||
reg.state = fdReg::pending;
|
||||
if (this->fdTbl.add (reg)!=0) {
|
||||
throw fdInterestSubscriptionAlreadyExits();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// fdManager::removeReg()
|
||||
// fdManager::removeReg ()
|
||||
//
|
||||
void fdManager::removeReg(fdReg ®)
|
||||
void fdManager::removeReg (fdReg ®In)
|
||||
{
|
||||
fdReg *pItemFound;
|
||||
|
||||
pItemFound = this->fdTbl.remove(reg);
|
||||
if (pItemFound!=®) {
|
||||
pItemFound = this->fdTbl.remove (regIn);
|
||||
if (pItemFound!=®In) {
|
||||
fprintf(stderr,
|
||||
"fdManager::removeReg() bad fd registration object\n");
|
||||
return;
|
||||
@@ -380,18 +321,18 @@ void fdManager::removeReg(fdReg ®)
|
||||
// signal fdManager that the fdReg was deleted
|
||||
// during the call back
|
||||
//
|
||||
if (this->pCBReg == ®) {
|
||||
if (this->pCBReg == ®In) {
|
||||
this->pCBReg = 0;
|
||||
}
|
||||
|
||||
switch (reg.state) {
|
||||
case fdrActive:
|
||||
this->activeList.remove(reg);
|
||||
switch (regIn.state) {
|
||||
case fdReg::active:
|
||||
this->activeList.remove (regIn);
|
||||
break;
|
||||
case fdrPending:
|
||||
this->regList.remove(reg);
|
||||
case fdReg::pending:
|
||||
this->regList.remove (regIn);
|
||||
break;
|
||||
case fdrLimbo:
|
||||
case fdReg::limbo:
|
||||
break;
|
||||
default:
|
||||
//
|
||||
@@ -399,15 +340,15 @@ void fdManager::removeReg(fdReg ®)
|
||||
//
|
||||
assert(0);
|
||||
}
|
||||
reg.state = fdrLimbo;
|
||||
regIn.state = fdReg::limbo;
|
||||
|
||||
FD_CLR(reg.getFD(), &this->fdSets[reg.getType()]);
|
||||
FD_CLR(regIn.getFD(), &this->fdSets[regIn.getType()]);
|
||||
}
|
||||
|
||||
//
|
||||
// lookUpFD()
|
||||
//
|
||||
epicsShareFunc fdReg *fdManager::lookUpFD(const SOCKET fd, const fdRegType type)
|
||||
epicsShareFunc fdReg *fdManager::lookUpFD (const SOCKET fd, const fdRegType type)
|
||||
{
|
||||
if (fd<0) {
|
||||
return NULL;
|
||||
@@ -420,13 +361,14 @@ epicsShareFunc fdReg *fdManager::lookUpFD(const SOCKET fd, const fdRegType type)
|
||||
// fdReg::fdReg()
|
||||
//
|
||||
fdReg::fdReg (const SOCKET fdIn, const fdRegType typIn,
|
||||
const unsigned onceOnlyIn) :
|
||||
fdRegId(fdIn,typIn), state(fdrLimbo), onceOnly(onceOnlyIn)
|
||||
{
|
||||
const bool onceOnlyIn, fdManager &managerIn) :
|
||||
fdRegId (fdIn,typIn), state (limbo),
|
||||
onceOnly (onceOnlyIn), manager (managerIn)
|
||||
{
|
||||
if (!FD_IN_FDSET(fdIn)) {
|
||||
fprintf (stderr, "%s: fd > FD_SETSIZE ignored\n",
|
||||
__FILE__);
|
||||
return;
|
||||
}
|
||||
fileDescriptorManager.installReg(*this);
|
||||
this->manager.installReg (*this);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* File descriptor management C++ class library
|
||||
* (for multiplexing IO in a single threaded environment)
|
||||
* File descriptor management C++ class library
|
||||
* (for multiplexing IO in a single threaded environment)
|
||||
*
|
||||
* Author Jeffrey O. Hill
|
||||
* johill@lanl.gov
|
||||
@@ -30,96 +30,93 @@
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
*
|
||||
* History
|
||||
* $Log$
|
||||
* Revision 1.10 1998/10/23 19:47:12 jhill
|
||||
* fixed inline is too big warning
|
||||
*
|
||||
* Revision 1.9 1998/06/16 02:04:07 jhill
|
||||
* fixed spelling
|
||||
*
|
||||
* Revision 1.8 1998/02/05 21:12:10 jhill
|
||||
* removed questionable inline
|
||||
*
|
||||
* Revision 1.7 1997/08/05 00:37:01 jhill
|
||||
* removed warnings
|
||||
*
|
||||
* Revision 1.6 1997/06/25 05:45:50 jhill
|
||||
* cleaned up pc port
|
||||
*
|
||||
* Revision 1.5 1997/04/23 17:22:58 jhill
|
||||
* fixed WIN32 DLL symbol exports
|
||||
*
|
||||
* Revision 1.4 1997/04/10 19:45:38 jhill
|
||||
* API changes and include with not <>
|
||||
*
|
||||
* Revision 1.3 1996/11/02 02:04:41 jhill
|
||||
* fixed several subtle bugs
|
||||
*
|
||||
* Revision 1.2 1996/09/04 21:50:16 jhill
|
||||
* added hashed fd to fdi convert
|
||||
*
|
||||
* Revision 1.1 1996/08/13 22:48:21 jhill
|
||||
* dfMgr =>fdManager
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef fdManagerH_included
|
||||
#define fdManagerH_included
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "shareLib.h" // reset share lib defines
|
||||
#include "tsDLList.h"
|
||||
#include "resourceLib.h"
|
||||
#include "osiTime.h"
|
||||
#include "osiSock.h"
|
||||
|
||||
enum fdRegType {fdrRead, fdrWrite, fdrExcp, fdRegTypeNElem};
|
||||
enum fdRegState {fdrActive, fdrPending, fdrLimbo};
|
||||
static const unsigned hashTableIndexBits = 8;
|
||||
|
||||
enum fdRegType {fdrRead, fdrWrite, fdrException, fdrNEnums};
|
||||
|
||||
//
|
||||
// fdRegId
|
||||
//
|
||||
// file descriptor interest id
|
||||
//
|
||||
class epicsShareClass fdRegId
|
||||
{
|
||||
public:
|
||||
|
||||
fdRegId (const SOCKET fdIn, const fdRegType typeIn) :
|
||||
fd(fdIn), type(typeIn) {}
|
||||
|
||||
SOCKET getFD ()
|
||||
SOCKET getFD () const
|
||||
{
|
||||
return this->fd;
|
||||
}
|
||||
|
||||
fdRegType getType ()
|
||||
fdRegType getType () const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
int operator == (const fdRegId &idIn)
|
||||
bool operator == (const fdRegId &idIn) const
|
||||
{
|
||||
return this->fd == idIn.fd && this->type==idIn.type;
|
||||
}
|
||||
|
||||
resTableIndex resourceHash (unsigned nBitsId) const;
|
||||
resTableIndex hash (unsigned nBitsId) const;
|
||||
|
||||
//
|
||||
// this must allow at least enough bits for all states
|
||||
// in type "fdRegType". The actual size of the table
|
||||
// is used because it improves performance.
|
||||
//
|
||||
static unsigned minIndexBitWidth ()
|
||||
{
|
||||
return hashTableIndexBits;
|
||||
}
|
||||
|
||||
static unsigned maxIndexBitWidth ()
|
||||
{
|
||||
return sizeof(SOCKET)*CHAR_BIT;
|
||||
}
|
||||
|
||||
virtual void show (unsigned level) const;
|
||||
private:
|
||||
const SOCKET fd;
|
||||
const fdRegType type;
|
||||
const SOCKET fd;
|
||||
const fdRegType type;
|
||||
};
|
||||
|
||||
class fdManager;
|
||||
|
||||
//
|
||||
// default file descriptor manager
|
||||
//
|
||||
epicsShareExtern fdManager fileDescriptorManager;
|
||||
|
||||
//
|
||||
// fdReg
|
||||
//
|
||||
// file descriptor registration
|
||||
//
|
||||
class fdReg : public tsDLNode<fdReg>, public fdRegId, public tsSLNode<fdReg> {
|
||||
friend class fdManager;
|
||||
class fdReg : public fdRegId, private tsDLNode<fdReg>, private tsSLNode<fdReg> {
|
||||
friend class fdManager;
|
||||
public:
|
||||
epicsShareFunc fdReg (const SOCKET fdIn, const fdRegType typ,
|
||||
const unsigned onceOnly=0);
|
||||
|
||||
epicsShareFunc fdReg (const SOCKET fdIn, const fdRegType type,
|
||||
const bool onceOnly=false, fdManager &manager = fileDescriptorManager);
|
||||
epicsShareFunc virtual ~fdReg ();
|
||||
|
||||
epicsShareFunc virtual void show(unsigned level) const;
|
||||
epicsShareFunc virtual void show (unsigned level) const;
|
||||
|
||||
//
|
||||
// Called by the file descriptor manager:
|
||||
@@ -131,7 +128,9 @@ public:
|
||||
// fdReg::destroy() does a "delete this"
|
||||
//
|
||||
epicsShareFunc virtual void destroy ();
|
||||
|
||||
private:
|
||||
enum state {active, pending, limbo};
|
||||
|
||||
//
|
||||
// called when there is activity on the fd
|
||||
@@ -142,57 +141,72 @@ private:
|
||||
//
|
||||
epicsShareFunc virtual void callBack ()=0;
|
||||
|
||||
unsigned char state; // fdRegState goes here
|
||||
unsigned char onceOnly;
|
||||
unsigned char state; // state enums go here
|
||||
unsigned char onceOnly;
|
||||
fdManager &manager;
|
||||
};
|
||||
|
||||
//
|
||||
// fdManager
|
||||
//
|
||||
// file descriptor manager
|
||||
//
|
||||
class fdManager {
|
||||
friend class fdReg;
|
||||
public:
|
||||
//
|
||||
// exceptions
|
||||
//
|
||||
class fdInterestSubscriptionAlreadyExits {};
|
||||
|
||||
epicsShareFunc fdManager();
|
||||
epicsShareFunc ~fdManager();
|
||||
epicsShareFunc void process (const osiTime &delay);
|
||||
epicsShareFunc void process (double delay); // delay parameter is in seconds
|
||||
|
||||
//
|
||||
// returns NULL if the fd is unknown
|
||||
//
|
||||
epicsShareFunc fdReg *lookUpFD(const SOCKET fd, const fdRegType type);
|
||||
private:
|
||||
tsDLList<fdReg> regList;
|
||||
tsDLList<fdReg> activeList;
|
||||
resTable<fdReg,fdRegId> fdTbl;
|
||||
fd_set fdSets[fdRegTypeNElem];
|
||||
epicsShareFunc fdReg *lookUpFD(const SOCKET fd, const fdRegType type);
|
||||
|
||||
int maxFD;
|
||||
unsigned processInProg;
|
||||
private:
|
||||
tsDLList<fdReg> regList;
|
||||
tsDLList<fdReg> activeList;
|
||||
resTable<fdReg, fdRegId> fdTbl;
|
||||
fd_set fdSets[fdrNEnums];
|
||||
|
||||
SOCKET maxFD;
|
||||
unsigned processInProg;
|
||||
//
|
||||
// Set to fdreg when in call back
|
||||
// and nill otherwise
|
||||
//
|
||||
fdReg *pCBReg;
|
||||
fdReg *pCBReg;
|
||||
|
||||
epicsShareFunc void installReg (fdReg ®);
|
||||
void removeReg (fdReg ®);
|
||||
epicsShareFunc void removeReg (fdReg ®);
|
||||
};
|
||||
|
||||
epicsShareExtern fdManager fileDescriptorManager;
|
||||
|
||||
//
|
||||
// fdManagerMaxInt ()
|
||||
// fdRegId::hash()
|
||||
//
|
||||
inline int fdManagerMaxInt (int a, int b)
|
||||
inline resTableIndex fdRegId::hash (unsigned) const
|
||||
{
|
||||
if (a>b) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return b;
|
||||
}
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = resTableIntHash
|
||||
<SOCKET, hashTableIndexBits, sizeof(SOCKET)*CHAR_BIT> (this->fd);
|
||||
|
||||
//
|
||||
// also evenly distribute based on the type of fdRegType
|
||||
//
|
||||
hashid ^= this->type;
|
||||
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
|
||||
#endif // fdManagerH_included
|
||||
|
||||
|
||||
Reference in New Issue
Block a user