installed ca server templates

This commit is contained in:
Jeff Hill
1996-06-20 22:15:56 +00:00
parent 117b4c7a9f
commit dda8b9c9f6
10 changed files with 2055 additions and 0 deletions

18
src/cxxTemplates/Makefile Normal file
View 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

View 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
View 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
View 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

View 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
View 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
View 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;
};

View 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

View 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

View 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;
};