diff --git a/src/cxxTemplates/Makefile b/src/cxxTemplates/Makefile new file mode 100644 index 000000000..5ab776fa9 --- /dev/null +++ b/src/cxxTemplates/Makefile @@ -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 + diff --git a/src/cxxTemplates/Makefile.Unix b/src/cxxTemplates/Makefile.Unix new file mode 100644 index 000000000..c9438d3be --- /dev/null +++ b/src/cxxTemplates/Makefile.Unix @@ -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 diff --git a/src/cxxTemplates/osiTime.h b/src/cxxTemplates/osiTime.h new file mode 100644 index 000000000..67d3815e4 --- /dev/null +++ b/src/cxxTemplates/osiTime.h @@ -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 +#ifndef assert // allows use of epicsAssert.h +#include +#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 (nSecInsec = 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= (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.nSec) { + rc = 1; + } + else { + rc = 0; + } + } + return rc; +} + +#endif // osiTimehInclude + diff --git a/src/cxxTemplates/osiTimer.h b/src/cxxTemplates/osiTimer.h new file mode 100644 index 000000000..6df763c5d --- /dev/null +++ b/src/cxxTemplates/osiTimer.h @@ -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 +#include + +enum osiBool {osiFalse=0, osiTrue=1}; +enum osiTimerState {ositPending, ositExpired, ositLimbo}; + +// +// osiTimer +// +class osiTimer : public tsDLNode { + 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 pending; + tsDLList expired; + osiBool inProcess; + + void install (osiTimer &tmr, osiTime delay); +}; + +extern osiTimerQueue staticTimerQueue; + + +#endif // osiTimerHInclude + diff --git a/src/cxxTemplates/resourceLib.h b/src/cxxTemplates/resourceLib.h new file mode 100644 index 000000000..ffa1f5084 --- /dev/null +++ b/src/cxxTemplates/resourceLib.h @@ -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 + */ + +#ifndef INCresourceLibh +#define INCresourceLibh + +#include +#include + +typedef int resLibStatus; +typedef unsigned resTableIndex; + +const unsigned resTableIndexBitWidth = (sizeof(resTableIndex)*CHAR_BIT); + +template +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; nbitshashIdMask = (1<hashIdMask) == 0){ + break; + } + } + this->hashIdNBits = nbits; + this->nInUse = 0u; + this->pTable = new tsSLList [this->hashIdMask+1u]; + if (!pTable) { + return -1; + } + return 0; + } + + ~resTable() + { + assert (this->nInUse == 0u); + + if (this->pTable) { + delete [] this->pTable; + } + } + + void destroyAllEntries() + { + tsSLList *pList = this->pTable; + + while (pList<&this->pTable[this->hashIdMask+1]) { + tsSLIter iter(*pList); + T *pItem; + T *pNextItem; + + pItem = iter(); + while (pItem) { + pNextItem = iter(); + delete pItem; + this->nInUse--; + pItem = pNextItem; + } + pList++; + } + } + + void show (unsigned level) + { + tsSLList *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 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 &list = this->pTable[this->hash(res)]; + tsSLNode *pPrev; + + pPrev = this->find(list, res); + if (pPrev) { + return -1; + } + list.add(res); + this->nInUse++; + return 0; + } + + T *remove (const ID &idIn) + { + tsSLList &list = this->pTable[this->hash(idIn)]; + tsSLNode *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 &list = this->pTable[this->hash(idIn)]; + tsSLNode *pPrev; + + pPrev = this->find(list, idIn); + if (pPrev) { + return pPrev->next(); + } + return NULL; + } + +private: + tsSLList *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 *find(tsSLList &list, const ID &idIn) + { + tsSLIter 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 uintRes : public uintId, public tsSLNode { +friend class uintResTable; +}; + +// +// special resource table which uses +// unsigned integer keys allocated in chronological sequence +// +template +class uintResTable : public resTable { +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<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 + diff --git a/src/cxxTemplates/tsDLList.h b/src/cxxTemplates/tsDLList.h new file mode 100644 index 000000000..6c489e559 --- /dev/null +++ b/src/cxxTemplates/tsDLList.h @@ -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 +// +template +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 &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 &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::pNext = addList.pFirst; + addList.pFirst->tsDLNode::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::pNext = 0; + item.tsDLNode::pPrev = this->pLast; + + if (this->itemCount) { + this->pLast->tsDLNode::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::pPrev = pItemBefore; + item.tsDLNode::pNext = + pItemBefore->tsDLNode::pNext; + pItemBefore->tsDLNode::pNext = &item; + } + else { + item.tsDLNode::pPrev = 0; + item.tsDLNode::pNext = this->pFirst; + this->pFirst = &item; + } + + if (item.tsDLNode::pNext) { + item.tsDLNode::pNext->tsDLNode::pPrev = &item; + } + else { + this->pLast = &item; + } + + this->itemCount++; + } + + // + // remove () + // + void remove (T &item) + { + if (this->pLast == &item) { + this->pLast = item.tsDLNode::pPrev; + } + else { + item.tsDLNode::pNext->tsDLNode::pPrev = + item.tsDLNode::pPrev; + } + + if (this->pFirst == &item) { + this->pFirst = item.tsDLNode::pNext; + } + else { + item.tsDLNode::pPrev->tsDLNode::pNext = + item.tsDLNode::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 +// +template +class tsDLNode { +friend class tsDLList; +friend class tsDLIter; +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 *getPrev() {return this->pPrev;} + T *getNext() {return this->pNext;} +private: + T *pNext; + T *pPrev; +}; + +// +// tsDLIter +// +template +class tsDLIter { +public: + tsDLIter(tsDLList &listIn) : + list(listIn), pCurrent(0) {} + + void reset () + { + this->pCurrent = 0; + } + + void reset (tsDLList &listIn) + { + this->reset(); + this->list = listIn; + } + + void operator = (tsDLList &listIn) + { + this->reset(listIn); + } + + T * operator () () + { + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->list.first(); + } + else { + pCur = pCur->tsDLNode::pNext; + } + this->pCurrent = pCur; + return pCur; + } +private: + tsDLList &list; + T *pCurrent; +}; + +#endif // tsDLListH_include + diff --git a/src/cxxTemplates/tsSLList.h b/src/cxxTemplates/tsSLList.h new file mode 100644 index 000000000..e2c15b88b --- /dev/null +++ b/src/cxxTemplates/tsSLList.h @@ -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 tsSLList : public tsSLNode { +public: + tsSLList () {} + + // + // first() + // + T *first() const + { + return this->tsSLNode::pNext; + } + + // + // insert() + // (itemBefore might be the list header object and therefore + // will not always be of type T) + // + void insert (T &item, tsSLNode &itemBefore) + { + item.tsSLNode::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 &itemBefore) + { + itemBefore.tsSLNode::pNext = item.tsSLNode::pNext; + } + + // + // get () + // + T * get() + { + T *pItem = this->tsSLNode::pNext; + if (pItem) { + this->remove(*pItem, *this); + } + return pItem; + } +}; + +// +// tsSLNode<> +// +template +class tsSLNode { +friend class tsSLList; +friend class tsSLIter; +public: + tsSLNode() : pNext(0) {} + + // + // when someone copies int a class deriving from this + // do _not_ change the node pointers + // + void operator = (tsSLNode &) {} + + T *next() {return this->pNext;} +private: + T *pNext; +}; + +template +class tsSLIter { +public: + tsSLIter(tsSLList &listIn) : + pCurrent(0), pPrevious(0), list(listIn) {} + void operator = (tsSLList &listIn) + { + list = listIn; + pCurrent = 0; + pPrevious = 0; + } + + T * operator () () + { + tsSLNode *pPrev = this->pCurrent; + T *pCur; + if (pPrev==0) { + pPrev = &this->list; + } + this->pPrevious = pPrev; + pCur = pPrev->pNext; + this->pCurrent = pCur; + return pCur; + } + + tsSLNode * prev () const + { + return this->pPrevious; + } + +private: + T *pCurrent; + tsSLNode *pPrevious; + tsSLList &list; +}; + diff --git a/src/libCom/cxxTemplates/resourceLib.h b/src/libCom/cxxTemplates/resourceLib.h new file mode 100644 index 000000000..ffa1f5084 --- /dev/null +++ b/src/libCom/cxxTemplates/resourceLib.h @@ -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 + */ + +#ifndef INCresourceLibh +#define INCresourceLibh + +#include +#include + +typedef int resLibStatus; +typedef unsigned resTableIndex; + +const unsigned resTableIndexBitWidth = (sizeof(resTableIndex)*CHAR_BIT); + +template +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; nbitshashIdMask = (1<hashIdMask) == 0){ + break; + } + } + this->hashIdNBits = nbits; + this->nInUse = 0u; + this->pTable = new tsSLList [this->hashIdMask+1u]; + if (!pTable) { + return -1; + } + return 0; + } + + ~resTable() + { + assert (this->nInUse == 0u); + + if (this->pTable) { + delete [] this->pTable; + } + } + + void destroyAllEntries() + { + tsSLList *pList = this->pTable; + + while (pList<&this->pTable[this->hashIdMask+1]) { + tsSLIter iter(*pList); + T *pItem; + T *pNextItem; + + pItem = iter(); + while (pItem) { + pNextItem = iter(); + delete pItem; + this->nInUse--; + pItem = pNextItem; + } + pList++; + } + } + + void show (unsigned level) + { + tsSLList *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 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 &list = this->pTable[this->hash(res)]; + tsSLNode *pPrev; + + pPrev = this->find(list, res); + if (pPrev) { + return -1; + } + list.add(res); + this->nInUse++; + return 0; + } + + T *remove (const ID &idIn) + { + tsSLList &list = this->pTable[this->hash(idIn)]; + tsSLNode *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 &list = this->pTable[this->hash(idIn)]; + tsSLNode *pPrev; + + pPrev = this->find(list, idIn); + if (pPrev) { + return pPrev->next(); + } + return NULL; + } + +private: + tsSLList *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 *find(tsSLList &list, const ID &idIn) + { + tsSLIter 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 uintRes : public uintId, public tsSLNode { +friend class uintResTable; +}; + +// +// special resource table which uses +// unsigned integer keys allocated in chronological sequence +// +template +class uintResTable : public resTable { +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<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 + diff --git a/src/libCom/cxxTemplates/tsDLList.h b/src/libCom/cxxTemplates/tsDLList.h new file mode 100644 index 000000000..6c489e559 --- /dev/null +++ b/src/libCom/cxxTemplates/tsDLList.h @@ -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 +// +template +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 &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 &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::pNext = addList.pFirst; + addList.pFirst->tsDLNode::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::pNext = 0; + item.tsDLNode::pPrev = this->pLast; + + if (this->itemCount) { + this->pLast->tsDLNode::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::pPrev = pItemBefore; + item.tsDLNode::pNext = + pItemBefore->tsDLNode::pNext; + pItemBefore->tsDLNode::pNext = &item; + } + else { + item.tsDLNode::pPrev = 0; + item.tsDLNode::pNext = this->pFirst; + this->pFirst = &item; + } + + if (item.tsDLNode::pNext) { + item.tsDLNode::pNext->tsDLNode::pPrev = &item; + } + else { + this->pLast = &item; + } + + this->itemCount++; + } + + // + // remove () + // + void remove (T &item) + { + if (this->pLast == &item) { + this->pLast = item.tsDLNode::pPrev; + } + else { + item.tsDLNode::pNext->tsDLNode::pPrev = + item.tsDLNode::pPrev; + } + + if (this->pFirst == &item) { + this->pFirst = item.tsDLNode::pNext; + } + else { + item.tsDLNode::pPrev->tsDLNode::pNext = + item.tsDLNode::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 +// +template +class tsDLNode { +friend class tsDLList; +friend class tsDLIter; +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 *getPrev() {return this->pPrev;} + T *getNext() {return this->pNext;} +private: + T *pNext; + T *pPrev; +}; + +// +// tsDLIter +// +template +class tsDLIter { +public: + tsDLIter(tsDLList &listIn) : + list(listIn), pCurrent(0) {} + + void reset () + { + this->pCurrent = 0; + } + + void reset (tsDLList &listIn) + { + this->reset(); + this->list = listIn; + } + + void operator = (tsDLList &listIn) + { + this->reset(listIn); + } + + T * operator () () + { + T *pCur = this->pCurrent; + if (pCur==0) { + pCur = this->list.first(); + } + else { + pCur = pCur->tsDLNode::pNext; + } + this->pCurrent = pCur; + return pCur; + } +private: + tsDLList &list; + T *pCurrent; +}; + +#endif // tsDLListH_include + diff --git a/src/libCom/cxxTemplates/tsSLList.h b/src/libCom/cxxTemplates/tsSLList.h new file mode 100644 index 000000000..e2c15b88b --- /dev/null +++ b/src/libCom/cxxTemplates/tsSLList.h @@ -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 tsSLList : public tsSLNode { +public: + tsSLList () {} + + // + // first() + // + T *first() const + { + return this->tsSLNode::pNext; + } + + // + // insert() + // (itemBefore might be the list header object and therefore + // will not always be of type T) + // + void insert (T &item, tsSLNode &itemBefore) + { + item.tsSLNode::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 &itemBefore) + { + itemBefore.tsSLNode::pNext = item.tsSLNode::pNext; + } + + // + // get () + // + T * get() + { + T *pItem = this->tsSLNode::pNext; + if (pItem) { + this->remove(*pItem, *this); + } + return pItem; + } +}; + +// +// tsSLNode<> +// +template +class tsSLNode { +friend class tsSLList; +friend class tsSLIter; +public: + tsSLNode() : pNext(0) {} + + // + // when someone copies int a class deriving from this + // do _not_ change the node pointers + // + void operator = (tsSLNode &) {} + + T *next() {return this->pNext;} +private: + T *pNext; +}; + +template +class tsSLIter { +public: + tsSLIter(tsSLList &listIn) : + pCurrent(0), pPrevious(0), list(listIn) {} + void operator = (tsSLList &listIn) + { + list = listIn; + pCurrent = 0; + pPrevious = 0; + } + + T * operator () () + { + tsSLNode *pPrev = this->pCurrent; + T *pCur; + if (pPrev==0) { + pPrev = &this->list; + } + this->pPrevious = pPrev; + pCur = pPrev->pNext; + this->pCurrent = pCur; + return pCur; + } + + tsSLNode * prev () const + { + return this->pPrevious; + } + +private: + T *pCurrent; + tsSLNode *pPrevious; + tsSLList &list; +}; +