LCOV - code coverage report
Current view: top level - source/lib/allocators - pool.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 19 0.0 %
Date: 2023-01-19 00:18:29 Functions: 0 54 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  *
       3             :  * Permission is hereby granted, free of charge, to any person obtaining
       4             :  * a copy of this software and associated documentation files (the
       5             :  * "Software"), to deal in the Software without restriction, including
       6             :  * without limitation the rights to use, copy, modify, merge, publish,
       7             :  * distribute, sublicense, and/or sell copies of the Software, and to
       8             :  * permit persons to whom the Software is furnished to do so, subject to
       9             :  * the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included
      12             :  * in all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      15             :  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      16             :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      17             :  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      18             :  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      19             :  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      20             :  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      21             :  */
      22             : 
      23             : /*
      24             :  * pool allocator (fixed-size blocks, freelist).
      25             :  */
      26             : 
      27             : #ifndef INCLUDED_ALLOCATORS_POOL
      28             : #define INCLUDED_ALLOCATORS_POOL
      29             : 
      30             : #include "lib/bits.h" // ROUND_UP
      31             : #include "lib/allocators/allocator_policies.h"
      32             : 
      33             : namespace Allocators {
      34             : 
      35             : /**
      36             :  * allocator design parameters:
      37             :  * - O(1) allocation and deallocation;
      38             :  * - fixed-size objects;
      39             :  * - support for deallocating all objects;
      40             :  * - consecutive allocations are back-to-back;
      41             :  * - objects are aligned to the pointer size.
      42             :  **/
      43             : template<typename T, class Storage = Storage_Fixed<> >
      44           0 : class Pool
      45             : {
      46             :     NONCOPYABLE(Pool);
      47             : public:
      48             :     // (must round up because freelist stores pointers inside objects)
      49             :     static const size_t objectSize = ROUND_UP(sizeof(T), sizeof(intptr_t));
      50             : 
      51           0 :     Pool(size_t maxObjects)
      52           0 :         : storage(maxObjects*objectSize)
      53             :     {
      54           0 :         DeallocateAll();
      55           0 :     }
      56             : 
      57           0 :     size_t RemainingObjects()
      58             :     {
      59           0 :         return (storage.MaxCapacity() - end) / objectSize;
      60             :     }
      61             : 
      62           0 :     T* Allocate()
      63             :     {
      64           0 :         void* p = mem_freelist_Detach(freelist);
      65           0 :         if(p)
      66             :         {
      67           0 :             ASSERT(Contains((uintptr_t)p));
      68           0 :             return (T*)p;
      69             :         }
      70             : 
      71           0 :         return (T*)StorageAppend(storage, end, objectSize);
      72             :     }
      73             : 
      74             :     void Deallocate(T* p)
      75             :     {
      76             :         ASSERT(Contains((uintptr_t)p));
      77             :         mem_freelist_AddToFront(freelist, p);
      78             :     }
      79             : 
      80           0 :     void DeallocateAll()
      81             :     {
      82           0 :         freelist = mem_freelist_Sentinel();
      83           0 :         end = 0;
      84           0 :     }
      85             : 
      86             :     // @return whether the address lies within the previously allocated range.
      87           0 :     bool Contains(uintptr_t address) const
      88             :     {
      89           0 :         return (address - storage.Address()) < end;
      90             :     }
      91             : 
      92             : private:
      93             :     Storage storage;
      94             :     size_t end;
      95             :     void* freelist;
      96             : };
      97             : 
      98             : void TestPool();
      99             : 
     100             : }   // namespace Allocators
     101             : 
     102             : 
     103             : #include "lib/allocators/dynarray.h"
     104             : 
     105             : /**
     106             :  * allocator design parameters:
     107             :  * - O(1) alloc and free;
     108             :  * - either fixed- or variable-sized blocks;
     109             :  * - doesn't preallocate the entire pool;
     110             :  * - returns sequential addresses.
     111             :  *
     112             :  * opaque! do not read/write any fields!
     113             :  **/
     114             : struct Pool
     115             : {
     116             :     DynArray da;
     117             : 
     118             :     /**
     119             :      * size of elements. = 0 if pool set up for variable-sized
     120             :      * elements, otherwise rounded up to pool alignment.
     121             :      **/
     122             :     size_t el_size;
     123             : 
     124             :     /**
     125             :      * pointer to freelist (opaque); see freelist_*.
     126             :      * never used (remains 0) if elements are of variable size.
     127             :      **/
     128             :     void* freelist;
     129             : };
     130             : 
     131             : /**
     132             :  * pass as pool_create's \<el_size\> param to indicate variable-sized allocs
     133             :  * are required (see below).
     134             :  **/
     135             : const size_t POOL_VARIABLE_ALLOCS = ~(size_t)0u;
     136             : 
     137             : /**
     138             :  * Ready Pool for use.
     139             :  *
     140             :  * @param p Pool*
     141             :  * @param max_size Max size [bytes] of the Pool; this much
     142             :  * (rounded up to next page multiple) virtual address space is reserved.
     143             :  * no virtual memory is actually committed until calls to pool_alloc.
     144             :  * @param el_size Number of bytes that will be returned by each
     145             :  * pool_alloc (whose size parameter is then ignored). Can be 0 to
     146             :  * allow variable-sized allocations, but pool_free is then unusable.
     147             :  * @return Status
     148             :  **/
     149             : Status pool_create(Pool* p, size_t max_size, size_t el_size);
     150             : 
     151             : /**
     152             :  * free all memory (address space + physical) that constitutes the
     153             :  * given Pool.
     154             :  *
     155             :  * future alloc and free calls on this pool will fail.
     156             :  * continued use of the allocated memory (*) is
     157             :  * impossible because it is marked not-present via MMU.
     158             :  * (* no matter if in freelist or unused or "allocated" to user)
     159             :  *
     160             :  * @param p Pool*
     161             :  * @return Status.
     162             :  **/
     163             : Status pool_destroy(Pool* p);
     164             : 
     165             : /**
     166             :  * indicate whether a pointer was allocated from the given pool.
     167             :  *
     168             :  * this is useful for callers that use several types of allocators.
     169             :  *
     170             :  * @param p Pool*
     171             :  * @param el
     172             :  * @return bool.
     173             :  **/
     174             : bool pool_contains(const Pool* p, void* el);
     175             : 
     176             : /**
     177             :  * Dole out memory from the pool.
     178             :  * exhausts the freelist before returning new entries to improve locality.
     179             :  *
     180             :  * @param p Pool*
     181             :  * @param size bytes to allocate; ignored if pool_create's el_size was not 0.
     182             :  * @return allocated memory, or 0 if the Pool would have to be expanded and
     183             :  * there isn't enough memory to do so.
     184             :  **/
     185             : void* pool_alloc(Pool* p, size_t size);
     186             : 
     187             : /**
     188             :  * Make a fixed-size element available for reuse in the given Pool.
     189             :  *
     190             :  * this is not allowed if the Pool was created for variable-size elements.
     191             :  * rationale: avoids having to pass el_size here and compare with size when
     192             :  * allocating; also prevents fragmentation and leaking memory.
     193             :  *
     194             :  * @param p Pool*
     195             :  * @param el Element returned by pool_alloc.
     196             :  **/
     197             : void pool_free(Pool* p, void* el);
     198             : 
     199             : /**
     200             :  * "free" all user allocations that ensued from the given Pool.
     201             :  *
     202             :  * this resets it as if freshly pool_create-d, but doesn't release the
     203             :  * underlying reserved virtual memory.
     204             :  *
     205             :  * @param p Pool*
     206             :  **/
     207             : void pool_free_all(Pool* p);
     208             : 
     209             : /**
     210             :  * Return the number of bytes committed in the pool's backing array.
     211             :  *
     212             :  * This is roughly the number of bytes allocated in this pool plus the
     213             :  * unused freelist entries.
     214             :  *
     215             :  * @param p Pool*
     216             :  * @return number of bytes
     217             :  **/
     218             : size_t pool_committed(Pool* p);
     219             : 
     220             : #endif  // #ifndef INCLUDED_ALLOCATORS_POOL

Generated by: LCOV version 1.13