LCOV - code coverage report
Current view: top level - elsa/storage/memory_resource - CacheResource.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 57 72 79.2 %
Date: 2024-05-16 04:22:26 Functions: 7 8 87.5 %

          Line data    Source code
       1             : #include "CacheResource.h"
       2             : 
       3             : namespace elsa::mr
       4             : {
       5             :     void CacheResource::releaseCache()
       6          13 :     {
       7       10058 :         for (auto& entry : _cache) {
       8       10058 :             _upstream->deallocate(entry.ptr, entry.size, entry.alignment);
       9       10058 :         }
      10          13 :         _cache.clear();
      11          13 :         _sizeToCacheElement.clear();
      12          13 :     }
      13             : 
      14             :     CacheResource::CacheResource(MemoryResource upstream, const CacheResourceConfig& config)
      15             :         : _upstream{upstream}, _config{config}
      16          10 :     {
      17          10 :         if (config.maxCachedCount != std::numeric_limits<size_t>::max()) {
      18             :             // The + 1 is necessary, because elements are evicted after inserting,
      19             :             // so the cache is briefly larger than the maxCachedCount.
      20           9 :             _sizeToCacheElement.reserve(config.maxCachedCount + 1);
      21           9 :         }
      22          10 :     }
      23             : 
      24             :     CacheResource::~CacheResource()
      25          10 :     {
      26          10 :         releaseCache();
      27          10 :     }
      28             : 
      29             :     MemoryResource CacheResource::make(MemoryResource upstream, const CacheResourceConfig& config)
      30          10 :     {
      31          10 :         return std::shared_ptr<MemResInterface>(new CacheResource(upstream, config),
      32          10 :                                                 [](CacheResource* p) { delete p; });
      33          10 :     }
      34             : 
      35             :     void* CacheResource::allocate(size_t size, size_t alignment)
      36       30139 :     {
      37       30139 :         auto mapIt = _sizeToCacheElement.find({size, alignment});
      38       30139 :         if (mapIt == _sizeToCacheElement.end()) {
      39       29584 :             try {
      40       29584 :                 return _upstream->allocate(size, alignment);
      41       29584 :             } catch (std::bad_alloc& e) {
      42           3 :                 releaseCache();
      43             :                 // try again after hopefully returning enough memory to the upstream allocator
      44           3 :                 return _upstream->allocate(size, alignment);
      45           3 :             }
      46         555 :         } else {
      47         555 :             void* ptr = mapIt->second->ptr;
      48         555 :             _cachedSize -= mapIt->second->size;
      49         555 :             _cache.erase(mapIt->second);
      50         555 :             _sizeToCacheElement.erase(mapIt);
      51         555 :             return ptr;
      52         555 :         }
      53       30139 :     }
      54             : 
      55             :     void CacheResource::deallocate(void* ptr, size_t size, size_t alignment) noexcept
      56       30136 :     {
      57       30136 :         if (size > _config.maxCacheSize) {
      58           0 :             _upstream->deallocate(ptr, size, alignment);
      59           0 :             return;
      60           0 :         }
      61             : 
      62       30136 :         if (!ptr) {
      63           0 :             return;
      64           0 :         }
      65             : 
      66       30136 :         try {
      67       30136 :             _cache.push_back({ptr, size, alignment});
      68       30136 :         } catch (std::bad_alloc& e) {
      69           0 :             _upstream->deallocate(ptr, size, alignment);
      70           0 :             return;
      71           0 :         }
      72             : 
      73       30136 :         try {
      74       30136 :             _sizeToCacheElement.insert({{size, alignment}, --_cache.end()});
      75       30136 :         } catch (std::bad_alloc& e) {
      76           0 :             _cache.pop_back();
      77           0 :             _upstream->deallocate(ptr, size, alignment);
      78           0 :             return;
      79           0 :         }
      80             : 
      81       30136 :         _cachedSize += size;
      82       49659 :         while (_cache.size() > _config.maxCachedCount || _cachedSize > _config.maxCacheSize) {
      83       19523 :             cache_resource::CacheElement& poppedElement = _cache.front();
      84       19523 :             auto poppedIt = _sizeToCacheElement.find({poppedElement.size, poppedElement.alignment});
      85             :             // If this throws, internal invariants are violated (the element is not in the map).
      86             :             // This would be a serious bug, thus termination seems justified.
      87       35255 :             while (&*poppedIt->second != &poppedElement)
      88       15732 :                 poppedIt++;
      89       19523 :             _sizeToCacheElement.erase(poppedIt);
      90       19523 :             _cachedSize -= poppedElement.size;
      91       19523 :             _upstream->deallocate(poppedElement.ptr, poppedElement.size, poppedElement.alignment);
      92       19523 :             _cache.pop_front();
      93       19523 :         }
      94       30136 :     }
      95             : 
      96             :     bool CacheResource::tryResize(void* ptr, size_t size, size_t alignment, size_t newSize) noexcept
      97           0 :     {
      98           0 :         return _upstream->tryResize(ptr, size, alignment, newSize);
      99           0 :     }
     100             : } // namespace elsa::mr

Generated by: LCOV version 1.14