Beispiel #1
0
UtlContainable* UtlHashBag::remove(const UtlContainable* object)
{
   UtlContainable* removed = NULL;

   if (object)
   {
      OsLock take(mContainerLock);

      UtlLink*  link;
      UtlChain* bucket;

      if ( lookup(object, bucket, link) )
      {
         removed = link->data;

         notifyIteratorsOfRemove(link);

         link->detachFromList(bucket);
         removed = link->data;
         link->release();

         mElements--;
      }
   }

   return removed;
}
Beispiel #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
   }
}
Beispiel #3
0
/**
 * Removed the designated object by reference
 * (as opposed to searching for an equality match).
 *
 * @return the object if successful, otherwise null
 */
UtlContainable* UtlHashBag::removeReference(const UtlContainable* object)
{
   UtlContainable* removed = NULL;

   if (object)
   {
      size_t   keyHash = object->hash();

      OsLock take(mContainerLock);

      UtlLink*  link;
      UtlChain* bucket;
      UtlLink* check;

      bucket = &mpBucket[bucketNumber(keyHash)];
      for (link = NULL, check = static_cast<UtlLink*>(bucket->listHead());
           (   !link                  // not found
            && check                  // not end of list
            && check->hash <= keyHash // hash list is ordered, so if > then it's not in the list
            );
           check = check->next()
           )
      {
         if (check->data == object)
         {
            link = check; // found it
         }
      }

      if (link)
      {
         notifyIteratorsOfRemove(link);

         link->detachFromList(bucket);
         removed = link->data;
         link->release();

         mElements--;
      }
   }

   return removed;
}
Beispiel #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;
}
Beispiel #5
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
}