Line data Source code
1 : #pragma once 2 : 3 : #include "MemoryResource.h" 4 : #include <unordered_map> 5 : #include <list> 6 : #include <memory> 7 : 8 : namespace elsa::mr 9 : { 10 : namespace region_resource 11 : { 12 : static constexpr size_t BLOCK_GRANULARITY = 256; 13 : } 14 : 15 : class RegionResource; 16 : 17 : class RegionResourceConfig 18 : { 19 : private: 20 : friend class RegionResource; 21 : 22 : size_t regionSize; 23 : bool isAdaptive; 24 : 25 : constexpr RegionResourceConfig(size_t regionSize, bool adaptive) 26 : : regionSize{regionSize}, isAdaptive{adaptive} 27 6 : { 28 6 : } 29 : 30 : public: 31 : /// @brief Default configuration for a region resource with (hopefully) sensible defaults. 32 : /// @return Default configuration for a region resource. 33 : static constexpr RegionResourceConfig defaultConfig() 34 6 : { 35 6 : return RegionResourceConfig(static_cast<size_t>(1) << 31, true); 36 6 : } 37 : 38 : constexpr RegionResourceConfig& setRegionSize(size_t size) 39 0 : { 40 0 : regionSize = size; 41 0 : return *this; 42 0 : } 43 : 44 : constexpr RegionResourceConfig& setAdaptive(bool adaptive) 45 0 : { 46 0 : isAdaptive = adaptive; 47 0 : return *this; 48 0 : } 49 : }; 50 : 51 : /// @brief Memory resource for the ContiguousStorage class. 52 : /// This is the most specialized and fastest memory resource, if used appropriately. 53 : /// As a region resource, memory freed to this resource can only be reused once ALL memory 54 : /// allocated from it is freed. Hence, this memory resource is well suited for a sawtooth 55 : /// allocation pattern, first doing all allocations, then freeing everything, then potentially 56 : /// repeating. 57 : /// Advantages: Extremely fast, allocation/deallocations perform only a few simple additions. 58 : /// Disadvantages: If used inappropriately, huge memory overhead. Also, move assignment 59 : /// between containers with different memory resources is more costly. Use it only if you are 60 : /// sure that memory allocations are your bottle-neck! If your algorithm works on huge data, 61 : /// allocations are probably not worth optimizing. 62 : class RegionResource : public MemResInterface 63 : { 64 : private: 65 : MemoryResource _upstream; 66 : 67 : RegionResourceConfig _config; 68 : 69 : void* _basePtr; 70 : 71 : void* _endPtr; 72 : 73 : void* _bumpPtr; 74 : 75 : size_t _allocatedSize; 76 : 77 : public: 78 : RegionResource(const RegionResource& other) = delete; 79 : 80 : RegionResource& operator=(const RegionResource& other) = delete; 81 : 82 : RegionResource(RegionResource&& other) noexcept = delete; 83 : 84 : RegionResource& operator=(RegionResource&& other) noexcept = delete; 85 : 86 : protected: 87 : RegionResource(const MemoryResource& upstream, 88 : const RegionResourceConfig& config = RegionResourceConfig::defaultConfig()); 89 : 90 : ~RegionResource(); 91 : 92 : public: 93 : static MemoryResource 94 : make(const MemoryResource& upstream = globalResource(), 95 : const RegionResourceConfig& config = RegionResourceConfig::defaultConfig()); 96 : 97 : void* allocate(size_t size, size_t alignment) override; 98 : 99 : void deallocate(void* ptr, size_t size, size_t alignment) noexcept override; 100 : 101 : bool tryResize(void* ptr, size_t size, size_t alignment, size_t newSize) noexcept override; 102 : }; 103 : } // namespace elsa::mr