Xyst test code coverage report
Current view: top level - Base - PUPUtil.hpp (source / functions) Coverage Total Hit
Commit: 1fb74642dd9d7732b67f32dec2f2762e238d3fa7 Lines: 100.0 % 38 38
Test Date: 2025-08-13 22:18:46 Functions: 92.9 % 14 13
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 26.9 % 208 56

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

Generated by: LCOV version 2.0-1