29 #ifndef INCresourceLibh
30 #define INCresourceLibh
39 #ifndef assert // allow use of epicsAssert.h
44 #include "epicsString.h"
45 #include "libComAPI.h"
46 typedef size_t resTableIndex;
76 template <
class T,
class ID>
82 void show (
unsigned level )
const;
85 T *
remove (
const ID &idIn );
87 T * lookup (
const ID &idIn )
const;
90 void traverse (
void (T::*pCB)() );
91 void traverseConst (
void (T::*pCB)()
const )
const;
92 unsigned numEntriesInstalled ()
const;
93 void setTableSize (
const unsigned newTableSize );
102 unsigned nextSplitIndex;
104 unsigned hashIxSplitMask;
105 unsigned nBitsHashIxSplitMask;
106 unsigned logBaseTwoTableSize;
108 resTableIndex hash (
const ID & idIn )
const;
109 T * find (
tsSLList<T> & list,
const ID & idIn )
const;
111 unsigned tableSize ()
const;
112 bool setTableSizePrivate (
unsigned logBaseTwoTableSize );
115 static unsigned resTableBitMask (
const unsigned nBits );
125 template <
class T,
class ID >
133 T & operator * ()
const;
134 T * operator -> ()
const;
143 void findNextEntry ();
152 template <
class T,
class ID >
160 const T & operator * ()
const;
161 const T * operator -> ()
const;
164 const T * pointer ()
const;
170 void findNextEntry ();
199 template <
class T,
unsigned MIN_INDEX_WIDTH=4u,
200 unsigned MAX_ID_WIDTH =
sizeof(T)*CHAR_BIT>
203 intId (
const T &idIn);
204 bool operator == (
const intId &idIn)
const;
205 resTableIndex hash ()
const;
206 const T getId()
const;
225 template <
class ITEM>
230 void idAssignAdd (
ITEM & item );
242 template <
class ITEM>
247 void setId (
unsigned newId);
259 enum allocationType {copyString, refString};
260 stringId (
const char * idIn, allocationType typeIn=copyString);
262 resTableIndex hash ()
const;
263 bool operator == (
const stringId &idIn)
const;
264 const char * resourceName()
const;
265 void show (
unsigned level)
const;
270 const allocationType allocType;
280 template <
class T,
class ID>
282 pTable ( 0 ), nextSplitIndex ( 0 ), hashIxMask ( 0 ),
283 hashIxSplitMask ( 0 ), nBitsHashIxSplitMask ( 0 ),
284 logBaseTwoTableSize ( 0 ), nInUse ( 0 ) {}
286 template <
class T,
class ID>
289 return ( 1 << nBits ) - 1;
297 template <
class T,
class ID>
300 if ( this->pTable ) {
302 tsSLList<T> & list = this->pTable [ this->hash(idIn) ];
305 while ( pItem.valid () ) {
306 const ID & idOfItem = *pItem;
307 if ( idOfItem == idIn ) {
309 list.remove ( *pPrev );
317 pPrev = pItem.pointer ();
320 return pItem.pointer ();
327 template <
class T,
class ID>
330 const unsigned N = this->tableSize ();
331 for (
unsigned i = 0u; i < N; i++ ) {
332 while ( T * pItem = this->pTable[i].
get() ) {
333 destination.add ( *pItem );
342 template <
class T,
class ID>
345 if ( this->pTable ) {
346 tsSLList<T> & list = this->pTable [ this->hash ( idIn ) ];
347 return this->find ( list, idIn );
357 template <
class T,
class ID>
360 resTableIndex h = idIn.hash ();
361 resTableIndex h0 = h & this->hashIxMask;
362 if ( h0 >= this->nextSplitIndex ) {
365 return h & this->hashIxSplitMask;
371 template <
class T,
class ID>
374 const unsigned N = this->tableSize ();
376 printf (
"Hash table with %u buckets and %u items of type %s installed\n",
377 N, this->nInUse,
typeid(T).name() );
379 if ( level >= 1u && N ) {
383 while ( pList < & this->pTable[N] ) {
385 while ( pItem.valid () ) {
388 pItem.pointer()->show ( level - 2u );
397 unsigned maxEntries = 0u;
399 for (
unsigned i = 0u; i < N; i++ ) {
402 while ( pItem.valid () ) {
404 pItem->show ( level );
412 if ( count > maxEntries ) {
420 double stdDev = sqrt( XX / N - mean * mean );
422 "entries per bucket: mean = %f std dev = %f max = %u\n",
423 mean, stdDev, maxEntries );
424 printf(
"%u empty buckets\n", empty);
425 if ( X != this->nInUse ) {
426 printf (
"this->nInUse didnt match items counted which was %f????\n", X );
432 template <
class T,
class ID>
435 const unsigned N = this->tableSize ();
437 if ( this->pTable ) {
438 assert ( this->nextSplitIndex <= this->hashIxMask + 1 );
439 assert ( this->hashIxMask );
440 assert ( this->hashIxMask == ( this->hashIxSplitMask >> 1 ) );
441 assert ( this->hashIxSplitMask );
442 assert ( this->nBitsHashIxSplitMask );
443 assert ( resTableBitMask ( this->nBitsHashIxSplitMask )
444 == this->hashIxSplitMask );
445 assert ( this->logBaseTwoTableSize );
446 assert ( this->nBitsHashIxSplitMask <= this->logBaseTwoTableSize );
449 assert ( this->nextSplitIndex == 0 );
450 assert ( this->hashIxMask == 0 );
451 assert ( this->hashIxSplitMask == 0 );
452 assert ( this->nBitsHashIxSplitMask == 0 );
453 assert ( this->logBaseTwoTableSize == 0 );
457 for (
unsigned i = 0u; i < N; i++ ) {
460 while ( pItem.valid () ) {
461 resTableIndex index = this->hash ( *pItem );
468 assert ( total == this->nInUse );
475 template <
class T,
class ID>
478 const unsigned N = this->tableSize ();
479 for (
unsigned i = 0u; i < N; i++ ) {
481 while ( pItem.valid () ) {
484 ( pItem.pointer ()->*pCB ) ();
493 template <
class T,
class ID>
496 const unsigned N = this->tableSize ();
497 for (
unsigned i = 0u; i < N; i++ ) {
500 while ( pItem.valid () ) {
503 ( pItem.pointer ()->*pCB ) ();
509 template <
class T,
class ID>
515 template <
class T,
class ID>
518 if ( this->pTable ) {
519 return ( this->hashIxMask + 1 ) + this->nextSplitIndex;
528 template <
class T,
class ID>
531 if ( newTableSize == 0u ) {
539 unsigned newMask = newTableSize - 1;
541 for ( nbits = 0; nbits <
sizeof (newTableSize) * CHAR_BIT; nbits++ ) {
542 unsigned nBitsMask = resTableBitMask ( nbits );
543 if ( ( newMask & ~nBitsMask ) == 0){
547 setTableSizePrivate ( nbits );
550 template <
class T,
class ID>
554 if ( this->logBaseTwoTableSize >= logBaseTwoTableSizeIn ) {
559 if ( logBaseTwoTableSizeIn < 4 ) {
560 logBaseTwoTableSizeIn = 4;
563 const unsigned newTableSize = 1 << logBaseTwoTableSizeIn;
564 # if ! defined (__GNUC__) || __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 92 )
565 const unsigned oldTableSize = this->pTable ? 1 << this->logBaseTwoTableSize : 0;
567 const unsigned oldTableOccupiedSize = this->tableSize ();
572 ::
operator new ( newTableSize *
sizeof (
tsSLList<T> ) );
575 if ( ! this->pTable ) {
583 for ( i = 0u; i < oldTableOccupiedSize; i++ ) {
584 new ( &pNewTable[i] )
tsSLList<T> ( this->pTable[i] );
586 for ( i = oldTableOccupiedSize; i < newTableSize; i++ ) {
592 # if ! defined (__GNUC__) || __GNUC__ > 2 || ( __GNUC__ == 2 && __GNUC_MINOR__ >= 92 )
593 for ( i = 0; i < oldTableSize; i++ ) {
594 this->pTable[i].~tsSLList<T>();
598 if ( ! this->pTable ) {
599 this->hashIxSplitMask = resTableBitMask ( logBaseTwoTableSizeIn );
600 this->nBitsHashIxSplitMask = logBaseTwoTableSizeIn;
601 this->hashIxMask = this->hashIxSplitMask >> 1;
602 this->nextSplitIndex = 0;
605 operator delete ( this->pTable );
606 this->pTable = pNewTable;
607 this->logBaseTwoTableSize = logBaseTwoTableSizeIn;
612 template <
class T,
class ID>
618 if ( this->nextSplitIndex > this->hashIxMask ) {
619 bool success = this->setTableSizePrivate ( this->nBitsHashIxSplitMask + 1 );
623 this->nBitsHashIxSplitMask += 1;
624 this->hashIxSplitMask = resTableBitMask ( this->nBitsHashIxSplitMask );
625 this->hashIxMask = this->hashIxSplitMask >> 1;
626 this->nextSplitIndex = 0;
630 tsSLList<T> tmp ( this->pTable[ this->nextSplitIndex ] );
631 this->nextSplitIndex++;
632 T *pItem = tmp.get();
634 resTableIndex index = this->hash ( *pItem );
635 this->pTable[index].add ( *pItem );
643 template <
class T,
class ID>
646 if ( ! this->pTable ) {
647 this->setTableSizePrivate ( 10 );
649 else if ( this->nInUse >= this->tableSize() ) {
650 this->splitBucket ();
652 if ( this->find ( list, res ) != 0 ) {
657 if ( this->find ( list, res ) != 0 ) {
673 template <
class T,
class ID>
677 while ( pItem.valid () ) {
678 const ID & idOfItem = *pItem;
679 if ( idOfItem == idIn ) {
684 return pItem.pointer ();
690 template <
class T,
class ID>
693 operator delete ( this->pTable );
700 template <
class T,
class ID>
709 template <
class T,
class ID>
715 template <
class T,
class ID>
721 template <
class T,
class ID>
731 template <
class T,
class ID >
733 index ( 0 ), pResTable ( & tableIn )
735 this->findNextEntry ();
738 template <
class T,
class ID >
740 iter (
tsSLList<T>::invalidIter() ),
741 index ( 0 ), pResTable ( 0 )
745 template <
class T,
class ID >
748 if ( this->pResTable ) {
749 while ( this->index < this->pResTable->tableSize() ) {
750 this->iter = this->pResTable->pTable[this->index++].firstIter ();
751 if ( this->iter.valid () ) {
758 template <
class T,
class ID >
761 return this->iter.valid ();
764 template <
class T,
class ID >
768 return ( this->pResTable == rhs.pResTable
769 && this->index == rhs.index
770 && this->iter == rhs.iter );
773 template <
class T,
class ID >
774 inline bool resTableIter<T,ID>::operator !=
777 return ! this->operator == ( rhs );
780 template <
class T,
class ID >
784 this->pResTable = rhs.pResTable;
785 this->index = rhs.index;
786 this->iter = rhs.iter;
790 template <
class T,
class ID >
793 return this->iter.operator * ();
796 template <
class T,
class ID >
799 return this->iter.operator -> ();
802 template <
class T,
class ID >
806 if ( ! this->iter.valid() ) {
807 this->findNextEntry ();
812 template <
class T,
class ID >
816 this->operator ++ ();
820 template <
class T,
class ID >
823 return this->iter.pointer ();
830 template <
class T,
class ID >
832 index ( 0 ), pResTable ( & tableIn )
834 this->findNextEntry ();
837 template <
class T,
class ID >
839 iter (
tsSLList<T>::invalidIter() ),
840 index ( 0 ), pResTable ( 0 )
844 template <
class T,
class ID >
847 if ( this->pResTable ) {
848 while ( this->index < this->pResTable->tableSize() ) {
849 const tsSLList<T> * pList = & this->pResTable->pTable[this->index++];
850 this->iter = pList->firstIter ();
851 if ( this->iter.valid () ) {
858 template <
class T,
class ID >
861 return this->iter.valid ();
864 template <
class T,
class ID >
868 return ( this->pResTable == rhs.pResTable
869 && this->index == rhs.index
870 && this->iter == rhs.iter );
873 template <
class T,
class ID >
874 inline bool resTableIterConst<T,ID>::operator !=
877 return ! this->operator == ( rhs );
880 template <
class T,
class ID >
884 this->pResTable = rhs.pResTable;
885 this->index = rhs.index;
886 this->iter = rhs.iter;
890 template <
class T,
class ID >
893 return this->iter.operator * ();
896 template <
class T,
class ID >
899 return this->iter.operator -> ();
902 template <
class T,
class ID >
906 if ( ! this->iter.valid() ) {
907 this->findNextEntry ();
912 template <
class T,
class ID >
916 this->operator ++ ();
920 template <
class T,
class ID >
923 return this->iter.pointer ();
929 inline chronIntId::chronIntId (
const unsigned &idIn ) :
930 intId<unsigned, 8u, sizeof(unsigned)*CHAR_BIT> ( idIn ) {}
935 template <
class ITEM>
939 template <
class ITEM>
943 template <
class ITEM>
954 template <
class ITEM>
964 template <
class ITEM>
969 item.chronIntIdRes<ITEM>::setId (allocId++);
982 template <
class ITEM>
990 template <
class ITEM>
1004 template <
class T,
unsigned MIN_INDEX_WIDTH,
unsigned MAX_ID_WIDTH>
1011 template <
class T,
unsigned MIN_INDEX_WIDTH,
unsigned MAX_ID_WIDTH>
1015 return this->
id == idIn.id;
1021 template <
class T,
unsigned MIN_INDEX_WIDTH,
unsigned MAX_ID_WIDTH>
1032 template <
class T >
1033 inline resTableIndex integerHash (
unsigned MIN_INDEX_WIDTH,
1034 unsigned MAX_ID_WIDTH,
const T &
id )
1036 resTableIndex hashid = static_cast <resTableIndex> ( id );
1051 unsigned width = MAX_ID_WIDTH;
1054 hashid ^= hashid>>width;
1055 }
while (width>MIN_INDEX_WIDTH);
1068 template <
class T,
unsigned MIN_INDEX_WIDTH,
unsigned MAX_ID_WIDTH>
1071 return integerHash ( MIN_INDEX_WIDTH, MAX_ID_WIDTH, this->
id );
1081 inline bool stringId::operator ==
1084 if (this->pStr!=NULL && idIn.pStr!=NULL) {
1085 return strcmp(this->pStr,idIn.pStr)==0;
1093 inline const char * stringId::resourceName ()
const
1098 #ifdef instantiateRecourceLib
1103 stringId::stringId (
const char * idIn, allocationType typeIn) :
1106 if (typeIn==copyString) {
1107 unsigned nChars = strlen (idIn) + 1u;
1108 this->pStr =
new char [nChars];
1109 memcpy ( (
void *) this->pStr, idIn, nChars );
1119 void stringId::show (
unsigned level)
const
1122 printf (
"resource id = %s\n", this->pStr);
1132 stringId::~stringId()
1134 if (this->allocType==copyString) {
1135 if (this->pStr!=NULL) {
1152 delete []
const_cast<char *
>(this->pStr);
1160 resTableIndex stringId::hash()
const
1165 return epicsStrHash(this->pStr, 0);
1168 #endif // if instantiateRecourceLib is defined
1170 #endif // INCresourceLibh
#define assert(exp)
Declare that a condition should be true.
Internal: bucket item structure.