LCOV - code coverage report
Current view: top level - Src/Data - SpDataAccessMode.hpp (source / functions) Hit Total Coverage
Test: Coverage example Lines: 54 55 98.2 %
Date: 2021-12-02 17:21:05 Functions: 545 832 65.5 %

          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 SPDATAACCESSMODE_HPP
       6             : #define SPDATAACCESSMODE_HPP
       7             : 
       8             : #include <type_traits>
       9             : #include <array>
      10             : 
      11             : #include "Config/SpConfig.hpp"
      12             : #include "Utils/SpArrayView.hpp"
      13             : #include "Utils/SpDebug.hpp"
      14             : #include "Data/SpDataDuplicator.hpp"
      15             : #include "Utils/SpArrayAccessor.hpp"
      16             : #include "Utils/small_vector.hpp"
      17             : 
      18             : ////////////////////////////////////////////////////////
      19             : /// All possible data access modes
      20             : ////////////////////////////////////////////////////////
      21             : 
      22             : enum class SpDataAccessMode{
      23             :     READ=0,
      24             :     WRITE,
      25             :     PARALLEL_WRITE,
      26             :     COMMUTATIVE_WRITE,
      27             :     POTENTIAL_WRITE
      28             : };
      29             : 
      30             : using SpDataAccessModeField = unsigned char;
      31             : 
      32             : ////////////////////////////////////////////////////////
      33             : /// Convert to string
      34             : ////////////////////////////////////////////////////////
      35             : 
      36       16403 : inline std::string SpModeToStr(const SpDataAccessMode inMode){
      37       16403 :     switch(inMode){
      38        5606 :     case SpDataAccessMode::READ: return "READ";
      39        7868 :     case SpDataAccessMode::WRITE: return "WRITE";
      40         135 :     case SpDataAccessMode::PARALLEL_WRITE: return "PARALLEL_WRITE";
      41         133 :     case SpDataAccessMode::COMMUTATIVE_WRITE: return "COMMUTATIVE_WRITE";
      42        2673 :     case SpDataAccessMode::POTENTIAL_WRITE: return "POTENTIAL_WRITE";
      43             :     }
      44           0 :     return "UNDEFINED";
      45             : }
      46             : 
      47             : ////////////////////////////////////////////////////////
      48             : /// Data mode => a mode + a data
      49             : ////////////////////////////////////////////////////////
      50             : 
      51             : template <SpDataAccessMode AccessModeT, class HandleTypeT>
      52             : struct SpScalarDataMode{
      53             :     static_assert(std::is_reference<HandleTypeT>::value,
      54             :                   "The given type must be a reference");
      55             : public:
      56             :     // To test at compile time if it is a scalar
      57             :     static const bool IsScalar = true;
      58             :     // The access mode of the data/access pair
      59             :     static const SpDataAccessMode AccessMode = AccessModeT;
      60             :     // The original data type (including reference)
      61             :     using HandleTypeRef = HandleTypeT;
      62             :     static_assert(std::is_reference<HandleTypeRef>::value, "The given type must be a reference");
      63             :     // The original data type (without reference)
      64             :     using HandleTypeNoRef = std::remove_reference_t<HandleTypeRef>;
      65             :     static_assert(!std::is_reference<HandleTypeNoRef>::value, "HandleTypeNoRef should be without reference");
      66             :     // The original data type (without reference with pointer)
      67             :     using HandleTypePtr = std::remove_reference_t<HandleTypeRef>*;
      68             :     static_assert(!std::is_reference<HandleTypePtr>::value && std::is_pointer<HandleTypePtr>::value, "HandleTypeNoRef should be without reference");
      69             :     // The raw data type (no const not ref)
      70             :     using RawHandleType = std::remove_const_t<std::remove_reference_t<HandleTypeRef>>;
      71             :     static_assert(!std::is_reference<RawHandleType>::value && !std::is_const<RawHandleType>::value, "HandleTypeNoRef should be without reference");
      72             : private:
      73             :     // The reference on the data
      74             :     HandleTypePtr ptrToData;
      75             : 
      76             : public:
      77             :     // Simple constructor (simply transfer the handle)
      78        1566 :     constexpr explicit SpScalarDataMode(HandleTypeT& inHandle)
      79        1566 :         : ptrToData(std::addressof(inHandle)){
      80        1566 :     }
      81             : 
      82             :     SpScalarDataMode(const SpScalarDataMode&) = default;
      83             :     SpScalarDataMode(SpScalarDataMode&&) = delete;
      84             :     SpScalarDataMode& operator=(const SpScalarDataMode&) = delete;
      85             :     SpScalarDataMode& operator=(SpScalarDataMode&&) = delete;
      86             : 
      87        6772 :     constexpr std::array<HandleTypePtr,1> getAllData(){
      88        6772 :         return std::array<HandleTypePtr,1>{ptrToData};
      89             :     }
      90             : 
      91        1377 :     constexpr HandleTypeRef getView(){
      92        1377 :         return *ptrToData;
      93             :     }
      94             : 
      95         180 :     constexpr void updatePtr([[maybe_unused]] const long int position, HandleTypePtr ptr){
      96         180 :         assert(position < 1);
      97         180 :         ptrToData = ptr;
      98         180 :     }
      99             : };
     100             : 
     101             : template <SpDataAccessMode AccessModeT, class HandleTypeT, class AccessorTypeT>
     102             : struct SpContainerDataMode{
     103             :     static_assert(std::is_pointer<HandleTypeT>::value,
     104             :                   "The given type must be a pointer");
     105             :     static_assert(!std::is_reference<HandleTypeT>::value,
     106             :                   "The given type must be not a pointer");
     107             : public:
     108             :     // To test at compile time if it is a scalar
     109             :     static const bool IsScalar = false;
     110             :     // The access mode of the data/access pair
     111             :     static const SpDataAccessMode AccessMode = AccessModeT;
     112             :     // The original data type (without reference with pointer)
     113             :     using HandleTypePtr = HandleTypeT;
     114             :     static_assert(!std::is_reference<HandleTypePtr>::value && std::is_pointer<HandleTypePtr>::value, "HandleTypeNoRef should be without reference");
     115             :     // The original data type (without reference)
     116             :     using HandleTypeNoRef = std::remove_pointer_t<HandleTypePtr>;
     117             :     static_assert(!std::is_reference<HandleTypeNoRef>::value, "HandleTypeNoRef should be without reference");
     118             :     // The original data type (including reference)
     119             :     using HandleTypeRef = HandleTypeNoRef&;
     120             :     static_assert(std::is_reference<HandleTypeRef>::value, "The given type must be a reference");
     121             :     // The raw data type (no const not ref)
     122             :     using RawHandleType = std::remove_const_t<std::remove_reference_t<HandleTypeRef>>;
     123             :     static_assert(!std::is_reference<RawHandleType>::value && !std::is_const<RawHandleType>::value, "HandleTypeNoRef should be without reference");
     124             : 
     125             :     using AccessorType = AccessorTypeT;
     126             : private:
     127             :     AccessorTypeT accessor;
     128             :     small_vector<HandleTypePtr> ptrToData;
     129             : 
     130             : public:
     131             : 
     132             :     template <class VHC>
     133          66 :     SpContainerDataMode(HandleTypePtr inHandle, VHC&& inView)
     134          66 :         : accessor(inHandle, std::forward<VHC>(inView)){
     135          66 :         ptrToData.reserve(accessor.getSize());
     136         446 :         for(HandleTypePtr ptr : accessor){
     137         380 :             ptrToData.push_back(ptr);
     138             :         }
     139          66 :     }
     140             : 
     141         492 :     small_vector_base<HandleTypePtr>& getAllData(){
     142         492 :         return ptrToData;
     143             :     }
     144             : 
     145          74 :     AccessorType& getView(){
     146          74 :         return accessor;
     147             :     }
     148             : 
     149         110 :     void updatePtr(const long int position, HandleTypePtr ptr){
     150         110 :         assert(position < static_cast<long int>(ptrToData.size()));
     151         110 :         ptrToData[position] = ptr;
     152         110 :         accessor.updatePtr(position, ptr);
     153         110 :     }
     154             : 
     155             :     SpContainerDataMode(SpContainerDataMode&&) = default;
     156         232 :     SpContainerDataMode(const SpContainerDataMode&) = default;
     157             :     SpContainerDataMode& operator=(const SpContainerDataMode&) = delete;
     158             :     SpContainerDataMode& operator=(SpContainerDataMode&&) = delete;
     159             : };
     160             : 
     161             : ////////////////////////////////////////////////////////
     162             : /// Access mode functions
     163             : ////////////////////////////////////////////////////////
     164             : 
     165             : template <class DepType>
     166         370 : constexpr SpScalarDataMode<SpDataAccessMode::READ, const DepType&> SpRead(const DepType& inDep){
     167         370 :     return SpScalarDataMode<SpDataAccessMode::READ, const DepType&>(inDep);
     168             : }
     169             : 
     170             : template <class DepType>
     171        1041 : constexpr SpScalarDataMode<SpDataAccessMode::WRITE, DepType&> SpWrite(DepType& inDep){
     172             :     static_assert(std::is_const<DepType>::value == false, "Write cannot be done on const value");
     173        1041 :     return SpScalarDataMode<SpDataAccessMode::WRITE, DepType&>(inDep);
     174             : }
     175             : 
     176             : template <class DepType>
     177          22 : constexpr SpScalarDataMode<SpDataAccessMode::PARALLEL_WRITE, DepType&> SpParallelWrite(DepType& inDep){
     178             :     static_assert(std::is_const<DepType>::value == false, "Atomic Write cannot be done on const value");
     179          22 :     return SpScalarDataMode<SpDataAccessMode::PARALLEL_WRITE, DepType&>(inDep);
     180             : }
     181             : 
     182             : template <class DepType>
     183          14 : constexpr SpScalarDataMode<SpDataAccessMode::COMMUTATIVE_WRITE, DepType&> SpCommutativeWrite(DepType& inDep){
     184             :     static_assert(std::is_const<DepType>::value == false, "Commutative Write cannot be done on const value");
     185          14 :     return SpScalarDataMode<SpDataAccessMode::COMMUTATIVE_WRITE, DepType&>(inDep);
     186             : }
     187             : 
     188             : template <class DepType>
     189         119 : constexpr SpScalarDataMode<SpDataAccessMode::POTENTIAL_WRITE, DepType&> SpPotentialWrite(DepType& inDep){
     190             :     static_assert(std::is_const<DepType>::value == false, "Potential write cannot be done on const value");
     191             :     static_assert(SpDataCanBeDuplicate<DepType>::value, "Potentially written to data must be duplicatable");
     192         119 :     return SpScalarDataMode<SpDataAccessMode::POTENTIAL_WRITE, DepType&>(inDep);
     193             : }
     194             : 
     195             : ////////////////////////////////////////////////////////
     196             : 
     197             : template <class DepType, class ViewType>
     198          66 : SpContainerDataMode<SpDataAccessMode::READ, const DepType*,SpArrayAccessor<const DepType>> SpReadArray(const DepType* inDep, ViewType&& inInterval){
     199          66 :     return SpContainerDataMode<SpDataAccessMode::READ, const DepType*,SpArrayAccessor<const DepType>>(inDep,std::forward<ViewType>(inInterval));
     200             : }
     201             : 
     202             : template <class DepType, class ViewType>
     203             : SpContainerDataMode<SpDataAccessMode::WRITE, DepType*,SpArrayAccessor<DepType>> SpWriteArray(DepType* inDep, ViewType&& inInterval){
     204             :     static_assert(std::is_const<DepType>::value == false, "SpWriteArray cannot be done on const value");
     205             :     return SpContainerDataMode<SpDataAccessMode::WRITE, DepType*,SpArrayAccessor<DepType>>(inDep,std::forward<ViewType>(inInterval));
     206             : }
     207             : 
     208             : template <class DepType, class ViewType>
     209             : SpContainerDataMode<SpDataAccessMode::COMMUTATIVE_WRITE, DepType*,SpArrayAccessor<DepType>> SpCommutativeWriteArray(DepType* inDep, ViewType&& inInterval){
     210             :     static_assert(std::is_const<DepType>::value == false, "SpCommutativeWriteArray cannot be done on const value");
     211             :     return SpContainerDataMode<SpDataAccessMode::COMMUTATIVE_WRITE, DepType*,SpArrayAccessor<DepType>>(inDep,std::forward<ViewType>(inInterval));
     212             : }
     213             : 
     214             : template <class DepType, class ViewType>
     215             : SpContainerDataMode<SpDataAccessMode::PARALLEL_WRITE, DepType*,SpArrayAccessor<DepType>> SpParallelWriteArray(DepType* inDep, ViewType&& inInterval){
     216             :     static_assert(std::is_const<DepType>::value == false, "SpParallelWriteArray cannot be done on const value");
     217             :     return SpContainerDataMode<SpDataAccessMode::PARALLEL_WRITE, DepType*,SpArrayAccessor<DepType>>(inDep,std::forward<ViewType>(inInterval));
     218             : }
     219             : 
     220             : template <class DepType, class ViewType>
     221             : SpContainerDataMode<SpDataAccessMode::POTENTIAL_WRITE, DepType*,SpArrayAccessor<DepType>> SpPotentialWriteArray(DepType* inDep, ViewType&& inInterval){
     222             :     static_assert(std::is_const<DepType>::value == false, "SpPotentialWriteArray cannot be done on const value");
     223             :     return SpContainerDataMode<SpDataAccessMode::POTENTIAL_WRITE, DepType*,SpArrayAccessor<DepType>>(inDep,std::forward<ViewType>(inInterval));
     224             : }
     225             : 
     226             : ////////////////////////////////////////////////////////
     227             : /// Forbid on rvalue
     228             : ////////////////////////////////////////////////////////
     229             : 
     230             : template <class DepType>
     231             : constexpr const DepType& SpRead(const DepType&& inDep) = delete;
     232             : 
     233             : template <class DepType>
     234             : constexpr std::remove_const_t<DepType>& SpWrite(DepType&& inDep) = delete;
     235             : 
     236             : template <class DepType>
     237             : constexpr std::remove_const_t<DepType>& SpParallelWrite(DepType&& inDep) = delete;
     238             : 
     239             : template <class DepType>
     240             : constexpr std::remove_const_t<DepType>& SpCommutativeWrite(DepType&& inDep) = delete;
     241             : 
     242             : template <class DepType>
     243             : constexpr std::remove_const_t<DepType>& SpPotentialWrite(DepType&& inDep) = delete;
     244             : 
     245             : ////////////////////////////////////////////////////////
     246             : /// Get data from data, or SpDataAccessMode or pair
     247             : ////////////////////////////////////////////////////////
     248             : 
     249             : template <SpDataAccessMode AccessMode, class ParamsType>
     250             : ParamsType& GetRealData(SpScalarDataMode<AccessMode, ParamsType>& scalarData){
     251             :     return scalarData.data;
     252             : }
     253             : 
     254             : template <SpDataAccessMode AccessMode, class HandleTypeRef, class ViewType>
     255             : ViewType& GetRealData(SpContainerDataMode<AccessMode, HandleTypeRef, ViewType>& containerData){
     256             :     return containerData.getView();
     257             : }
     258             : 
     259             : template<typename T, typename = void>
     260             : struct is_plus_equal_compatible : std::false_type
     261             : { };
     262             : 
     263             : template<typename T>
     264             : struct is_plus_equal_compatible<T,
     265             :     typename std::enable_if<
     266             :         true,
     267             :         decltype(std::declval<T&>() += std::declval<const T&>(), (void)0)
     268             :         >::type
     269             :     > : std::true_type
     270             : {
     271             : };
     272             : 
     273             : 
     274             : ////////////////////////////////////////////////////////
     275             : /// Test if a type has the getView method
     276             : ////////////////////////////////////////////////////////
     277             : 
     278             : template<class...> using void_t = void;
     279             : 
     280             : template<class, class = void>
     281             : struct has_getView : std::false_type {};
     282             : 
     283             : template<class T>
     284             : struct has_getView<T, void_t<decltype(std::declval<T>().getView())>> : std::true_type {};
     285             : 
     286             : template<class, class = void>
     287             : struct has_getAllData : std::false_type {};
     288             : 
     289             : template<class T>
     290             : struct has_getAllData<T, void_t<decltype(std::declval<T>().getAllData())>> : std::true_type {};
     291             : 
     292             : template <SpDataAccessMode dam1, SpDataAccessMode dam2>
     293             : struct access_modes_are_equal_internal : std::conditional_t<dam1==dam2, std::true_type, std::false_type> {};
     294             :     
     295             : template<SpDataAccessMode dam1, typename T, typename = std::void_t<>>
     296             : struct access_modes_are_equal : std::false_type {};
     297             : 
     298             : template <SpDataAccessMode dam1, typename T>
     299             : struct access_modes_are_equal<dam1, T, std::void_t<decltype(T::AccessMode)>> : access_modes_are_equal_internal<dam1, T::AccessMode> {};    
     300             :        
     301             : enum class SpCallableType {
     302             :     CPU=0,
     303             :     GPU        
     304             : };
     305             : 
     306             : template <bool compileWithCuda, class T, SpCallableType ct>
     307             : class SpCallableWrapper {
     308             : private:
     309             :     using CallableTy = std::remove_reference_t<T>;
     310             :     CallableTy callable; 
     311             : public:
     312             :     static constexpr auto callable_type = ct;
     313             :     
     314             :     template <typename T2, typename=std::enable_if_t<std::is_same<std::remove_reference_t<T2>, CallableTy>::value>> 
     315         964 :     SpCallableWrapper(T2&& inCallable) : callable(std::forward<T2>(inCallable)) {}
     316             :        
     317         874 :     CallableTy& getCallableRef() {
     318         874 :         return callable;
     319             :     }
     320             : };
     321             : 
     322             : template <class T, SpCallableType ct>
     323             : class SpCallableWrapper<false, T, ct> {
     324             : public:
     325             :     template<typename T2>
     326           4 :     SpCallableWrapper(T2&&) {}
     327             : };
     328             : 
     329             : template <class T>
     330         964 : auto SpCpu(T &&callable) {
     331         964 :     return SpCallableWrapper<true, T, SpCallableType::CPU>(std::forward<T>(callable));
     332             : }
     333             : 
     334             : template <class T>
     335           4 : auto SpGpu(T&& callable) {
     336           4 :     return SpCallableWrapper<SpConfig::CompileWithCuda, T, SpCallableType::GPU>(std::forward<T>(callable));
     337             : }
     338             : 
     339             : template <class T0>
     340             : struct is_instantiation_of_callable_wrapper : std::false_type {};
     341             : 
     342             : template <bool b, class T0, SpCallableType ct>
     343             : struct is_instantiation_of_callable_wrapper<SpCallableWrapper<b, T0, ct>> : std::true_type {};
     344             : 
     345             : template <class T0>
     346             : inline constexpr bool is_instantiation_of_callable_wrapper_v = is_instantiation_of_callable_wrapper<T0>::value;
     347             : 
     348             : template <class T0, SpCallableType callableType0>
     349             : struct is_instantiation_of_callable_wrapper_with_type : std::false_type {};
     350             : 
     351             : template <bool b, class T0, SpCallableType callableType0, SpCallableType callableType1>
     352             : struct is_instantiation_of_callable_wrapper_with_type<SpCallableWrapper<b, T0, callableType1>, callableType0> : 
     353             : std::conditional_t<callableType0==callableType1, std::true_type, std::false_type> {};
     354             : 
     355             : template <class T, SpCallableType callableType>
     356             : inline constexpr bool is_instantiation_of_callable_wrapper_with_type_v = is_instantiation_of_callable_wrapper_with_type<T, callableType>::value;
     357             : 
     358             : #endif

Generated by: LCOV version 1.14