installed ca server templates
This commit is contained in:
18
src/cxxTemplates/Makefile
Normal file
18
src/cxxTemplates/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Base: Lowest Level Directroy Makefile
|
||||
# by Janet Anderson
|
||||
#
|
||||
# $Log$
|
||||
# Revision 1.1 1994/09/07 19:26:01 jba
|
||||
# New file
|
||||
#
|
||||
#
|
||||
|
||||
EPICS=../../..
|
||||
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
include $(EPICS)/config/RULES_ARCHS
|
||||
|
||||
11
src/cxxTemplates/Makefile.Unix
Normal file
11
src/cxxTemplates/Makefile.Unix
Normal file
@@ -0,0 +1,11 @@
|
||||
EPICS = ../../../..
|
||||
include Target.include
|
||||
include $(EPICS)/config/CONFIG_BASE
|
||||
|
||||
INC += osiTime.h
|
||||
INC += osiTimer.h
|
||||
INC += resourceLib.h
|
||||
INC += tsDLList.h
|
||||
INC += tsSLList.h
|
||||
|
||||
include $(EPICS)/config/RULES.Unix
|
||||
224
src/cxxTemplates/osiTime.h
Normal file
224
src/cxxTemplates/osiTime.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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 osiTimehInclude
|
||||
#define osiTimehInclude
|
||||
|
||||
#include <limits.h>
|
||||
#ifndef assert // allows use of epicsAssert.h
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
const unsigned nSecPerSec = 1000000000u;
|
||||
const unsigned nSecPerUSec = 1000u;
|
||||
const unsigned secPerMin = 60u;
|
||||
|
||||
class osiTime {
|
||||
static friend osiTime operator+
|
||||
(const osiTime &lhs, const osiTime &rhs);
|
||||
static friend osiTime operator-
|
||||
(const osiTime &lhs, const osiTime &rhs);
|
||||
static friend int operator>=
|
||||
(const osiTime &lhs, const osiTime &rhs);
|
||||
public:
|
||||
osiTime () : sec(0u), nSec(0u) {}
|
||||
osiTime (const osiTime &t) : sec(t.sec), nSec(t.nSec) {}
|
||||
osiTime (const unsigned long secIn, const unsigned long nSecIn)
|
||||
{
|
||||
if (nSecIn<nSecPerSec) {
|
||||
this->sec = secIn;
|
||||
this->nSec = nSecIn;
|
||||
}
|
||||
else if (nSecIn<(nSecPerSec<<1u)){
|
||||
this->sec = secIn + 1u;
|
||||
this->nSec = nSecIn-nSecPerSec;
|
||||
}
|
||||
else {
|
||||
this->sec = nSecIn/nSecPerSec + secIn;
|
||||
this->nSec = nSecIn%nSecPerSec;
|
||||
}
|
||||
}
|
||||
osiTime (double t)
|
||||
{
|
||||
double intPart;
|
||||
if (t<0.0l) {
|
||||
t = 0.0l;
|
||||
}
|
||||
this->sec = (unsigned long) t;
|
||||
intPart = (double) this->sec;
|
||||
this->nSec = (unsigned long) ((t-intPart)*nSecPerSec);
|
||||
}
|
||||
|
||||
//
|
||||
// fetched as fields so this file is not required
|
||||
// to include os dependent struct timeval
|
||||
//
|
||||
void getTV(long &secOut, long &uSecOut) const
|
||||
{
|
||||
assert (this->sec<=LONG_MAX);
|
||||
secOut = (long) this->sec;
|
||||
assert (this->nSec<=LONG_MAX);
|
||||
uSecOut = (long) this->nSec/nSecPerUSec;
|
||||
}
|
||||
//
|
||||
//
|
||||
void get(long &secOut, long &nSecOut) const
|
||||
{
|
||||
assert(this->sec <= LONG_MAX);
|
||||
secOut = this->sec;
|
||||
assert(this->nSec <= LONG_MAX);
|
||||
nSecOut = this->nSec;
|
||||
}
|
||||
void get(unsigned long &secOut, unsigned long &nSecOut) const
|
||||
{
|
||||
secOut = this->sec;
|
||||
nSecOut = this->nSec;
|
||||
}
|
||||
void get(unsigned &secOut, unsigned &nSecOut) const
|
||||
{
|
||||
secOut = this->sec;
|
||||
nSecOut = this->nSec;
|
||||
}
|
||||
|
||||
operator double() const
|
||||
{
|
||||
return ((double)this->nSec)/nSecPerSec+this->sec;
|
||||
}
|
||||
operator float() const
|
||||
{
|
||||
return ((float)this->nSec)/nSecPerSec+this->sec;
|
||||
}
|
||||
static osiTime getCurrent();
|
||||
|
||||
osiTime operator+= (const osiTime &rhs);
|
||||
osiTime operator-= (const osiTime &rhs);
|
||||
|
||||
void show(unsigned)
|
||||
{
|
||||
printf("osiTime: sec=%lu nSec=%lu\n",
|
||||
this->sec, this->nSec);
|
||||
}
|
||||
private:
|
||||
unsigned long sec;
|
||||
unsigned long nSec;
|
||||
};
|
||||
|
||||
inline osiTime operator+ (const osiTime &lhs, const osiTime &rhs)
|
||||
{
|
||||
return osiTime(lhs.sec + rhs.sec, lhs.nSec + rhs.nSec);
|
||||
}
|
||||
|
||||
inline osiTime osiTime::operator+= (const osiTime &rhs)
|
||||
{
|
||||
*this = *this + rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//
|
||||
// like data type unsigned this assumes that the lhs > rhs
|
||||
// (otherwise we assume sec wrap around)
|
||||
//
|
||||
inline osiTime operator- (const osiTime &lhs, const osiTime &rhs)
|
||||
{
|
||||
unsigned long nSec, sec;
|
||||
|
||||
if (lhs.sec<rhs.sec) {
|
||||
//
|
||||
// wrap around
|
||||
//
|
||||
sec = lhs.sec + (ULONG_MAX - rhs.sec);
|
||||
}
|
||||
else {
|
||||
sec = lhs.sec - rhs.sec;
|
||||
}
|
||||
|
||||
if (lhs.nSec<rhs.nSec) {
|
||||
//
|
||||
// Borrow
|
||||
//
|
||||
nSec = lhs.nSec + (nSecPerSec - rhs.nSec);
|
||||
sec--;
|
||||
}
|
||||
else {
|
||||
nSec = lhs.nSec - rhs.nSec;
|
||||
}
|
||||
return osiTime(sec, nSec);
|
||||
}
|
||||
|
||||
inline osiTime osiTime::operator-= (const osiTime &rhs)
|
||||
{
|
||||
*this = *this - rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline int operator>= (const osiTime &lhs, const osiTime &rhs)
|
||||
{
|
||||
int rc;
|
||||
//
|
||||
// Sun's CC -O generates bad code here
|
||||
//
|
||||
//
|
||||
//
|
||||
#if 0
|
||||
if (lhs.sec>rhs.sec) {
|
||||
return 1;
|
||||
}
|
||||
else if (lhs.sec==rhs.sec) {
|
||||
if (lhs.nSec>=rhs.nSec) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
assert(lhs.sec<=rhs.sec);
|
||||
return 0;
|
||||
#endif
|
||||
if (lhs.sec>rhs.sec) {
|
||||
rc = 1;
|
||||
}
|
||||
else if (lhs.sec<rhs.sec) {
|
||||
rc = 0;
|
||||
}
|
||||
else {
|
||||
if (lhs.nSec>=rhs.nSec) {
|
||||
rc = 1;
|
||||
}
|
||||
else {
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif // osiTimehInclude
|
||||
|
||||
132
src/cxxTemplates/osiTimer.h
Normal file
132
src/cxxTemplates/osiTimer.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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 osiTimerHInclude
|
||||
#define osiTimerHInclude
|
||||
|
||||
#include <tsDLList.h>
|
||||
#include <osiTime.h>
|
||||
|
||||
enum osiBool {osiFalse=0, osiTrue=1};
|
||||
enum osiTimerState {ositPending, ositExpired, ositLimbo};
|
||||
|
||||
//
|
||||
// osiTimer
|
||||
//
|
||||
class osiTimer : public tsDLNode<osiTimer> {
|
||||
friend class osiTimerQueue;
|
||||
public:
|
||||
osiTimer (const osiTime &delay)
|
||||
{
|
||||
this->arm(&delay);
|
||||
}
|
||||
virtual ~osiTimer();
|
||||
|
||||
//
|
||||
// called when the timer expires
|
||||
//
|
||||
virtual void expire()=0;
|
||||
|
||||
//
|
||||
// called if
|
||||
// 1) osiTimer exists and the osiTimerQueue is deleted
|
||||
// 2) when the timer expies and again() returs false
|
||||
//
|
||||
// osiTimer::destroy() does a "delete this"
|
||||
//
|
||||
virtual void destroy();
|
||||
|
||||
//
|
||||
// osiTimer::again() returns false
|
||||
// (run the timer once only)
|
||||
// returning true indicates that the
|
||||
// timer should be rearmed with delay
|
||||
// "delay()" when it expires
|
||||
//
|
||||
virtual osiBool again();
|
||||
|
||||
//
|
||||
// returns the delay prior to expire
|
||||
// for subsequent iterations (if "again()"
|
||||
// returns true)
|
||||
//
|
||||
// osiTimer::delay() returns 1 sec
|
||||
//
|
||||
virtual const osiTime delay();
|
||||
|
||||
virtual void show (unsigned level);
|
||||
|
||||
//
|
||||
// for diagnosics
|
||||
//
|
||||
virtual const char *name()
|
||||
{
|
||||
return "unknown class deriving from osiTimer";
|
||||
}
|
||||
private:
|
||||
osiTime exp;
|
||||
osiTimerState state;
|
||||
|
||||
//
|
||||
// arm()
|
||||
// place timer in the pending queue
|
||||
//
|
||||
void arm (const osiTime * const pInitialDelay=0);
|
||||
};
|
||||
|
||||
//
|
||||
// osiTimerQueue
|
||||
//
|
||||
class osiTimerQueue {
|
||||
friend class osiTimer;
|
||||
public:
|
||||
osiTimerQueue() : inProcess(osiFalse) {};
|
||||
~osiTimerQueue();
|
||||
osiTime delayToFirstExpire ();
|
||||
void process ();
|
||||
void show (unsigned level);
|
||||
private:
|
||||
tsDLList<osiTimer> pending;
|
||||
tsDLList<osiTimer> expired;
|
||||
osiBool inProcess;
|
||||
|
||||
void install (osiTimer &tmr, osiTime delay);
|
||||
};
|
||||
|
||||
extern osiTimerQueue staticTimerQueue;
|
||||
|
||||
|
||||
#endif // osiTimerHInclude
|
||||
|
||||
394
src/cxxTemplates/resourceLib.h
Normal file
394
src/cxxTemplates/resourceLib.h
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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$
|
||||
*
|
||||
* NOTES:
|
||||
* .01 Storage for identifier must persist until an item is deleted
|
||||
* .02 class T must derive from class ID and tsSLNode<T>
|
||||
*/
|
||||
|
||||
#ifndef INCresourceLibh
|
||||
#define INCresourceLibh
|
||||
|
||||
#include <tsSLList.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef int resLibStatus;
|
||||
typedef unsigned resTableIndex;
|
||||
|
||||
const unsigned resTableIndexBitWidth = (sizeof(resTableIndex)*CHAR_BIT);
|
||||
|
||||
template <class T, class ID>
|
||||
class resTable {
|
||||
public:
|
||||
resTable() :
|
||||
pTable(0), hashIdMask(0), hashIdNBits(0), nInUse(0) {}
|
||||
|
||||
int init(unsigned nHashTableEntries)
|
||||
{
|
||||
unsigned nbits;
|
||||
|
||||
if (nHashTableEntries<1u) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// count the number of bits in the hash index
|
||||
//
|
||||
for (nbits=0; nbits<resTableIndexBitWidth; nbits++) {
|
||||
this->hashIdMask = (1<<nbits) - 1;
|
||||
if ( ((nHashTableEntries-1) & ~this->hashIdMask) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->hashIdNBits = nbits;
|
||||
this->nInUse = 0u;
|
||||
this->pTable = new tsSLList<T> [this->hashIdMask+1u];
|
||||
if (!pTable) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
~resTable()
|
||||
{
|
||||
assert (this->nInUse == 0u);
|
||||
|
||||
if (this->pTable) {
|
||||
delete [] this->pTable;
|
||||
}
|
||||
}
|
||||
|
||||
void destroyAllEntries()
|
||||
{
|
||||
tsSLList<T> *pList = this->pTable;
|
||||
|
||||
while (pList<&this->pTable[this->hashIdMask+1]) {
|
||||
tsSLIter<T> iter(*pList);
|
||||
T *pItem;
|
||||
T *pNextItem;
|
||||
|
||||
pItem = iter();
|
||||
while (pItem) {
|
||||
pNextItem = iter();
|
||||
delete pItem;
|
||||
this->nInUse--;
|
||||
pItem = pNextItem;
|
||||
}
|
||||
pList++;
|
||||
}
|
||||
}
|
||||
|
||||
void show (unsigned level)
|
||||
{
|
||||
tsSLList<T> *pList;
|
||||
double X;
|
||||
double XX;
|
||||
double mean;
|
||||
double stdDev;
|
||||
unsigned maxEntries;
|
||||
|
||||
printf("resTable with %d resources installed\n", this->nInUse);
|
||||
|
||||
if (level >=1u) {
|
||||
pList = this->pTable;
|
||||
X = 0.0;
|
||||
XX = 0.0;
|
||||
maxEntries = 0;
|
||||
while (pList < &this->pTable[this->hashIdMask+1]) {
|
||||
unsigned count;
|
||||
tsSLIter<T> iter(*pList);
|
||||
T *pItem;
|
||||
|
||||
count = 0;
|
||||
while ( (pItem = iter()) ) {
|
||||
if (level >= 3u) {
|
||||
pItem->show (level);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
X += count;
|
||||
XX += count*count;
|
||||
if (count>maxEntries) {
|
||||
maxEntries = count;
|
||||
}
|
||||
pList++;
|
||||
}
|
||||
|
||||
mean = X/(this->hashIdMask+1);
|
||||
stdDev = sqrt(XX/(this->hashIdMask+1)- mean*mean);
|
||||
printf(
|
||||
"entries/table index - mean = %f std dev = %f max = %d\n",
|
||||
mean, stdDev, maxEntries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
int add (T &res)
|
||||
{
|
||||
//
|
||||
// T must derive from ID
|
||||
//
|
||||
tsSLList<T> &list = this->pTable[this->hash(res)];
|
||||
tsSLNode<T> *pPrev;
|
||||
|
||||
pPrev = this->find(list, res);
|
||||
if (pPrev) {
|
||||
return -1;
|
||||
}
|
||||
list.add(res);
|
||||
this->nInUse++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
T *remove (const ID &idIn)
|
||||
{
|
||||
tsSLList<T> &list = this->pTable[this->hash(idIn)];
|
||||
tsSLNode<T> *pPrev;
|
||||
T *pItem;
|
||||
|
||||
pPrev = this->find(list, idIn);
|
||||
if (!pPrev) {
|
||||
return 0;
|
||||
}
|
||||
this->nInUse--;
|
||||
pItem = pPrev->next();
|
||||
list.remove(*pItem, *pPrev);
|
||||
return pItem;
|
||||
}
|
||||
|
||||
|
||||
T *lookup (const ID &idIn)
|
||||
{
|
||||
tsSLList<T> &list = this->pTable[this->hash(idIn)];
|
||||
tsSLNode<T> *pPrev;
|
||||
|
||||
pPrev = this->find(list, idIn);
|
||||
if (pPrev) {
|
||||
return pPrev->next();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
tsSLList<T> *pTable;
|
||||
unsigned hashIdMask;
|
||||
unsigned hashIdNBits;
|
||||
unsigned nInUse;
|
||||
|
||||
resTableIndex hash(const ID & idIn)
|
||||
{
|
||||
resTableIndex hashid;
|
||||
hashid = idIn.resourceHash(this->hashIdNBits);
|
||||
return hashid & this->hashIdMask;
|
||||
}
|
||||
|
||||
//
|
||||
// beware - this returns a pointer to the node just prior to the
|
||||
// the item found on the list
|
||||
//
|
||||
tsSLNode<T> *find(tsSLList<T> &list, const ID &idIn)
|
||||
{
|
||||
tsSLIter<T> iter(list);
|
||||
T *pItem;
|
||||
ID *pId;
|
||||
|
||||
while ( (pItem = iter()) ) {
|
||||
pId = pItem;
|
||||
if (*pId == idIn) {
|
||||
return iter.prev();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Some ID classes that work with the above template
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// unsigned identifier
|
||||
//
|
||||
class uintId {
|
||||
public:
|
||||
uintId(unsigned idIn=~0u) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
unsigned src = this->id;
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = src;
|
||||
src = src >> nBitsId;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> nBitsId;
|
||||
}
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const uintId &idIn)
|
||||
{
|
||||
return this->id == idIn.id;
|
||||
}
|
||||
|
||||
const unsigned getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
protected:
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
//
|
||||
// resource with unsigned chronological identifier
|
||||
//
|
||||
template <class ITEM>
|
||||
class uintRes : public uintId, public tsSLNode<ITEM> {
|
||||
friend class uintResTable<ITEM>;
|
||||
};
|
||||
|
||||
//
|
||||
// special resource table which uses
|
||||
// unsigned integer keys allocated in chronological sequence
|
||||
//
|
||||
template <class ITEM>
|
||||
class uintResTable : public resTable<ITEM, uintId> {
|
||||
public:
|
||||
uintResTable() : allocId(1u) {} // hashing is faster close to zero
|
||||
|
||||
//
|
||||
// NOTE: This detects (and avoids) the case where
|
||||
// the PV id wraps around and we attempt to have two
|
||||
// resources with the same id.
|
||||
//
|
||||
void installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintId::id = this->allocId++;
|
||||
resTblStatus = this->add(item);
|
||||
}
|
||||
while (resTblStatus);
|
||||
}
|
||||
private:
|
||||
unsigned allocId;
|
||||
};
|
||||
|
||||
//
|
||||
// pointer identifier
|
||||
//
|
||||
class ptrId {
|
||||
public:
|
||||
ptrId (void const * const idIn) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
//
|
||||
// This makes the assumption that
|
||||
// a pointer will fit inside of a long
|
||||
// (this assumption may not port to all
|
||||
// CPU architectures)
|
||||
//
|
||||
unsigned long src = (unsigned long) this->id;
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = src;
|
||||
src = src >> nBitsId;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> nBitsId;
|
||||
}
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const ptrId &idIn)
|
||||
{
|
||||
return this->id == idIn.id;
|
||||
}
|
||||
private:
|
||||
void const * const id;
|
||||
};
|
||||
|
||||
//
|
||||
// character string identifier
|
||||
//
|
||||
class stringId {
|
||||
public:
|
||||
stringId (char const * const idIn) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
const char *pStr = this->id;
|
||||
resTableIndex hashid;
|
||||
unsigned i;
|
||||
|
||||
hashid = 0u;
|
||||
for (i=0u; pStr[i]; i++) {
|
||||
hashid += pStr[i] * (i+1u);
|
||||
}
|
||||
|
||||
hashid = hashid % (1u<<nBitsId);
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const stringId &idIn)
|
||||
{
|
||||
return strcmp(this->id,idIn.id)==0;
|
||||
}
|
||||
|
||||
const char * resourceName()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void show (unsigned)
|
||||
{
|
||||
printf ("resource id = %s\n", id);
|
||||
}
|
||||
private:
|
||||
char const * const id;
|
||||
};
|
||||
|
||||
#endif // INCresourceLibh
|
||||
|
||||
290
src/cxxTemplates/tsDLList.h
Normal file
290
src/cxxTemplates/tsDLList.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* type safe doubly linked list templates
|
||||
*
|
||||
* 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 tsDLListH_include
|
||||
#define tsDLListH_include
|
||||
|
||||
//
|
||||
// tsDLList<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLList {
|
||||
private:
|
||||
//
|
||||
// clear()
|
||||
//
|
||||
void clear()
|
||||
{
|
||||
this->pFirst = 0;
|
||||
this->pLast = 0;
|
||||
this->itemCount = 0u;
|
||||
}
|
||||
public:
|
||||
tsDLList ()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
//
|
||||
// adds addList to this (and removes all items from addList)
|
||||
//
|
||||
tsDLList (tsDLList<T> &addList)
|
||||
{
|
||||
*this = addList;
|
||||
addList.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// first()
|
||||
//
|
||||
T *first() const
|
||||
{
|
||||
return (T *) this->pFirst;
|
||||
}
|
||||
|
||||
//
|
||||
// last()
|
||||
//
|
||||
T *last() const
|
||||
{
|
||||
return (T *) this->pLast;
|
||||
}
|
||||
|
||||
//
|
||||
// count()
|
||||
//
|
||||
unsigned count() const
|
||||
{
|
||||
return this->itemCount;
|
||||
}
|
||||
|
||||
//
|
||||
// add() -
|
||||
// adds addList to this (and removes all items from addList)
|
||||
//
|
||||
void add (tsDLList<T> &addList)
|
||||
{
|
||||
//
|
||||
// NOOP if addList is empty
|
||||
//
|
||||
if (addList.itemCount==0u) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->itemCount==0u) {
|
||||
//
|
||||
// this is empty so just init from
|
||||
// addList
|
||||
//
|
||||
*this = addList;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// add addList to the end of this
|
||||
//
|
||||
this->pLast->tsDLNode<T>::pNext = addList.pFirst;
|
||||
addList.pFirst->tsDLNode<T>::pPrev = addList.pLast;
|
||||
this->pLast = addList.pLast;
|
||||
this->itemCount += addList.itemCount;
|
||||
}
|
||||
|
||||
//
|
||||
// leave addList empty
|
||||
//
|
||||
addList.clear();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// add() - an item
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
item.tsDLNode<T>::pNext = 0;
|
||||
item.tsDLNode<T>::pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
this->pLast->tsDLNode<T>::pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->pLast = &item;
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// insert()
|
||||
// pItemBefore==0 => make item be the first item on the list
|
||||
// pItemBefore!=0 => place item in the list immediately after
|
||||
// pItemBefore
|
||||
//
|
||||
void insert (T &item, T *pItemBefore=0)
|
||||
{
|
||||
if (pItemBefore) {
|
||||
item.tsDLNode<T>::pPrev = pItemBefore;
|
||||
item.tsDLNode<T>::pNext =
|
||||
pItemBefore->tsDLNode<T>::pNext;
|
||||
pItemBefore->tsDLNode<T>::pNext = &item;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pPrev = 0;
|
||||
item.tsDLNode<T>::pNext = this->pFirst;
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
if (item.tsDLNode<T>::pNext) {
|
||||
item.tsDLNode<T>::pNext->tsDLNode<T>::pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// remove ()
|
||||
//
|
||||
void remove (T &item)
|
||||
{
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = item.tsDLNode<T>::pPrev;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pNext->tsDLNode<T>::pPrev =
|
||||
item.tsDLNode<T>::pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = item.tsDLNode<T>::pNext;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pPrev->tsDLNode<T>::pNext =
|
||||
item.tsDLNode<T>::pNext;
|
||||
}
|
||||
|
||||
this->itemCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// get ()
|
||||
//
|
||||
T * get()
|
||||
{
|
||||
T *pItem = this->pFirst;
|
||||
|
||||
if (pItem) {
|
||||
this->remove (*pItem);
|
||||
}
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
private:
|
||||
T *pFirst;
|
||||
T *pLast;
|
||||
unsigned itemCount;
|
||||
};
|
||||
|
||||
//
|
||||
// tsDLNode<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLNode {
|
||||
friend class tsDLList<T>;
|
||||
friend class tsDLIter<T>;
|
||||
public:
|
||||
tsDLNode() : pNext(0), pPrev(0) {}
|
||||
//
|
||||
// when someone copies int a class deriving from this
|
||||
// do _not_ change the node pointers
|
||||
//
|
||||
void operator = (tsDLNode<T> &) {}
|
||||
|
||||
T *getPrev() {return this->pPrev;}
|
||||
T *getNext() {return this->pNext;}
|
||||
private:
|
||||
T *pNext;
|
||||
T *pPrev;
|
||||
};
|
||||
|
||||
//
|
||||
// tsDLIter<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLIter {
|
||||
public:
|
||||
tsDLIter(tsDLList<T> &listIn) :
|
||||
list(listIn), pCurrent(0) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->pCurrent = 0;
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->reset();
|
||||
this->list = listIn;
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->reset(listIn);
|
||||
}
|
||||
|
||||
T * operator () ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->list.first();
|
||||
}
|
||||
else {
|
||||
pCur = pCur->tsDLNode<T>::pNext;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
private:
|
||||
tsDLList<T> &list;
|
||||
T *pCurrent;
|
||||
};
|
||||
|
||||
#endif // tsDLListH_include
|
||||
|
||||
151
src/cxxTemplates/tsSLList.h
Normal file
151
src/cxxTemplates/tsSLList.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* tsSLList - type safe singly linked list templates
|
||||
*
|
||||
* 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$
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// tsSLList<>
|
||||
//
|
||||
template <class T>
|
||||
class tsSLList : public tsSLNode<T> {
|
||||
public:
|
||||
tsSLList () {}
|
||||
|
||||
//
|
||||
// first()
|
||||
//
|
||||
T *first() const
|
||||
{
|
||||
return this->tsSLNode<T>::pNext;
|
||||
}
|
||||
|
||||
//
|
||||
// insert()
|
||||
// (itemBefore might be the list header object and therefore
|
||||
// will not always be of type T)
|
||||
//
|
||||
void insert (T &item, tsSLNode<T> &itemBefore)
|
||||
{
|
||||
item.tsSLNode<T>::pNext = itemBefore.pNext;
|
||||
itemBefore.pNext = &item;
|
||||
}
|
||||
|
||||
//
|
||||
// add()
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
this->insert (item, *this);
|
||||
}
|
||||
|
||||
//
|
||||
// remove ()
|
||||
// (itemBefore might be the list header object and therefore
|
||||
// will not always be of type T)
|
||||
//
|
||||
void remove (T &item, tsSLNode<T> &itemBefore)
|
||||
{
|
||||
itemBefore.tsSLNode<T>::pNext = item.tsSLNode<T>::pNext;
|
||||
}
|
||||
|
||||
//
|
||||
// get ()
|
||||
//
|
||||
T * get()
|
||||
{
|
||||
T *pItem = this->tsSLNode<T>::pNext;
|
||||
if (pItem) {
|
||||
this->remove(*pItem, *this);
|
||||
}
|
||||
return pItem;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// tsSLNode<>
|
||||
//
|
||||
template <class T>
|
||||
class tsSLNode {
|
||||
friend class tsSLList<T>;
|
||||
friend class tsSLIter<T>;
|
||||
public:
|
||||
tsSLNode() : pNext(0) {}
|
||||
|
||||
//
|
||||
// when someone copies int a class deriving from this
|
||||
// do _not_ change the node pointers
|
||||
//
|
||||
void operator = (tsSLNode<T> &) {}
|
||||
|
||||
T *next() {return this->pNext;}
|
||||
private:
|
||||
T *pNext;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class tsSLIter {
|
||||
public:
|
||||
tsSLIter(tsSLList<T> &listIn) :
|
||||
pCurrent(0), pPrevious(0), list(listIn) {}
|
||||
void operator = (tsSLList<T> &listIn)
|
||||
{
|
||||
list = listIn;
|
||||
pCurrent = 0;
|
||||
pPrevious = 0;
|
||||
}
|
||||
|
||||
T * operator () ()
|
||||
{
|
||||
tsSLNode<T> *pPrev = this->pCurrent;
|
||||
T *pCur;
|
||||
if (pPrev==0) {
|
||||
pPrev = &this->list;
|
||||
}
|
||||
this->pPrevious = pPrev;
|
||||
pCur = pPrev->pNext;
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
tsSLNode<T> * prev () const
|
||||
{
|
||||
return this->pPrevious;
|
||||
}
|
||||
|
||||
private:
|
||||
T *pCurrent;
|
||||
tsSLNode<T> *pPrevious;
|
||||
tsSLList<T> &list;
|
||||
};
|
||||
|
||||
394
src/libCom/cxxTemplates/resourceLib.h
Normal file
394
src/libCom/cxxTemplates/resourceLib.h
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* 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$
|
||||
*
|
||||
* NOTES:
|
||||
* .01 Storage for identifier must persist until an item is deleted
|
||||
* .02 class T must derive from class ID and tsSLNode<T>
|
||||
*/
|
||||
|
||||
#ifndef INCresourceLibh
|
||||
#define INCresourceLibh
|
||||
|
||||
#include <tsSLList.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef int resLibStatus;
|
||||
typedef unsigned resTableIndex;
|
||||
|
||||
const unsigned resTableIndexBitWidth = (sizeof(resTableIndex)*CHAR_BIT);
|
||||
|
||||
template <class T, class ID>
|
||||
class resTable {
|
||||
public:
|
||||
resTable() :
|
||||
pTable(0), hashIdMask(0), hashIdNBits(0), nInUse(0) {}
|
||||
|
||||
int init(unsigned nHashTableEntries)
|
||||
{
|
||||
unsigned nbits;
|
||||
|
||||
if (nHashTableEntries<1u) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// count the number of bits in the hash index
|
||||
//
|
||||
for (nbits=0; nbits<resTableIndexBitWidth; nbits++) {
|
||||
this->hashIdMask = (1<<nbits) - 1;
|
||||
if ( ((nHashTableEntries-1) & ~this->hashIdMask) == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->hashIdNBits = nbits;
|
||||
this->nInUse = 0u;
|
||||
this->pTable = new tsSLList<T> [this->hashIdMask+1u];
|
||||
if (!pTable) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
~resTable()
|
||||
{
|
||||
assert (this->nInUse == 0u);
|
||||
|
||||
if (this->pTable) {
|
||||
delete [] this->pTable;
|
||||
}
|
||||
}
|
||||
|
||||
void destroyAllEntries()
|
||||
{
|
||||
tsSLList<T> *pList = this->pTable;
|
||||
|
||||
while (pList<&this->pTable[this->hashIdMask+1]) {
|
||||
tsSLIter<T> iter(*pList);
|
||||
T *pItem;
|
||||
T *pNextItem;
|
||||
|
||||
pItem = iter();
|
||||
while (pItem) {
|
||||
pNextItem = iter();
|
||||
delete pItem;
|
||||
this->nInUse--;
|
||||
pItem = pNextItem;
|
||||
}
|
||||
pList++;
|
||||
}
|
||||
}
|
||||
|
||||
void show (unsigned level)
|
||||
{
|
||||
tsSLList<T> *pList;
|
||||
double X;
|
||||
double XX;
|
||||
double mean;
|
||||
double stdDev;
|
||||
unsigned maxEntries;
|
||||
|
||||
printf("resTable with %d resources installed\n", this->nInUse);
|
||||
|
||||
if (level >=1u) {
|
||||
pList = this->pTable;
|
||||
X = 0.0;
|
||||
XX = 0.0;
|
||||
maxEntries = 0;
|
||||
while (pList < &this->pTable[this->hashIdMask+1]) {
|
||||
unsigned count;
|
||||
tsSLIter<T> iter(*pList);
|
||||
T *pItem;
|
||||
|
||||
count = 0;
|
||||
while ( (pItem = iter()) ) {
|
||||
if (level >= 3u) {
|
||||
pItem->show (level);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
X += count;
|
||||
XX += count*count;
|
||||
if (count>maxEntries) {
|
||||
maxEntries = count;
|
||||
}
|
||||
pList++;
|
||||
}
|
||||
|
||||
mean = X/(this->hashIdMask+1);
|
||||
stdDev = sqrt(XX/(this->hashIdMask+1)- mean*mean);
|
||||
printf(
|
||||
"entries/table index - mean = %f std dev = %f max = %d\n",
|
||||
mean, stdDev, maxEntries);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
int add (T &res)
|
||||
{
|
||||
//
|
||||
// T must derive from ID
|
||||
//
|
||||
tsSLList<T> &list = this->pTable[this->hash(res)];
|
||||
tsSLNode<T> *pPrev;
|
||||
|
||||
pPrev = this->find(list, res);
|
||||
if (pPrev) {
|
||||
return -1;
|
||||
}
|
||||
list.add(res);
|
||||
this->nInUse++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
T *remove (const ID &idIn)
|
||||
{
|
||||
tsSLList<T> &list = this->pTable[this->hash(idIn)];
|
||||
tsSLNode<T> *pPrev;
|
||||
T *pItem;
|
||||
|
||||
pPrev = this->find(list, idIn);
|
||||
if (!pPrev) {
|
||||
return 0;
|
||||
}
|
||||
this->nInUse--;
|
||||
pItem = pPrev->next();
|
||||
list.remove(*pItem, *pPrev);
|
||||
return pItem;
|
||||
}
|
||||
|
||||
|
||||
T *lookup (const ID &idIn)
|
||||
{
|
||||
tsSLList<T> &list = this->pTable[this->hash(idIn)];
|
||||
tsSLNode<T> *pPrev;
|
||||
|
||||
pPrev = this->find(list, idIn);
|
||||
if (pPrev) {
|
||||
return pPrev->next();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
tsSLList<T> *pTable;
|
||||
unsigned hashIdMask;
|
||||
unsigned hashIdNBits;
|
||||
unsigned nInUse;
|
||||
|
||||
resTableIndex hash(const ID & idIn)
|
||||
{
|
||||
resTableIndex hashid;
|
||||
hashid = idIn.resourceHash(this->hashIdNBits);
|
||||
return hashid & this->hashIdMask;
|
||||
}
|
||||
|
||||
//
|
||||
// beware - this returns a pointer to the node just prior to the
|
||||
// the item found on the list
|
||||
//
|
||||
tsSLNode<T> *find(tsSLList<T> &list, const ID &idIn)
|
||||
{
|
||||
tsSLIter<T> iter(list);
|
||||
T *pItem;
|
||||
ID *pId;
|
||||
|
||||
while ( (pItem = iter()) ) {
|
||||
pId = pItem;
|
||||
if (*pId == idIn) {
|
||||
return iter.prev();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Some ID classes that work with the above template
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// unsigned identifier
|
||||
//
|
||||
class uintId {
|
||||
public:
|
||||
uintId(unsigned idIn=~0u) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
unsigned src = this->id;
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = src;
|
||||
src = src >> nBitsId;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> nBitsId;
|
||||
}
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const uintId &idIn)
|
||||
{
|
||||
return this->id == idIn.id;
|
||||
}
|
||||
|
||||
const unsigned getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
protected:
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
//
|
||||
// resource with unsigned chronological identifier
|
||||
//
|
||||
template <class ITEM>
|
||||
class uintRes : public uintId, public tsSLNode<ITEM> {
|
||||
friend class uintResTable<ITEM>;
|
||||
};
|
||||
|
||||
//
|
||||
// special resource table which uses
|
||||
// unsigned integer keys allocated in chronological sequence
|
||||
//
|
||||
template <class ITEM>
|
||||
class uintResTable : public resTable<ITEM, uintId> {
|
||||
public:
|
||||
uintResTable() : allocId(1u) {} // hashing is faster close to zero
|
||||
|
||||
//
|
||||
// NOTE: This detects (and avoids) the case where
|
||||
// the PV id wraps around and we attempt to have two
|
||||
// resources with the same id.
|
||||
//
|
||||
void installItem(ITEM &item)
|
||||
{
|
||||
int resTblStatus;
|
||||
do {
|
||||
item.uintId::id = this->allocId++;
|
||||
resTblStatus = this->add(item);
|
||||
}
|
||||
while (resTblStatus);
|
||||
}
|
||||
private:
|
||||
unsigned allocId;
|
||||
};
|
||||
|
||||
//
|
||||
// pointer identifier
|
||||
//
|
||||
class ptrId {
|
||||
public:
|
||||
ptrId (void const * const idIn) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
//
|
||||
// This makes the assumption that
|
||||
// a pointer will fit inside of a long
|
||||
// (this assumption may not port to all
|
||||
// CPU architectures)
|
||||
//
|
||||
unsigned long src = (unsigned long) this->id;
|
||||
resTableIndex hashid;
|
||||
|
||||
hashid = src;
|
||||
src = src >> nBitsId;
|
||||
while (src) {
|
||||
hashid = hashid ^ src;
|
||||
src = src >> nBitsId;
|
||||
}
|
||||
//
|
||||
// the result here is always masked to the
|
||||
// proper size after it is returned to the resource class
|
||||
//
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const ptrId &idIn)
|
||||
{
|
||||
return this->id == idIn.id;
|
||||
}
|
||||
private:
|
||||
void const * const id;
|
||||
};
|
||||
|
||||
//
|
||||
// character string identifier
|
||||
//
|
||||
class stringId {
|
||||
public:
|
||||
stringId (char const * const idIn) : id(idIn) {}
|
||||
|
||||
resTableIndex resourceHash(unsigned nBitsId) const
|
||||
{
|
||||
const char *pStr = this->id;
|
||||
resTableIndex hashid;
|
||||
unsigned i;
|
||||
|
||||
hashid = 0u;
|
||||
for (i=0u; pStr[i]; i++) {
|
||||
hashid += pStr[i] * (i+1u);
|
||||
}
|
||||
|
||||
hashid = hashid % (1u<<nBitsId);
|
||||
|
||||
return hashid;
|
||||
}
|
||||
|
||||
int operator == (const stringId &idIn)
|
||||
{
|
||||
return strcmp(this->id,idIn.id)==0;
|
||||
}
|
||||
|
||||
const char * resourceName()
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void show (unsigned)
|
||||
{
|
||||
printf ("resource id = %s\n", id);
|
||||
}
|
||||
private:
|
||||
char const * const id;
|
||||
};
|
||||
|
||||
#endif // INCresourceLibh
|
||||
|
||||
290
src/libCom/cxxTemplates/tsDLList.h
Normal file
290
src/libCom/cxxTemplates/tsDLList.h
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* type safe doubly linked list templates
|
||||
*
|
||||
* 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 tsDLListH_include
|
||||
#define tsDLListH_include
|
||||
|
||||
//
|
||||
// tsDLList<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLList {
|
||||
private:
|
||||
//
|
||||
// clear()
|
||||
//
|
||||
void clear()
|
||||
{
|
||||
this->pFirst = 0;
|
||||
this->pLast = 0;
|
||||
this->itemCount = 0u;
|
||||
}
|
||||
public:
|
||||
tsDLList ()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
//
|
||||
// adds addList to this (and removes all items from addList)
|
||||
//
|
||||
tsDLList (tsDLList<T> &addList)
|
||||
{
|
||||
*this = addList;
|
||||
addList.clear();
|
||||
}
|
||||
|
||||
//
|
||||
// first()
|
||||
//
|
||||
T *first() const
|
||||
{
|
||||
return (T *) this->pFirst;
|
||||
}
|
||||
|
||||
//
|
||||
// last()
|
||||
//
|
||||
T *last() const
|
||||
{
|
||||
return (T *) this->pLast;
|
||||
}
|
||||
|
||||
//
|
||||
// count()
|
||||
//
|
||||
unsigned count() const
|
||||
{
|
||||
return this->itemCount;
|
||||
}
|
||||
|
||||
//
|
||||
// add() -
|
||||
// adds addList to this (and removes all items from addList)
|
||||
//
|
||||
void add (tsDLList<T> &addList)
|
||||
{
|
||||
//
|
||||
// NOOP if addList is empty
|
||||
//
|
||||
if (addList.itemCount==0u) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->itemCount==0u) {
|
||||
//
|
||||
// this is empty so just init from
|
||||
// addList
|
||||
//
|
||||
*this = addList;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// add addList to the end of this
|
||||
//
|
||||
this->pLast->tsDLNode<T>::pNext = addList.pFirst;
|
||||
addList.pFirst->tsDLNode<T>::pPrev = addList.pLast;
|
||||
this->pLast = addList.pLast;
|
||||
this->itemCount += addList.itemCount;
|
||||
}
|
||||
|
||||
//
|
||||
// leave addList empty
|
||||
//
|
||||
addList.clear();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// add() - an item
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
item.tsDLNode<T>::pNext = 0;
|
||||
item.tsDLNode<T>::pPrev = this->pLast;
|
||||
|
||||
if (this->itemCount) {
|
||||
this->pLast->tsDLNode<T>::pNext = &item;
|
||||
}
|
||||
else {
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
this->pLast = &item;
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// insert()
|
||||
// pItemBefore==0 => make item be the first item on the list
|
||||
// pItemBefore!=0 => place item in the list immediately after
|
||||
// pItemBefore
|
||||
//
|
||||
void insert (T &item, T *pItemBefore=0)
|
||||
{
|
||||
if (pItemBefore) {
|
||||
item.tsDLNode<T>::pPrev = pItemBefore;
|
||||
item.tsDLNode<T>::pNext =
|
||||
pItemBefore->tsDLNode<T>::pNext;
|
||||
pItemBefore->tsDLNode<T>::pNext = &item;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pPrev = 0;
|
||||
item.tsDLNode<T>::pNext = this->pFirst;
|
||||
this->pFirst = &item;
|
||||
}
|
||||
|
||||
if (item.tsDLNode<T>::pNext) {
|
||||
item.tsDLNode<T>::pNext->tsDLNode<T>::pPrev = &item;
|
||||
}
|
||||
else {
|
||||
this->pLast = &item;
|
||||
}
|
||||
|
||||
this->itemCount++;
|
||||
}
|
||||
|
||||
//
|
||||
// remove ()
|
||||
//
|
||||
void remove (T &item)
|
||||
{
|
||||
if (this->pLast == &item) {
|
||||
this->pLast = item.tsDLNode<T>::pPrev;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pNext->tsDLNode<T>::pPrev =
|
||||
item.tsDLNode<T>::pPrev;
|
||||
}
|
||||
|
||||
if (this->pFirst == &item) {
|
||||
this->pFirst = item.tsDLNode<T>::pNext;
|
||||
}
|
||||
else {
|
||||
item.tsDLNode<T>::pPrev->tsDLNode<T>::pNext =
|
||||
item.tsDLNode<T>::pNext;
|
||||
}
|
||||
|
||||
this->itemCount--;
|
||||
}
|
||||
|
||||
//
|
||||
// get ()
|
||||
//
|
||||
T * get()
|
||||
{
|
||||
T *pItem = this->pFirst;
|
||||
|
||||
if (pItem) {
|
||||
this->remove (*pItem);
|
||||
}
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
private:
|
||||
T *pFirst;
|
||||
T *pLast;
|
||||
unsigned itemCount;
|
||||
};
|
||||
|
||||
//
|
||||
// tsDLNode<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLNode {
|
||||
friend class tsDLList<T>;
|
||||
friend class tsDLIter<T>;
|
||||
public:
|
||||
tsDLNode() : pNext(0), pPrev(0) {}
|
||||
//
|
||||
// when someone copies int a class deriving from this
|
||||
// do _not_ change the node pointers
|
||||
//
|
||||
void operator = (tsDLNode<T> &) {}
|
||||
|
||||
T *getPrev() {return this->pPrev;}
|
||||
T *getNext() {return this->pNext;}
|
||||
private:
|
||||
T *pNext;
|
||||
T *pPrev;
|
||||
};
|
||||
|
||||
//
|
||||
// tsDLIter<T>
|
||||
//
|
||||
template <class T>
|
||||
class tsDLIter {
|
||||
public:
|
||||
tsDLIter(tsDLList<T> &listIn) :
|
||||
list(listIn), pCurrent(0) {}
|
||||
|
||||
void reset ()
|
||||
{
|
||||
this->pCurrent = 0;
|
||||
}
|
||||
|
||||
void reset (tsDLList<T> &listIn)
|
||||
{
|
||||
this->reset();
|
||||
this->list = listIn;
|
||||
}
|
||||
|
||||
void operator = (tsDLList<T> &listIn)
|
||||
{
|
||||
this->reset(listIn);
|
||||
}
|
||||
|
||||
T * operator () ()
|
||||
{
|
||||
T *pCur = this->pCurrent;
|
||||
if (pCur==0) {
|
||||
pCur = this->list.first();
|
||||
}
|
||||
else {
|
||||
pCur = pCur->tsDLNode<T>::pNext;
|
||||
}
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
private:
|
||||
tsDLList<T> &list;
|
||||
T *pCurrent;
|
||||
};
|
||||
|
||||
#endif // tsDLListH_include
|
||||
|
||||
151
src/libCom/cxxTemplates/tsSLList.h
Normal file
151
src/libCom/cxxTemplates/tsSLList.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* tsSLList - type safe singly linked list templates
|
||||
*
|
||||
* 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$
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// tsSLList<>
|
||||
//
|
||||
template <class T>
|
||||
class tsSLList : public tsSLNode<T> {
|
||||
public:
|
||||
tsSLList () {}
|
||||
|
||||
//
|
||||
// first()
|
||||
//
|
||||
T *first() const
|
||||
{
|
||||
return this->tsSLNode<T>::pNext;
|
||||
}
|
||||
|
||||
//
|
||||
// insert()
|
||||
// (itemBefore might be the list header object and therefore
|
||||
// will not always be of type T)
|
||||
//
|
||||
void insert (T &item, tsSLNode<T> &itemBefore)
|
||||
{
|
||||
item.tsSLNode<T>::pNext = itemBefore.pNext;
|
||||
itemBefore.pNext = &item;
|
||||
}
|
||||
|
||||
//
|
||||
// add()
|
||||
//
|
||||
void add (T &item)
|
||||
{
|
||||
this->insert (item, *this);
|
||||
}
|
||||
|
||||
//
|
||||
// remove ()
|
||||
// (itemBefore might be the list header object and therefore
|
||||
// will not always be of type T)
|
||||
//
|
||||
void remove (T &item, tsSLNode<T> &itemBefore)
|
||||
{
|
||||
itemBefore.tsSLNode<T>::pNext = item.tsSLNode<T>::pNext;
|
||||
}
|
||||
|
||||
//
|
||||
// get ()
|
||||
//
|
||||
T * get()
|
||||
{
|
||||
T *pItem = this->tsSLNode<T>::pNext;
|
||||
if (pItem) {
|
||||
this->remove(*pItem, *this);
|
||||
}
|
||||
return pItem;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// tsSLNode<>
|
||||
//
|
||||
template <class T>
|
||||
class tsSLNode {
|
||||
friend class tsSLList<T>;
|
||||
friend class tsSLIter<T>;
|
||||
public:
|
||||
tsSLNode() : pNext(0) {}
|
||||
|
||||
//
|
||||
// when someone copies int a class deriving from this
|
||||
// do _not_ change the node pointers
|
||||
//
|
||||
void operator = (tsSLNode<T> &) {}
|
||||
|
||||
T *next() {return this->pNext;}
|
||||
private:
|
||||
T *pNext;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class tsSLIter {
|
||||
public:
|
||||
tsSLIter(tsSLList<T> &listIn) :
|
||||
pCurrent(0), pPrevious(0), list(listIn) {}
|
||||
void operator = (tsSLList<T> &listIn)
|
||||
{
|
||||
list = listIn;
|
||||
pCurrent = 0;
|
||||
pPrevious = 0;
|
||||
}
|
||||
|
||||
T * operator () ()
|
||||
{
|
||||
tsSLNode<T> *pPrev = this->pCurrent;
|
||||
T *pCur;
|
||||
if (pPrev==0) {
|
||||
pPrev = &this->list;
|
||||
}
|
||||
this->pPrevious = pPrev;
|
||||
pCur = pPrev->pNext;
|
||||
this->pCurrent = pCur;
|
||||
return pCur;
|
||||
}
|
||||
|
||||
tsSLNode<T> * prev () const
|
||||
{
|
||||
return this->pPrevious;
|
||||
}
|
||||
|
||||
private:
|
||||
T *pCurrent;
|
||||
tsSLNode<T> *pPrevious;
|
||||
tsSLList<T> &list;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user