Пример #1
0
void UtlHashMap::destroyAll() 
{
   OsLock take(mContainerLock);

   size_t i;
   size_t toBeDestroyed;
   for (i = 0, toBeDestroyed = mElements;
        i < numberOfBuckets() && toBeDestroyed;
        i++
        ) // for each bucket
   {
      while(!mpBucket[i].isUnLinked()) // bucket is not empty yet
      {
         UtlPair* pair = static_cast<UtlPair*>(mpBucket[i].head());
         notifyIteratorsOfRemove(pair);
         pair->detachFromList(&mpBucket[i]);
         delete pair->data;
         if (pair->value != INTERNAL_NULL)
         {
            delete pair->value;
         }
         pair->release();
         toBeDestroyed--;
      }
   }
   mElements = 0;
}
Пример #2
0
/*
 * Allocate additional buckets and redistribute existing contents.
 * This should only be called through resizeIfNeededAndSafe.
 */
void UtlHashBag::resize()
{
   // already holding the mContainerLock
   UtlChain* newBucket;
   size_t    newBucketBits;

   // if an iterator had prevented resizing while many elements were added,
   // we might need to double more than once to restore the target ratio.
   for (newBucketBits = mBucketBits+1;
        mElements / NUM_HASHBAG_BUCKETS(newBucketBits) >= 3;
        newBucketBits++
        )
   {
   }

   // allocate the new buckets
   newBucket = new UtlChain[NUM_HASHBAG_BUCKETS(newBucketBits)];

   if (newBucket)
   {
      // save the old buckets until we move the entries out of them
      UtlChain* oldBucket     = mpBucket;
      size_t    numOldBuckets = numberOfBuckets();

      // put in the new buckets
      mBucketBits = newBucketBits;
      mpBucket = newBucket;

      // move all the entries to the new buckets
      size_t old;
      size_t toBeMoved;
      for (old = 0, toBeMoved = mElements;
           old < numOldBuckets && toBeMoved;
           old++
           )
      {
         while(!oldBucket[old].isUnLinked()) // old bucket is not empty yet
         {
            UtlLink* link = static_cast<UtlLink*>(oldBucket[old].head());
            link->detachFromList(&oldBucket[old]);
            insert(link, &mpBucket[bucketNumber(link->hash)]);
            toBeMoved--;
         }
      }

      delete [] oldBucket; // finished with the old empty buckets
   }
   else
   {
      assert(newBucket); // failed to allocate new buckets
   }
}
Пример #3
0
/**
 * Search for the designated object by reference.
 * @return the object if found, otherwise NULL.
 */
UtlContainable* UtlHashBag::findReference(const UtlContainable* object) const
{
   UtlContainable* found = NULL;

   if (object)
   {
      OsLock take(mContainerLock);

      UtlLink*  link = NULL;
      UtlChain* bucket;
      UtlLink* check;

      // walk the buckets
      for (size_t i = 0; link == NULL && i < numberOfBuckets(); i++)
      {
         bucket = &mpBucket[i];

         for (link = NULL, check = static_cast<UtlLink*>(bucket->listHead());
              (   !link                  // not found
               && check                  // not end of list
                 );
              check = check->next()
            )
         {
            if (check->data == object)
            {
               link = check; // found it
            }
         }
      }

      if (link)
      {
         found = link->data;
      }
   }

   return found;
}
Пример #4
0
void UtlHashBag::removeAll()
{
   OsLock take(mContainerLock);

   size_t i;
   size_t toBeRemoved;
   for (i = 0, toBeRemoved = mElements;
        i < numberOfBuckets() && toBeRemoved;
        i++
        ) // for each bucket
   {
      while(!mpBucket[i].isUnLinked()) // bucket is not empty yet
      {
         UtlLink* link = static_cast<UtlLink*>(mpBucket[i].head());
         notifyIteratorsOfRemove(link);
         link->detachFromList(&mpBucket[i]);
         link->release();
         toBeRemoved--;
      }
   }
   mElements = 0;
}
Пример #5
0
size_t UtlHashMap::bucketNumber(unsigned hash) const
{
   /*
    * We only use mBucketBits of the hash to index mpBucket, but we don't want to
    * loose the information in the higher bits of the hash code.  So we 'fold' the 
    * high order bits by XORing them mBucketBits at a time into the bits we'll
    * use until there are no non-zero high order bits left.
    */
   size_t foldedHash;
   size_t highBits;

   size_t lowBitsMask = numberOfBuckets() - 1;
   for ( (foldedHash = hash & lowBitsMask, // get the low bits we want into the folded value
          highBits   = hash                // don't bother masking off the low bits
          );
         (highBits = highBits >> mBucketBits);  // shift out bits already used until zero 
         foldedHash ^= highBits & lowBitsMask // incorporate non-zero
        )
   {
   }
   return foldedHash;
}
Пример #6
0
// Destructor
UtlHashBag::~UtlHashBag()
{
   UtlContainer::acquireIteratorConnectionLock();
   OsLock take(mContainerLock);

   invalidateIterators();

   UtlContainer::releaseIteratorConnectionLock();

   // still holding the mContainerLock
   // walk the buckets
   for (size_t i = 0; i < numberOfBuckets(); i++)
   {
      // empty each bucket and release each UtlPair back to the pool
      while (!mpBucket[i].isUnLinked())
      {
         UtlLink* link = static_cast<UtlLink*>(mpBucket[i].listHead());
         link->detachFromList(&mpBucket[i]);
         link->release();
      }
   }
   delete [] mpBucket;   // free the bucket headers
}