LCOV - code coverage report
Current view: top level - Src/Utils - SpUtils.hpp (source / functions) Hit Total Coverage
Test: Coverage example Lines: 19 23 82.6 %
Date: 2021-12-02 17:21:05 Functions: 1401 2633 53.2 %

          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 SPUTILS_HPP
       6             : #define SPUTILS_HPP
       7             : 
       8             : #include <thread>
       9             : #include <string>
      10             : #include <sstream>
      11             : #include <cstring>
      12             : #include <functional>
      13             : #include <memory>
      14             : 
      15             : #ifndef _GNU_SOURCE
      16             : #define _GNU_SOURCE
      17             : #endif
      18             : #include <sys/types.h>
      19             : #include <unistd.h>
      20             : #include <sys/syscall.h>
      21             : 
      22             : #ifdef __APPLE__
      23             : #include "MacOSX.hpp"
      24             : #else    
      25             : #include <sched.h>
      26             : #endif
      27             : 
      28             : #include <cassert>
      29             : 
      30             : #include "SpDebug.hpp"
      31             : #include "small_vector.hpp"
      32             : 
      33             : /**
      34             :  * Utils methods
      35             :  */
      36             : namespace SpUtils{
      37             :     /** Return the default number of threads using hardware's capacity */
      38          39 :     inline int DefaultNumThreads(){
      39          39 :         if(getenv("OMP_NUM_THREADS")){
      40           0 :             std::istringstream iss(getenv("OMP_NUM_THREADS"),std::istringstream::in);
      41           0 :             int nbThreads = -1;
      42           0 :             iss >> nbThreads;
      43           0 :             if( /*iss.tellg()*/ iss.eof() ) return nbThreads;
      44             :         }
      45          39 :         return static_cast<int>(std::thread::hardware_concurrency());
      46             :     }
      47             : 
      48             :     inline bool DefaultToBind(const int inNumThreads){
      49             :         if(getenv("OMP_PROC_BIND")){
      50             :             return strcmp(getenv("OMP_PROC_BIND"), "TRUE") == 0
      51             :                     || strcmp(getenv("OMP_PROC_BIND"), "true") == 0
      52             :                     || strcmp(getenv("OMP_PROC_BIND"), "1") == 0;
      53             :         }
      54             :         return (inNumThreads <= static_cast<int>(std::thread::hardware_concurrency()));
      55             :     }
      56             : 
      57             :     inline void BindToCore(const int inCoreId){
      58             :         cpu_set_t mask;
      59             :         CPU_ZERO(&mask);
      60             :         CPU_SET(inCoreId, &mask);
      61             :         
      62             :         #ifdef __APPLE__
      63             :             [[maybe_unused]] int retValue = macosspecific::sched_setaffinity_np(pthread_self(), sizeof(mask), &mask);
      64             :             assert(retValue == 0);
      65             :         #else
      66             :             pid_t tid = static_cast<pid_t>(syscall(SYS_gettid));
      67             :             [[maybe_unused]] int retValue = sched_setaffinity(tid, sizeof(mask), &mask);
      68             :             assert(retValue == 0);
      69             :         #endif
      70             : 
      71             :         SpDebugPrint() << "Bind to " << inCoreId << " core";
      72             :     }
      73             : 
      74             :     /** Return the current binding (bit a position n is set to 1 when bind
      75             :      * to core n)
      76             :      */
      77             :     inline void GetBinding(cpu_set_t *mask){
      78             :         CPU_ZERO(mask);
      79             :         
      80             :         #ifdef __APPLE__
      81             :             [[maybe_unused]] int retValue = macosspecific::sched_getaffinity_np(pthread_self(), sizeof(*mask), mask);
      82             :             assert(retValue == 0);
      83             :         #else
      84             :             pid_t tid = static_cast<pid_t>(syscall(SYS_gettid));
      85             :             // Get the affinity
      86             :             [[maybe_unused]] int retValue = sched_getaffinity(tid, sizeof(*mask), mask);
      87             :             assert(retValue == 0);
      88             :         #endif
      89             :     }
      90             : 
      91             :     /** Return the current thread id */
      92             :     long int GetThreadId();
      93             : 
      94             :     /** Return true if the code is executed from a task */
      95           4 :     inline bool IsInTask(){
      96           4 :         return GetThreadId() != 0;
      97             :     }
      98             : 
      99             :     /** Set current thread Id */
     100             :     void SetThreadId(const long int inThreadId);
     101             : 
     102             :     /** Replace all substring in a string */
     103        1797 :     inline std::string ReplaceAllInString(std::string sentence, const std::string& itemToReplace, const std::string& inSubstitutionString){
     104        2336 :         for(std::string::size_type idxFound = sentence.find(itemToReplace); idxFound != std::string::npos; idxFound = sentence.find(itemToReplace)){
     105         539 :             sentence.replace(idxFound, itemToReplace.size(), inSubstitutionString);
     106             :         }
     107        1797 :         return sentence;
     108             :     }
     109             : 
     110             :     /** To perform some assert/check */
     111             :     inline void CheckCorrect(const char* test, const bool isCorrect, const int line, const char* file){
     112             :         if(!isCorrect){
     113             :             std::cout << "Error in file " << file << " line " << line << std::endl;
     114             :             std::cout << "Test was " << test << std::endl;
     115             :             exit(-1);
     116             :         }
     117             :     }
     118             : 
     119             :     template <typename CallableTy, typename TupleTy, std::size_t... Is,
     120             :     std::enable_if_t<sizeof...(Is) == 0 || std::conjunction_v<std::is_invocable<CallableTy, std::tuple_element_t<Is, std::remove_reference_t<TupleTy>>>...>, int> = 0>
     121        1601 :     static void foreach_in_tuple_impl(CallableTy &&c, TupleTy &&t, std::index_sequence<Is...>) {
     122             :         if constexpr(sizeof...(Is) > 0) {
     123             :             using RetTy = std::invoke_result_t<CallableTy, std::tuple_element_t<0, std::remove_reference_t<TupleTy>>>;
     124             : 
     125             :             if constexpr(std::is_same_v<RetTy, bool>) {
     126           9 :                 (std::invoke(std::forward<CallableTy>(c), std::get<Is>(std::forward<TupleTy>(t))) || ...);
     127             :             } else {
     128        1583 :                 (static_cast<void>(std::invoke(std::forward<CallableTy>(c), std::get<Is>(std::forward<TupleTy>(t)))),...);
     129             :             }
     130             :         }
     131        1601 :     }
     132             :     
     133             :     template <typename CallableTy, typename TupleTy, std::size_t... Is,
     134             :     std::enable_if_t<sizeof...(Is) != 0 && std::conjunction_v<std::is_invocable<CallableTy, std::integral_constant<size_t, Is>,
     135             :     std::tuple_element_t<Is, std::remove_reference_t<TupleTy>>>...>, int> = 0>
     136        1070 :     static void foreach_in_tuple_impl(CallableTy &&c, TupleTy &&t, std::index_sequence<Is...>) {
     137             :         if constexpr(sizeof...(Is) > 0) {
     138             :             using RetTy = std::invoke_result_t<CallableTy, std::integral_constant<size_t, 0>, std::tuple_element_t<0, std::remove_reference_t<TupleTy>>>;
     139             : 
     140             :             if constexpr(std::is_same_v<RetTy, bool>) {
     141             :                 (std::invoke(std::forward<CallableTy>(c), std::integral_constant<size_t, Is>{}, std::get<Is>(std::forward<TupleTy>(t))) || ...);
     142             :             } else {
     143        1070 :                 (static_cast<void>(std::invoke(std::forward<CallableTy>(c), std::integral_constant<size_t, Is>{}, std::get<Is>(std::forward<TupleTy>(t)))),...);
     144             :             }
     145             :         }
     146        1070 :     }
     147             : 
     148             :     template <typename CallableTy, typename TupleTy>
     149        2671 :     static void foreach_in_tuple(CallableTy &&c, TupleTy &&t) {
     150        2671 :         foreach_in_tuple_impl(std::forward<CallableTy>(c), std::forward<TupleTy>(t), std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<TupleTy>>>{});
     151        2671 :     }
     152             : }
     153             : 
     154             : #define spetabaru_xstr(s) spetabaru_str(s)
     155             : #define spetabaru_str(s) #s
     156             : #define always_assert(X) SpUtils::CheckCorrect(spetabaru_str(X), (X), __LINE__, __FILE__)
     157             : 
     158             : #endif

Generated by: LCOV version 1.14