LCOV - code coverage report
Current view: top level - xpcom/ds - nsDeque.h (source / functions) Hit Total Coverage
Test: output.info Lines: 6 11 54.5 %
Date: 2017-07-14 16:53:18 Functions: 4 6 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /**
       8             :  * MODULE NOTES:
       9             :  *
      10             :  * The Deque is a very small, very efficient container object
      11             :  * than can hold items of type void*, offering the following features:
      12             :  * - Its interface supports pushing, popping, and peeking of items at the back
      13             :  *   or front, and retrieval from any position.
      14             :  * - It can iterate over items via a ForEach method, range-for, or an iterator
      15             :  *   class.
      16             :  * - When full, it can efficiently resize dynamically.
      17             :  *
      18             :  * NOTE: The only bit of trickery here is that this deque is
      19             :  * built upon a ring-buffer. Like all ring buffers, the first
      20             :  * item may not be at index[0]. The mOrigin member determines
      21             :  * where the first child is. This point is quietly hidden from
      22             :  * customers of this class.
      23             :  */
      24             : 
      25             : #ifndef _NSDEQUE
      26             : #define _NSDEQUE
      27             : 
      28             : #include "nscore.h"
      29             : #include "nsDebug.h"
      30             : #include "mozilla/Attributes.h"
      31             : #include "mozilla/fallible.h"
      32             : #include "mozilla/MemoryReporting.h"
      33             : 
      34             : /**
      35             :  * The nsDequeFunctor class is used when you want to create
      36             :  * callbacks between the deque and your generic code.
      37             :  * Use these objects in a call to ForEach(), and as custom deallocators.
      38             :  */
      39           6 : class nsDequeFunctor
      40             : {
      41             : public:
      42             :   virtual void* operator()(void* aObject) = 0;
      43           3 :   virtual ~nsDequeFunctor() {}
      44             : };
      45             : 
      46             : /******************************************************
      47             :  * Here comes the nsDeque class itself...
      48             :  ******************************************************/
      49             : 
      50             : /**
      51             :  * The deque (double-ended queue) class is a common container type,
      52             :  * whose behavior mimics a line in your favorite checkout stand.
      53             :  * Classic CS describes the common behavior of a queue as FIFO.
      54             :  * A deque allows insertion and removal at both ends of
      55             :  * the container.
      56             :  *
      57             :  * The deque stores pointers to items.
      58             :  */
      59             : class nsDeque
      60             : {
      61             :   typedef mozilla::fallible_t fallible_t;
      62             : public:
      63             :   /**
      64             :    * Constructs an empty deque.
      65             :    *
      66             :    * @param   aDeallocator Optional deallocator functor that will be called from
      67             :    *                       Erase() and the destructor on any remaining item.
      68             :    *                       The deallocator is owned by the deque and will be
      69             :    *                       deleted at destruction time.
      70             :    */
      71             :   explicit nsDeque(nsDequeFunctor* aDeallocator = nullptr);
      72             : 
      73             :   /**
      74             :    * Deque destructor. Erases all items, deletes the deallocator.
      75             :    */
      76             :   ~nsDeque();
      77             : 
      78             :   /**
      79             :    * Returns the number of items currently stored in
      80             :    * this deque.
      81             :    *
      82             :    * @return  number of items currently in the deque
      83             :    */
      84          22 :   inline size_t GetSize() const { return mSize; }
      85             : 
      86             :   /**
      87             :    * Appends new member at the end of the deque.
      88             :    *
      89             :    * @param   aItem item to store in deque
      90             :    */
      91           3 :   void Push(void* aItem)
      92             :   {
      93           3 :     if (!Push(aItem, mozilla::fallible)) {
      94           0 :       NS_ABORT_OOM(mSize * sizeof(void*));
      95             :     }
      96           3 :   }
      97             : 
      98             :   /**
      99             :    * Appends new member at the end of the deque.
     100             :    *
     101             :    * @param   aItem item to store in deque
     102             :    * @return  true if succeeded, false if failed to resize deque as needed
     103             :    */
     104             :   MOZ_MUST_USE bool Push(void* aItem, const fallible_t&);
     105             : 
     106             :   /**
     107             :    * Inserts new member at the front of the deque.
     108             :    *
     109             :    * @param   aItem item to store in deque
     110             :    */
     111           0 :   void PushFront(void* aItem)
     112             :   {
     113           0 :     if (!PushFront(aItem, mozilla::fallible)) {
     114           0 :       NS_ABORT_OOM(mSize * sizeof(void*));
     115             :     }
     116           0 :   }
     117             : 
     118             :   /**
     119             :    * Inserts new member at the front of the deque.
     120             :    *
     121             :    * @param   aItem item to store in deque
     122             :    * @return  true if succeeded, false if failed to resize deque as needed
     123             :    */
     124             :   MOZ_MUST_USE bool PushFront(void* aItem, const fallible_t&);
     125             : 
     126             :   /**
     127             :    * Remove and return the last item in the container.
     128             :    *
     129             :    * @return  the item that was the last item in container
     130             :    */
     131             :   void* Pop();
     132             : 
     133             :   /**
     134             :    * Remove and return the first item in the container.
     135             :    *
     136             :    * @return  the item that was first item in container
     137             :    */
     138             :   void* PopFront();
     139             : 
     140             :   /**
     141             :    * Retrieve the last item without removing it.
     142             :    *
     143             :    * @return  the last item in container
     144             :    */
     145             :   void* Peek() const;
     146             : 
     147             :   /**
     148             :    * Retrieve the first item without removing it.
     149             :    *
     150             :    * @return  the first item in container
     151             :    */
     152             :   void* PeekFront() const;
     153             : 
     154             :   /**
     155             :    * Retrieve a member from the deque without removing it.
     156             :    *
     157             :    * @param   index of desired item
     158             :    * @return  item in list, or nullptr if index is outside the deque
     159             :    */
     160             :   void* ObjectAt(size_t aIndex) const;
     161             : 
     162             :   /**
     163             :    * Remove and delete all items from container.
     164             :    * Deletes are handled by the deallocator nsDequeFunctor
     165             :    * which is specified at deque construction.
     166             :    */
     167             :   void Erase();
     168             : 
     169             :   /**
     170             :    * Call this method when you want to iterate through all
     171             :    * items in the container, passing a functor along
     172             :    * to call your code.
     173             :    * If the deque is modified during ForEach, iteration will continue based on
     174             :    * item indices; meaning that front operations may effectively skip over
     175             :    * items or visit some items multiple times.
     176             :    *
     177             :    * @param   aFunctor object to call for each member
     178             :    */
     179             :   void ForEach(nsDequeFunctor& aFunctor) const;
     180             : 
     181             :   // This iterator assumes that the deque itself is const, i.e., it cannot be
     182             :   // modified while the iterator is used.
     183             :   // Also it is a 'const' iterator in that it provides copies of the deque's
     184             :   // elements, and therefore it is not possible to modify the deque's contents
     185             :   // by assigning to a dereference of this iterator.
     186             :   class ConstDequeIterator
     187             :   {
     188             :   public:
     189             :     ConstDequeIterator(const nsDeque& aDeque, size_t aIndex)
     190             :       : mDeque(aDeque)
     191             :       , mIndex(aIndex)
     192             :     {
     193             :     }
     194             :     ConstDequeIterator& operator++()
     195             :     {
     196             :       ++mIndex;
     197             :       return *this;
     198             :     }
     199             :     bool operator==(const ConstDequeIterator& aOther) const
     200             :     {
     201             :       return mIndex == aOther.mIndex;
     202             :     }
     203             :     bool operator!=(const ConstDequeIterator& aOther) const
     204             :     {
     205             :       return mIndex != aOther.mIndex;
     206             :     }
     207             :     void* operator*() const
     208             :     {
     209             :       // Don't allow out-of-deque dereferences.
     210             :       MOZ_RELEASE_ASSERT(mIndex < mDeque.GetSize());
     211             :       return mDeque.ObjectAt(mIndex);
     212             :     }
     213             :   private:
     214             :     const nsDeque& mDeque;
     215             :     size_t mIndex;
     216             :   };
     217             :   // If this deque is const, we can provide ConstDequeIterator's.
     218             :   ConstDequeIterator begin() const
     219             :   {
     220             :     return ConstDequeIterator(*this, 0);
     221             :   }
     222             :   ConstDequeIterator end() const
     223             :   {
     224             :     return ConstDequeIterator(*this, mSize);
     225             :   }
     226             : 
     227             :   // It is a 'const' iterator in that it provides copies of the deque's
     228             :   // elements, and therefore it is not possible to modify the deque's contents
     229             :   // by assigning to a dereference of this iterator.
     230             :   // If the deque is modified in other ways, this iterator will stay at the same
     231             :   // index, and will handle past-the-end comparisons, but not dereferencing.
     232             :   class ConstIterator
     233             :   {
     234             :   public:
     235             :     // Special index for the end iterator, to track the possibly-shifting
     236             :     // deque size.
     237             :     static const size_t EndIteratorIndex = size_t(-1);
     238             : 
     239             :     ConstIterator(const nsDeque& aDeque, size_t aIndex)
     240             :       : mDeque(aDeque)
     241             :       , mIndex(aIndex)
     242             :     {
     243             :     }
     244             :     ConstIterator& operator++()
     245             :     {
     246             :       // End-iterator shouldn't be modified.
     247             :       MOZ_ASSERT(mIndex != EndIteratorIndex);
     248             :       ++mIndex;
     249             :       return *this;
     250             :     }
     251             :     bool operator==(const ConstIterator& aOther) const
     252             :     {
     253             :       return EffectiveIndex() == aOther.EffectiveIndex();
     254             :     }
     255             :     bool operator!=(const ConstIterator& aOther) const
     256             :     {
     257             :       return EffectiveIndex() != aOther.EffectiveIndex();
     258             :     }
     259             :     void* operator*() const
     260             :     {
     261             :       // Don't allow out-of-deque dereferences.
     262             :       MOZ_RELEASE_ASSERT(mIndex < mDeque.GetSize());
     263             :       return mDeque.ObjectAt(mIndex);
     264             :     }
     265             :   private:
     266             :     // 0 <= index < deque.GetSize() inside the deque, deque.GetSize() otherwise.
     267             :     // Only used when comparing indices, not to actually access items.
     268             :     size_t EffectiveIndex() const
     269             :     {
     270             :       return (mIndex < mDeque.GetSize()) ? mIndex : mDeque.GetSize();
     271             :     }
     272             : 
     273             :     const nsDeque& mDeque;
     274             :     size_t mIndex; // May point outside the deque!
     275             :   };
     276             :   // If this deque is *not* const, we provide ConstIterator's that can handle
     277             :   // deque size changes.
     278             :   ConstIterator begin()
     279             :   {
     280             :     return ConstIterator(*this, 0);
     281             :   }
     282             :   ConstIterator end()
     283             :   {
     284             :     return ConstIterator(*this, ConstIterator::EndIteratorIndex);
     285             :   }
     286             : 
     287             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     288             :   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     289             : 
     290             : protected:
     291             :   size_t         mSize;
     292             :   size_t         mCapacity;
     293             :   size_t         mOrigin;
     294             :   nsDequeFunctor* mDeallocator;
     295             :   void*           mBuffer[8];
     296             :   void**          mData;
     297             : 
     298             : private:
     299             : 
     300             :   /**
     301             :    * Copy constructor (deleted)
     302             :    *
     303             :    * @param aOther another deque
     304             :    */
     305             :   nsDeque(const nsDeque& aOther) = delete;
     306             : 
     307             :   /**
     308             :    * Deque assignment operator (deleted)
     309             :    *
     310             :    * @param aOther another deque
     311             :    * @return *this
     312             :    */
     313             :   nsDeque& operator=(const nsDeque& aOther) = delete;
     314             : 
     315             :   bool GrowCapacity();
     316             :   void SetDeallocator(nsDequeFunctor* aDeallocator);
     317             : 
     318             :   /**
     319             :    * Remove all items from container without destroying them.
     320             :    */
     321             :   void Empty();
     322             : };
     323             : #endif

Generated by: LCOV version 1.13