LCOV - code coverage report
Current view: top level - Src/Utils - SpBufferDataView.hpp (source / functions) Hit Total Coverage
Test: Coverage example Lines: 63 68 92.6 %
Date: 2021-12-02 17:21:05 Functions: 14 14 100.0 %

          Line data    Source code
       1             : ///////////////////////////////////////////////////////////////////////////
       2             : // Spetabaru - Berenger Bramas MPCDF - 2017
       3             : // Under LGPL Licence, please you must read the LICENCE file.
       4             : ///////////////////////////////////////////////////////////////////////////
       5             : #ifndef SPBUFFERDATAVIEW_HPP
       6             : #define SPBUFFERDATAVIEW_HPP
       7             : 
       8             : #include <atomic>
       9             : 
      10             : #include "SpAbstractBufferManager.hpp"
      11             : 
      12             : template <class TargetType>
      13             : class SpDataBufferCore{
      14             :     SpAbstractBufferManager<TargetType>* bufferManager;
      15             : 
      16             :     std::atomic<bool> underUsage;
      17             :     std::atomic<int> dataUseLimitCounter;
      18             :     std::atomic<TargetType*> dataPtr;
      19             :     std::atomic<int> dataUseCounter;
      20             : 
      21             :     std::atomic<int> nbOfPossibleDeleter;
      22             : 
      23         208 :     bool freeDataIfPossible(){
      24         208 :         if(underUsage == false && dataUseLimitCounter == dataUseCounter){
      25         103 :             TargetType* todeleteDataPtr = dataPtr;
      26         103 :             TargetType* nullDataptr = nullptr;
      27         103 :             if(todeleteDataPtr != nullptr && dataPtr.compare_exchange_strong(todeleteDataPtr, nullDataptr) == true){
      28         103 :                 assert(nbOfPossibleDeleter >= 1);
      29         103 :                 while(nbOfPossibleDeleter != 1);
      30         103 :                 if(bufferManager){
      31         102 :                     bufferManager->releaseABuffer(todeleteDataPtr);
      32             :                 }
      33             :                 else{
      34           1 :                     delete todeleteDataPtr;
      35             :                 }
      36         103 :                 delete this;
      37         103 :                 return true;
      38             :             }
      39             :             else{
      40           0 :                 assert(todeleteDataPtr == nullptr);
      41             :             }
      42             :         }
      43         105 :         return false;
      44             :     }
      45             : 
      46         103 :     ~SpDataBufferCore(){
      47         103 :     }
      48             : 
      49             : public:
      50         103 :     explicit SpDataBufferCore(SpAbstractBufferManager<TargetType>* inBufferManager = nullptr)
      51         103 :         : bufferManager(inBufferManager), underUsage(true), dataUseLimitCounter(0), dataPtr(nullptr), dataUseCounter(0), nbOfPossibleDeleter(0){
      52         103 :     }
      53             : 
      54             :     SpDataBufferCore(const SpDataBufferCore&) = delete;
      55             :     SpDataBufferCore(SpDataBufferCore&&) = delete;
      56             :     SpDataBufferCore& operator=(const SpDataBufferCore&) = delete;
      57             :     SpDataBufferCore& operator=(SpDataBufferCore&&) = delete;
      58             : 
      59         105 :     void useData(){
      60             :         // Do nothing
      61         105 :         assert(dataUseCounter < dataUseLimitCounter);
      62         105 :     }
      63             : 
      64         105 :     TargetType* getData(){
      65         105 :         if(dataPtr == nullptr){
      66         103 :             TargetType* newDataPtr = (bufferManager ? bufferManager->getABuffer() : new TargetType());
      67         103 :             TargetType* nullDataptr = nullptr;
      68         103 :             if(dataPtr.compare_exchange_strong(nullDataptr, newDataPtr) == false){
      69           0 :                 assert(nullDataptr != nullptr);
      70           0 :                 if(bufferManager){
      71           0 :                     bufferManager->releaseABuffer(newDataPtr);
      72             :                 }
      73             :                 else{
      74           0 :                     delete newDataPtr;
      75             :                 }
      76             :             }
      77             :         }
      78         105 :         return dataPtr;
      79             :     }
      80             : 
      81         105 :     void releaseData(){
      82         105 :         nbOfPossibleDeleter += 1;
      83         105 :         assert(dataUseCounter < dataUseLimitCounter);
      84         105 :         dataUseCounter += 1;
      85         105 :         if(freeDataIfPossible() == false){
      86           6 :             nbOfPossibleDeleter -= 1;
      87             :         }
      88         105 :     }
      89             : 
      90         105 :     void addOneUse(){
      91         105 :         assert(underUsage);
      92         105 :         dataUseLimitCounter += 1;
      93         105 :     }
      94             : 
      95         103 :     void dataUseLimitIsFixed(){
      96         103 :         nbOfPossibleDeleter += 1;
      97         103 :         assert(underUsage);
      98         103 :         underUsage = false;
      99         103 :         if(freeDataIfPossible() == false){
     100          99 :             nbOfPossibleDeleter -= 1;
     101             :         }
     102         103 :     }
     103             : };
     104             : 
     105             : 
     106             : template <class TargetType>
     107             : class SpDataBuffer{
     108             :     SpDataBufferCore<TargetType>* dataPtr;
     109             : 
     110             : public:
     111         105 :     SpDataBuffer(SpDataBufferCore<TargetType>& inData)
     112         105 :         : dataPtr(&inData){
     113         105 :         dataPtr->useData();
     114         105 :     }
     115             : 
     116             :     SpDataBuffer(const SpDataBufferCore<TargetType>& inData)
     117             :         : SpDataBuffer(*const_cast<SpDataBufferCore<TargetType>*>(&inData)){
     118             :     }
     119             : 
     120             :     SpDataBuffer(const SpDataBuffer&) = delete;
     121             :     SpDataBuffer& operator=(const SpDataBuffer&) = delete;
     122             : 
     123         105 :     ~SpDataBuffer(){
     124         105 :         dataPtr->releaseData();
     125         105 :     }
     126             : 
     127             :     operator TargetType&(){
     128             :         return *dataPtr->getData();
     129             :     }
     130             : 
     131             :     operator const TargetType&() const{
     132             :         return *dataPtr->getData();
     133             :     }
     134             : 
     135             :     TargetType* operator->(){
     136             :         return dataPtr->getData();
     137             :     }
     138             : 
     139             :     const TargetType* operator->() const{
     140             :         return dataPtr->getData();
     141             :     }
     142             : 
     143         105 :     TargetType& operator*(){
     144         105 :         return *dataPtr->getData();
     145             :     }
     146             : 
     147             :     const TargetType& operator*() const{
     148             :         return *dataPtr->getData();
     149             :     }
     150             : };
     151             : 
     152             : template <class TargetType>
     153             : class SpBufferDataView{
     154             :     SpDataBufferCore<TargetType>* dataPtr;
     155             : 
     156             : public:
     157         103 :     explicit SpBufferDataView(SpAbstractBufferManager<TargetType>* inBufferManager = nullptr){
     158         103 :         dataPtr = new SpDataBufferCore<TargetType>(inBufferManager);
     159         103 :     }
     160             : 
     161             :     SpBufferDataView(SpBufferDataView&&) = default;
     162             : 
     163             :     SpBufferDataView(const SpBufferDataView&) = delete;
     164             :     SpBufferDataView& operator=(const SpBufferDataView&) = delete;
     165             :     SpBufferDataView& operator=(SpBufferDataView&&) = delete;
     166             : 
     167         103 :     ~SpBufferDataView(){
     168         103 :         dataPtr->dataUseLimitIsFixed();
     169         103 :     }
     170             : 
     171             :     // Must be called only when passed to a task
     172         105 :     SpDataBufferCore<TargetType>& getDataDep(){
     173         105 :         dataPtr->addOneUse();
     174         105 :         return *dataPtr;
     175             :     }
     176             : };
     177             : 
     178             : #endif

Generated by: LCOV version 1.14