예제 #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;
}
예제 #2
0
// Return the list position of the designated object.
ssize_t UtlSList::index(const UtlContainable* containableToMatch) const
{
    ssize_t matchedIndex = UTL_NOT_FOUND;
    ssize_t currentIndex;
    UtlLink* listNode;
    UtlContainable* visitNode = NULL;

    OsLock take(mContainerLock);

    LIST_SANITY_CHECK;
    for(listNode = head(), currentIndex = 0;
        matchedIndex == UTL_NOT_FOUND && listNode;
        listNode = listNode->next()
        )
    {
        visitNode = (UtlContainable*) listNode->data;
        if(visitNode && visitNode->compareTo(containableToMatch) == 0)
        {
           matchedIndex = currentIndex;
        }
        else
        {
           currentIndex++;
        }
    }
    LIST_SANITY_CHECK;

    return matchedIndex;
}
예제 #3
0
// Find the next like-instance of the designated object .
UtlContainable* UtlSListIterator::findNext(const UtlContainable* containableToMatch) 
{
   UtlContainable* match = NULL;

   UtlContainer::acquireIteratorConnectionLock();
   OsLock takeContainer(mContainerRefLock);
   UtlSList* myList = static_cast<UtlSList*>(mpMyContainer);
   
   OsLock take(myList->mContainerLock);
   UtlContainer::releaseIteratorConnectionLock();

   // advance the iterator
   UtlLink* nextLink = (mpCurrentNode == NULL
                        ? myList->head()
                        : mpCurrentNode->next()
                        );

   // search for the next match forward
   while (nextLink && !match)
   {
      UtlContainable *candidate = (UtlContainable*)nextLink->data;
      if (candidate && candidate->compareTo(containableToMatch) == 0)
      {
         mpCurrentNode = nextLink;
         match = candidate;
      }
      else
      {
         nextLink = nextLink->next();
      }
   }
   
   return match;
}
예제 #4
0
// Return the first UtlLink node to find.
UtlLink* UtlSortedList::findNode(UtlLink* start, MatchType match, const UtlContainable* obj) const
{
   UtlLink*        listNode;
   UtlLink*        foundNode;
   UtlContainable* listElement;
   int             comparison = 0;
   
   // the caller already holds the mContainerLock

   for (listNode = start, foundNode = NULL;
        !foundNode && listNode;
        listNode = listNode->next()
        )
   {
      listElement = (UtlContainable*)listNode->data;
      if (listElement)
      {
         // we can't use the hash as a shortcut here because we need the order too
         comparison = listElement->compareTo(obj);
         if ( comparison >= 0 )
         {
            foundNode = listNode;
         }
      }
   }

   if (foundNode && match == EXACTLY && comparison != 0) // match not exact
   {
      foundNode = NULL; 
   }
   return foundNode;
}
예제 #5
0
// Find the first occurrence of the designated object by equality.
UtlContainable* UtlSList::find(const UtlContainable* containableToMatch) const
{
   UtlLink* listNode;
   UtlContainable* matchElement = NULL;
   UtlContainable* visitNode;

   unsigned targetHash = containableToMatch->hash();

   OsLock take(mContainerLock);

   LIST_SANITY_CHECK;
   for(listNode = head()->findNextHash(targetHash);
       listNode &&  matchElement == NULL;
       listNode = listNode->next()->findNextHash(targetHash)
       )
   {
      visitNode = (UtlContainable*) listNode->data;
      if(visitNode && visitNode->compareTo(containableToMatch) == 0)
      {
         matchElement = visitNode;
      }
   }
   LIST_SANITY_CHECK;

   return(matchElement);
}
예제 #6
0
// Remove the designated object by equality.
UtlContainable* UtlSList::remove(const UtlContainable* object)
{
   UtlLink* listNode;
   UtlLink* found;
   UtlContainable* foundObject = NULL;

   OsLock take(mContainerLock);

   LIST_SANITY_CHECK;
   for (listNode = head(), found = NULL; listNode && !found; listNode = listNode->next())
   {
      UtlContainable* visitNode = (UtlContainable*) listNode->data;
      if(visitNode && visitNode->compareTo(object) == 0)
      {
         found = listNode;
      }
   }

   if (found)
   {
      foundObject = (UtlContainable*)found->data;
      removeLink(found);
   }
   LIST_SANITY_CHECK;

   return foundObject;
}
예제 #7
0
void UtlHashBag::notifyIteratorsOfRemove(const UtlLink* link)
{
   UtlLink* listNode;
   UtlHashBagIterator* foundIterator;

   for (listNode = mIteratorList.head(); listNode; listNode = listNode->next())
   {
      foundIterator = (UtlHashBagIterator*)listNode->data;
      foundIterator->removing(link);
   }
}
예제 #8
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
   }
}
예제 #9
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;
}
예제 #10
0
// Return the number of occurrences of the designated object.
size_t UtlSList::occurrencesOf(const UtlContainable* containableToMatch) const
{
   int count = 0;
   UtlLink* listNode;
   UtlContainable* visitNode = NULL;

   OsLock take(mContainerLock);

   LIST_SANITY_CHECK;
   for(listNode = head(); listNode; listNode = listNode->next())
   {
      visitNode = (UtlContainable*)listNode->data;
      if(visitNode && visitNode->compareTo(containableToMatch) == 0)
      {
         count++;
      }
   }
   LIST_SANITY_CHECK;

   return(count);
}
예제 #11
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;
}
예제 #12
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;
}
예제 #13
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
}
예제 #14
0
// Return the number of occurrences of the designated object.
size_t UtlSortedList::occurrencesOf(const UtlContainable* containableToMatch) const 
{
   int count = 0;
   UtlLink* listNode;
   UtlContainable* visitNode = NULL;
   int             comparison;

   OsLock take(const_cast<OsBSem&>(mContainerLock));
   
   for (listNode = head(), comparison = 0;
        comparison <= 0 && listNode;
        listNode = listNode->next()
        )
   {
      visitNode = (UtlContainable*)listNode->data;
      if(visitNode && visitNode->compareTo(containableToMatch) == 0)
      {
         count++;
      }
   }

   return(count);
}
예제 #15
0
// Return the list position of the designated object.
size_t UtlSortedList::index(const UtlContainable* obj) const 
{
   size_t          index = UTL_NOT_FOUND;
   size_t          thisIndex;
   UtlLink*        listNode;
   unsigned        keyHash = obj->hash();
   
   OsLock take(const_cast<OsBSem&>(mContainerLock));
   
   for (listNode = head(), thisIndex = 0;
        listNode && index == UTL_NOT_FOUND;
        listNode = listNode->next(), thisIndex++)
   {
      if (   listNode->data                      // there is an object (for safety sake)
          && listNode->hash == keyHash           // quick test for possible equality
          && listNode->data->compareTo(obj) == 0 // real (but slower) test for equality
          )
      {
         index = thisIndex;
      }
   }
    
   return index;
}
예제 #16
0
// Insert at the designated position.
UtlContainable* UtlSList::insertAt(size_t N, UtlContainable* obj)
{
   // :NOTE: this method is deliberately not the same as g_list_insert in that
   //        the glib routine will accept a value of N > the length of the list
   //        but this routine treats that as an error.
   UtlContainable* inserted = NULL;

   OsLock take(mContainerLock);

   LIST_SANITY_CHECK;
   size_t n;
   UtlLink* link;
   for (n = 0, link = head(); link && n < N; link = link->next(), n++)
   {
   }
   if (n == N)
   {
      UtlLink::listBefore(this, link, obj);
      inserted = obj;
   }
   LIST_SANITY_CHECK;

   return inserted;
}