LCOV - code coverage report
Current view: top level - gfx/2d - IterableArena.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 39 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #ifndef MOZILLA_GFX_ITERABLEARENA_H_
       7             : #define MOZILLA_GFX_ITERABLEARENA_H_
       8             : 
       9             : #include "mozilla/Move.h"
      10             : #include "mozilla/Assertions.h"
      11             : #include "mozilla/gfx/Logging.h"
      12             : 
      13             : #include <string.h>
      14             : #include <vector>
      15             : #include <stdint.h>
      16             : #include <stdio.h>
      17             : 
      18             : namespace mozilla {
      19             : namespace gfx {
      20             : 
      21             : /// A simple pool allocator for plain data structures.
      22             : ///
      23             : /// Beware that the pool will not attempt to run the destructors. It is the
      24             : /// responsibility of the user of this class to either use objects with no
      25             : /// destructor or to manually call the allocated objects destructors.
      26             : /// If the pool is growable, its allocated objects must be safely moveable in
      27             : /// in memory (through memcpy).
      28             : class IterableArena {
      29             : protected:
      30             :   struct Header
      31             :   {
      32             :     size_t mBlocSize;
      33             :   };
      34             : public:
      35             :   enum ArenaType {
      36             :     FIXED_SIZE,
      37             :     GROWABLE
      38             :   };
      39             : 
      40           0 :   IterableArena(ArenaType aType, size_t aStorageSize)
      41           0 :   : mSize(aStorageSize)
      42             :   , mCursor(0)
      43           0 :   , mIsGrowable(aType == GROWABLE)
      44             :   {
      45           0 :     if (mSize == 0) {
      46           0 :       mSize = 128;
      47             :     }
      48             : 
      49           0 :     mStorage = (uint8_t*)malloc(mSize);
      50           0 :     if (mStorage == nullptr) {
      51           0 :       gfxCriticalError() << "Not enough Memory allocate a memory pool of size " << aStorageSize;
      52           0 :       MOZ_CRASH("GFX: Out of memory IterableArena");
      53             :     }
      54           0 :   }
      55             : 
      56           0 :   ~IterableArena()
      57           0 :   {
      58           0 :     free(mStorage);
      59           0 :   }
      60             : 
      61             :   /// Constructs a new item in the pool and returns a positive offset in case of
      62             :   /// success.
      63             :   ///
      64             :   /// The offset never changes even if the storage is reallocated, so users
      65             :   /// of this class should prefer storing offsets rather than direct pointers
      66             :   /// to the allocated objects.
      67             :   /// Alloc can cause the storage to be reallocated if the pool was initialized
      68             :   /// with IterableArena::GROWABLE.
      69             :   /// If for any reason the pool fails to allocate enough space for the new item
      70             :   /// Alloc returns a negative offset and the object's constructor is not called.
      71             :   template<typename T, typename... Args>
      72             :   ptrdiff_t
      73             :   Alloc(Args&&... aArgs)
      74             :   {
      75             :     void* storage = nullptr;
      76             :     auto offset = AllocRaw(sizeof(T), &storage);
      77             :     if (offset < 0) {
      78             :       return offset;
      79             :     }
      80             :     new (storage) T(Forward<Args>(aArgs)...);
      81             :     return offset;
      82             :   }
      83             : 
      84             :   ptrdiff_t AllocRaw(size_t aSize, void** aOutPtr = nullptr)
      85             :   {
      86             :     const size_t blocSize = AlignedSize(sizeof(Header) + aSize);
      87             : 
      88             :     if (AlignedSize(mCursor + blocSize) > mSize) {
      89             :       if (!mIsGrowable) {
      90             :         return -1;
      91             :       }
      92             : 
      93             :       size_t newSize = mSize * 2;
      94             :       while (AlignedSize(mCursor + blocSize) > newSize) {
      95             :         newSize *= 2;
      96             :       }
      97             : 
      98             :       uint8_t* newStorage = (uint8_t*)realloc(mStorage, newSize);
      99             :       if (!newStorage) {
     100             :          gfxCriticalError() << "Not enough Memory to grow the memory pool, size: " << newSize;
     101             :         return -1;
     102             :       }
     103             : 
     104             :       mStorage = newStorage;
     105             :       mSize = newSize;
     106             :     }
     107             :     ptrdiff_t offset = mCursor;
     108             :     GetHeader(offset)->mBlocSize = blocSize;
     109             :     mCursor += blocSize;
     110             :     if (aOutPtr) {
     111             :         *aOutPtr = GetStorage(offset);
     112             :     }
     113             :     return offset;
     114             :   }
     115             : 
     116             :   /// Get access to an allocated item at a given offset (only use offsets returned
     117             :   /// by Alloc or AllocRaw).
     118             :   ///
     119             :   /// If the pool is growable, the returned pointer is only valid temporarily. The
     120             :   /// underlying storage can be reallocated in Alloc or AllocRaw, so do not keep
     121             :   /// these pointers around and store the offset instead.
     122           0 :   void* GetStorage(ptrdiff_t offset = 0)
     123             :   {
     124           0 :     MOZ_ASSERT(offset >= 0);
     125           0 :     MOZ_ASSERT(offset < mCursor);
     126           0 :     return offset >= 0 ? mStorage + offset + sizeof(Header) : nullptr;
     127             :   }
     128             : 
     129             :   /// Clears the storage without running any destructor and without deallocating it.
     130           0 :   void Clear()
     131             :   {
     132           0 :     mCursor = 0;
     133           0 :   }
     134             : 
     135             :   /// Iterate over the elements allocated in this pool.
     136             :   ///
     137             :   /// Takes a lambda or function object accepting a void* as parameter.
     138             :   template<typename Func>
     139           0 :   void ForEach(Func cb)
     140             :   {
     141           0 :     Iterator it;
     142           0 :     while (void* ptr = it.Next(this)) {
     143           0 :       cb(ptr);
     144             :     }
     145           0 :   }
     146             : 
     147             :   /// A simple iterator over an arena.
     148             :   class Iterator {
     149             :   public:
     150           0 :     Iterator()
     151           0 :     : mCursor(0)
     152           0 :     {}
     153             : 
     154           0 :     void* Next(IterableArena* aArena)
     155             :     {
     156           0 :       if (mCursor >= aArena->mCursor) {
     157           0 :         return nullptr;
     158             :       }
     159           0 :       void* result = aArena->GetStorage(mCursor);
     160           0 :       const size_t blocSize = aArena->GetHeader(mCursor)->mBlocSize;
     161           0 :       MOZ_ASSERT(blocSize != 0);
     162           0 :       mCursor += blocSize;
     163           0 :       return result;
     164             :     }
     165             : 
     166             :   private:
     167             :     ptrdiff_t mCursor;
     168             :   };
     169             : 
     170             : protected:
     171           0 :   Header* GetHeader(ptrdiff_t offset)
     172             :   {
     173           0 :     return (Header*) (mStorage + offset);
     174             :   }
     175             : 
     176             :   size_t AlignedSize(size_t aSize) const
     177             :   {
     178             :     const size_t alignment = sizeof(uintptr_t);
     179             :     return aSize + (alignment - (aSize % alignment)) % alignment;
     180             :   }
     181             : 
     182             :   uint8_t* mStorage;
     183             :   uint32_t mSize;
     184             :   ptrdiff_t mCursor;
     185             :   bool mIsGrowable;
     186             : 
     187             :   friend class Iterator;
     188             : };
     189             : 
     190             : } // namespace
     191             : } // namespace
     192             : 
     193             : #endif

Generated by: LCOV version 1.13