Walker test code coverage report
Current view: top level - Base - PUPUtil.hpp (source / functions) Hit Total Coverage
Commit: test_coverage.info Lines: 23 23 100.0 %
Date: 2022-09-21 13:52:12 Functions: 5 5 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 43 150 28.7 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Base/PUPUtil.hpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     Charm++ Pack/UnPack utilities
       9                 :            :   \details   This file contains some extensions to Charm++'s Pack/UnPack
      10                 :            :     routines.
      11                 :            : */
      12                 :            : // *****************************************************************************
      13                 :            : #ifndef PUPUtil_h
      14                 :            : #define PUPUtil_h
      15                 :            : 
      16                 :            : #include <type_traits>
      17                 :            : 
      18                 :            : #include <unordered_map>
      19                 :            : #include <unordered_set>
      20                 :            : #include <variant>
      21                 :            : #include <optional>
      22                 :            : 
      23                 :            : #include "NoWarning/pup_stl.hpp"
      24                 :            : 
      25                 :            : //! Extensions to Charm++'s Pack/Unpack routines
      26                 :            : namespace PUP {
      27                 :            : 
      28                 :            : //////////////////// Serialize enum class ////////////////////
      29                 :            : 
      30                 :            : #if defined(__clang__)
      31                 :            :   #pragma clang diagnostic push
      32                 :            :   #pragma clang diagnostic ignored "-Wuninitialized"
      33                 :            : #elif defined(STRICT_GNUC)
      34                 :            :   #pragma GCC diagnostic push
      35                 :            :   #pragma GCC diagnostic ignored "-Wuninitialized"
      36                 :            :   #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
      37                 :            : #endif
      38                 :            : 
      39                 :            : //! \brief Pack/Unpack enum class.
      40                 :            : //! \details In Charm++ usually both the pup() overload and an overload for
      41                 :            : //!   operator| are defined for all serializable types. However, we cannot
      42                 :            : //!   define operator| for enum class as it would conflict with Charm++'s
      43                 :            : //!   catch-all, template< class T > inline void operator|(PUP::er &p,T &t)
      44                 :            : //!   {...}.
      45                 :            : //! \param[in] p Charm++'s pack/unpack object
      46                 :            : //! \param[in] e Enum class to pack/unpack
      47                 :            : template< typename E,
      48                 :            :           typename std::enable_if< std::is_enum< E >::value, int >::type = 0 >
      49                 :            : inline void pup( PUP::er& p, E& e ) {
      50 [ +  - ][ -  - ]:  180376398 :   auto v = static_cast< typename std::underlying_type_t< E > >( e );
         [ -  - ][ +  - ]
         [ +  - ][ -  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  - ]
         [ -  - ][ -  - ]
         [ +  - ][ -  - ]
         [ -  - ][ +  - ]
         [ +  - ][ -  - ]
         [ -  - ][ -  - ]
         [ +  - ][ -  - ]
         [ -  - ][ +  - ]
                 [ +  - ]
      51                 :            :   p | v;
      52 [ +  - ][ -  - ]:  180364536 :   e = static_cast< E >( v );
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ +  - ][ -  - ]
         [ -  - ][ +  - ]
      53                 :            : }
      54                 :            : 
      55                 :            : #if defined(__clang__)
      56                 :            :   #pragma clang diagnostic pop
      57                 :            : #elif defined(STRICT_GNUC)
      58                 :            :   #pragma GCC diagnostic pop
      59                 :            : #endif
      60                 :            : 
      61                 :            : //////////////////// Serialize std::unordered_map ////////////////////
      62                 :            : 
      63                 :            : //! Pack/Unpack std::unordered_map.
      64                 :            : //! \param[in] p Charm++'s pack/unpack object
      65                 :            : //! \param[in] m std::unordered_map< Key, T, Hash, KeyEqual > to pack/unpack
      66                 :            : template< class Key,
      67                 :            :           class T,
      68                 :            :           class Hash = std::hash< Key >,
      69                 :            :           class KeyEqual = std::equal_to< Key > >
      70                 :            : inline void pup( PUP::er& p, std::unordered_map< Key, T, Hash, KeyEqual >& m ) {
      71                 :            :   auto size = PUP_stl_container_size( p, m );
      72                 :            :   if (p.isUnpacking()) {
      73                 :            :     for (decltype(size) s=0; s<size; ++s) {
      74                 :            :       std::pair< Key, T > node;
      75                 :            :       p | node;
      76                 :            :       m.emplace( node );
      77                 :            :     }
      78                 :            :   } else {
      79                 :            :     for (auto& t : m) {
      80                 :            :       std::pair< Key, T > node( t );
      81                 :            :       p | node;
      82                 :            :     }
      83                 :            :   }
      84                 :            : }
      85                 :            : //! Pack/Unpack std::unordered_map.
      86                 :            : //! \param[in] p Charm++'s pack/unpack object
      87                 :            : //! \param[in] m std::unordered_map< Key, T, Hash, KeyEqual > to pack/unpack
      88                 :            : template< class Key,
      89                 :            :           class T,
      90                 :            :           class Hash = std::hash< Key >,
      91                 :            :           class KeyEqual = std::equal_to< Key > >
      92                 :            : inline void operator|( PUP::er& p,
      93                 :            :                        std::unordered_map< Key, T, Hash, KeyEqual >& m )
      94                 :            : { pup( p, m ); }
      95                 :            : 
      96                 :            : //////////////////// Serialize std::unordered_set ////////////////////
      97                 :            : 
      98                 :            : //! Pack/Unpack std::unordered_set.
      99                 :            : //! \param[in] p Charm++'s pack/unpack object
     100                 :            : //! \param[in] s std::unordered_set< Key, Hash, KeyEqual > to pack/unpack
     101                 :            : template< class Key,
     102                 :            :           class Hash = std::hash< Key >,
     103                 :            :           class KeyEqual = std::equal_to< Key > >
     104                 :            : inline void pup( PUP::er& p, std::unordered_set< Key, Hash, KeyEqual >& s ) {
     105                 :            :   auto size = PUP_stl_container_size( p, s );
     106                 :            :   if (p.isUnpacking()) {
     107                 :            :     for (decltype(size) i=0; i<size; ++i) {
     108                 :            :       Key node;
     109                 :            :       p | node;
     110                 :            :       s.emplace( node );
     111                 :            :     }
     112                 :            :   } else {
     113                 :            :     for (auto& t : s) {
     114                 :            :       Key node( t );
     115                 :            :       p | node;
     116                 :            :     }
     117                 :            :   }
     118                 :            : }
     119                 :            : //! Pack/Unpack std::unordered_set.
     120                 :            : //! \param[in] p Charm++'s pack/unpack object
     121                 :            : //! \param[in] s std::unordered_set< Key, Hash, KeyEqual > to pack/unpack
     122                 :            : template< class Key,
     123                 :            :           class Hash = std::hash< Key >,
     124                 :            :           class KeyEqual = std::equal_to< Key > >
     125                 :            : inline void operator|( PUP::er& p,
     126                 :            :                        std::unordered_set< Key, Hash, KeyEqual >& s )
     127                 :            : { pup( p, s ); }
     128                 :            : 
     129                 :            : //////////////////// Serialize std::optional ////////////////////
     130                 :            : 
     131                 :            : //! Pack/Unpack std::optional
     132                 :            : //! \param[in] p Charm++'s pack/unpack object
     133                 :            : //! \param[in] o std::optional< T > of arbitrary type T to pack/unpack
     134                 :            : template< class T >
     135         [ +  + ]:     725911 : inline void pup( PUP::er& p, std::optional< T >& o ) {
     136         [ +  + ]:     725911 :   T underlying_value = o ? *o : T();
     137         [ +  - ]:     725911 :   bool exist = o ? true : false;
     138                 :            :   p | exist;
     139         [ +  - ]:     725908 :   p | underlying_value;
     140 [ +  + ][ +  + ]:    1451819 :   o = exist ? std::make_optional(underlying_value) : std::nullopt;
     141                 :     725911 : }
     142                 :            : //! Pack/Unpack std::optional
     143                 :            : //! \param[in] p Charm++'s pack/unpack object
     144                 :            : //! \param[in] o std::optional< T > of arbitrary type T to pack/unpack
     145                 :            : template< class T >
     146 [ -  - ][ -  - ]:     145187 : inline void operator|( PUP::er& p, std::optional< T >& o ) { pup( p, o ); }
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  - ]
     147                 :            : 
     148                 :            : //////////////////// Serialize std::variant ////////////////////
     149                 :            : 
     150                 :            : // Since std::variant when default-constructed is initialized to hold a value of
     151                 :            : // the first alternative of its type list, calling PUP that works based on a
     152                 :            : // std::visit with a templated operator() would always incorrectly trigger the
     153                 :            : // overload for the first type. Thus when PUPing a variant not only its value
     154                 :            : // but its type must also be sent during migration. The pup operator template
     155                 :            : // below achieves this by reading out not only the value but also its zero-based
     156                 :            : // index of the type alternative that is currently held by the variant passed to
     157                 :            : // its initializer constructor. The index and the variant are then PUPed and
     158                 :            : // when unpacking, as an additional step, the variant is reconstructed using the
     159                 :            : // index and the value in the variant. This latter is done by invoking an
     160                 :            : // expansion of an initializer list, guaranteed to happen in order, stepping
     161                 :            : // through the typelist in the variant.  Thanks to Nils Deppe for simplifying
     162                 :            : // the original version of this operation. See UnitTest/tests/Base/TestPUPUtil.h
     163                 :            : // or puping a variant in action.
     164                 :            : 
     165                 :            : //! Pack/Unpack helper for std::variant
     166                 :            : //! \param[in,out] index Counter (location) for type in variant
     167                 :            : //! \param[in] send_index Target counter (location) for type in variant
     168                 :            : //! \param[in] p Charm++'s pack/unpack object
     169                 :            : //! \param[in] var std::variant< Ts... > of arbitrary types to pack/unpack
     170                 :            : template <class T, class... Ts>
     171                 :         12 : char pup_helper( std::size_t& index,
     172                 :            :                  const std::size_t send_index,
     173                 :            :                  PUP::er& p,
     174                 :            :                  std::variant<Ts...>& var )
     175                 :            : {
     176         [ +  + ]:         12 :   if (index == send_index) {
     177         [ +  + ]:          6 :     if (p.isUnpacking()) {
     178                 :          2 :       T t{};
     179                 :            :       p | t;
     180                 :            :       var = std::move(t);
     181                 :            :     } else {
     182                 :            :       p | std::get<T>(var);
     183                 :            :     }
     184                 :            :   }
     185                 :         12 :   index++;
     186                 :         12 :   return '0';
     187                 :            : }
     188                 :            : 
     189                 :            : //! Pack/Unpack std::variant
     190                 :            : //! \param[in] p Charm++'s pack/unpack object
     191                 :            : //! \param[in] var std::variant< Ts... > of arbitrary types to pack/unpack
     192                 :            : template <class... Ts>
     193                 :          6 : void pup(PUP::er& p, std::variant<Ts...>& var) {
     194                 :          6 :   std::size_t index = 0;
     195                 :          6 :   auto send_index = var.index();
     196                 :            :   p | send_index;
     197                 :         12 :   (void)std::initializer_list<char>{
     198                 :          6 :       pup_helper<Ts>(index, send_index, p, var)...};
     199                 :          6 : }
     200                 :            : 
     201                 :            : //! Pack/Unpack std::variant
     202                 :            : //! \param[in] p Charm++'s pack/unpack object
     203                 :            : //! \param[in] d std::variant< Ts... > of arbitrary types to pack/unpack
     204                 :            : template <typename... Ts>
     205                 :            : inline void operator|(PUP::er& p, std::variant<Ts...>& d) {
     206 [ -  - ][ -  - ]:          6 :   pup(p, d);
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  - ]
     207                 :          4 : }
     208                 :            : 
     209                 :            : } // PUP::
     210                 :            : 
     211                 :            : #endif // PUPUtil_h

Generated by: LCOV version 1.14