SpECTRE Documentation Coverage Report
Current view: top level - Parallel - Callback.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 13 77 16.9 %
Date: 2025-12-05 05:03:31
Legend: Lines: hit not hit

          Line data    Source code
       1           1 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : /// \file
       5             : /// Defines Parallel::Callback.
       6             : 
       7             : #pragma once
       8             : 
       9             : #include <memory>
      10             : #include <pup.h>
      11             : #include <tuple>
      12             : #include <utility>
      13             : 
      14             : #include "Parallel/Invoke.hpp"
      15             : #include "Utilities/PrettyType.hpp"
      16             : #include "Utilities/Serialization/CharmPupable.hpp"
      17             : #include "Utilities/Serialization/RegisterDerivedClassesWithCharm.hpp"
      18             : #include "Utilities/TypeTraits/HasEquivalence.hpp"
      19             : 
      20             : namespace Parallel {
      21             : namespace detail {
      22             : // Not all tuple arguments are guaranteed to have operator==, so we check the
      23             : // ones we can.
      24             : template <typename... Args>
      25             : bool tuple_equal(const std::tuple<Args...>& tuple_1,
      26             :                  const std::tuple<Args...>& tuple_2) {
      27             :   bool result = true;
      28             :   tmpl::for_each<tmpl::make_sequence<tmpl::size_t<0>,
      29             :                                      tmpl::size<tmpl::list<Args...>>::value>>(
      30             :       [&](const auto index_v) {
      31             :         constexpr size_t index = tmpl::type_from<decltype(index_v)>::value;
      32             : 
      33             :         if (not result) {
      34             :           return;
      35             :         }
      36             : 
      37             :         if constexpr (tt::has_equivalence_v<decltype(std::get<index>(
      38             :                           tuple_1))>) {
      39             :           result =
      40             :               result and std::get<index>(tuple_1) == std::get<index>(tuple_2);
      41             :         }
      42             :       });
      43             : 
      44             :   return result;
      45             : }
      46             : }  // namespace detail
      47             : 
      48             : /// An abstract base class, whose derived class holds a function that
      49             : /// can be invoked at a later time.  The function is intended to be
      50             : /// invoked only once.
      51           1 : class Callback : public PUP::able {
      52             :  public:
      53           0 :   WRAPPED_PUPable_abstract(Callback);  // NOLINT
      54           0 :   Callback() = default;
      55           0 :   Callback(const Callback&) = default;
      56           0 :   Callback& operator=(const Callback&) = default;
      57           0 :   Callback(Callback&&) = default;
      58           0 :   Callback& operator=(Callback&&) = default;
      59           0 :   ~Callback() override = default;
      60           0 :   explicit Callback(CkMigrateMessage* msg) : PUP::able(msg) {}
      61           0 :   virtual void invoke() = 0;
      62           0 :   virtual void register_with_charm() = 0;
      63             :   /*!
      64             :    * \brief Returns if this callback is equal to the one passed in.
      65             :    */
      66           1 :   virtual bool is_equal_to(const Callback& rhs) const = 0;
      67           0 :   virtual std::string name() const = 0;
      68           0 :   virtual std::unique_ptr<Callback> get_clone() = 0;
      69             : };
      70             : 
      71             : /// Wraps a call to a simple action and its arguments.
      72             : /// Can be invoked only once.
      73             : template <typename SimpleAction, typename Proxy, typename... Args>
      74           1 : class SimpleActionCallback : public Callback {
      75             :  public:
      76           0 :   WRAPPED_PUPable_decl_template(SimpleActionCallback);  // NOLINT
      77           0 :   SimpleActionCallback() = default;
      78             :   // NOLINTNEXTLINE(google-explicit-constructor)
      79           0 :   SimpleActionCallback(Proxy proxy, std::decay_t<Args>... args)
      80             :       : proxy_(proxy), args_(std::move(args)...) {}
      81           0 :   explicit SimpleActionCallback(CkMigrateMessage* msg) : Callback(msg) {}
      82             :   using PUP::able::register_constructor;
      83           0 :   void invoke() override {
      84             :     std::apply(
      85             :         [this](auto&&... args) {
      86             :           Parallel::simple_action<SimpleAction>(proxy_, args...);
      87             :         },
      88             :         std::move(args_));
      89             :   }
      90           0 :   void pup(PUP::er& p) override {
      91             :     p | proxy_;
      92             :     p | args_;
      93             :   }
      94             : 
      95           0 :   void register_with_charm() override {
      96             :     static bool done_registration{false};
      97             :     if (done_registration) {
      98             :       return;
      99             :     }
     100             :     done_registration = true;
     101             :     register_classes_with_charm<SimpleActionCallback>();
     102             :   }
     103             : 
     104           1 :   bool is_equal_to(const Callback& rhs) const override {
     105             :     const auto* downcast_ptr = dynamic_cast<const SimpleActionCallback*>(&rhs);
     106             :     if (downcast_ptr == nullptr) {
     107             :       return false;
     108             :     }
     109             :     return detail::tuple_equal(args_, downcast_ptr->args_);
     110             :   }
     111             : 
     112           0 :   std::string name() const override {
     113             :     // Use pretty_type::get_name with the action since we want to differentiate
     114             :     // template paremeters. Only use pretty_type::name for proxy because it'll
     115             :     // likely be really long with the template parameters which is unnecessary
     116             :     return "SimpleActionCallback(" + pretty_type::get_name<SimpleAction>() +
     117             :            "," + pretty_type::name<Proxy>() + ")";
     118             :   }
     119             : 
     120           0 :   std::unique_ptr<Callback> get_clone() override {
     121             :     return std::make_unique<SimpleActionCallback<SimpleAction, Proxy, Args...>>(
     122             :         *this);
     123             :   }
     124             : 
     125             :  private:
     126           0 :   std::decay_t<Proxy> proxy_{};
     127           0 :   std::tuple<std::decay_t<Args>...> args_{};
     128             : };
     129             : 
     130             : /// Wraps a call to a simple action without arguments.
     131             : template <typename SimpleAction, typename Proxy>
     132           1 : class SimpleActionCallback<SimpleAction, Proxy> : public Callback {
     133             :  public:
     134           0 :   WRAPPED_PUPable_decl_template(SimpleActionCallback);  // NOLINT
     135           0 :   SimpleActionCallback() = default;
     136             :   // NOLINTNEXTLINE(google-explicit-constructor)
     137           0 :   SimpleActionCallback(Proxy proxy) : proxy_(proxy) {}
     138           0 :   explicit SimpleActionCallback(CkMigrateMessage* msg) : Callback(msg) {}
     139             :   using PUP::able::register_constructor;
     140           0 :   void invoke() override { Parallel::simple_action<SimpleAction>(proxy_); }
     141             : 
     142           0 :   void pup(PUP::er& p) override { p | proxy_; }
     143             : 
     144           0 :   void register_with_charm() override {
     145             :     static bool done_registration{false};
     146             :     if (done_registration) {
     147             :       return;
     148             :     }
     149             :     done_registration = true;
     150             :     register_classes_with_charm<SimpleActionCallback>();
     151             :   }
     152             : 
     153           1 :   bool is_equal_to(const Callback& rhs) const override {
     154             :     const auto* downcast_ptr = dynamic_cast<const SimpleActionCallback*>(&rhs);
     155             :     return downcast_ptr != nullptr;
     156             :   }
     157             : 
     158           0 :   std::string name() const override {
     159             :     // Use pretty_type::get_name with the action since we want to differentiate
     160             :     // template paremeters. Only use pretty_type::name for proxy because it'll
     161             :     // likely be really long with the template parameters which is unnecessary
     162             :     return "SimpleActionCallback(" + pretty_type::get_name<SimpleAction>() +
     163             :            "," + pretty_type::name<Proxy>() + ")";
     164             :   }
     165             : 
     166           0 :   std::unique_ptr<Callback> get_clone() override {
     167             :     return std::make_unique<SimpleActionCallback<SimpleAction, Proxy>>(*this);
     168             :   }
     169             : 
     170             :  private:
     171           0 :   std::decay_t<Proxy> proxy_{};
     172             : };
     173             : 
     174             : /// Wraps a call to a threaded action and its arguments.
     175             : /// Can be invoked only once.
     176             : template <typename ThreadedAction, typename Proxy, typename... Args>
     177           1 : class ThreadedActionCallback : public Callback {
     178             :  public:
     179           0 :   WRAPPED_PUPable_decl_template(ThreadedActionCallback);  // NOLINT
     180           0 :   ThreadedActionCallback() = default;
     181             :   // NOLINTNEXTLINE(google-explicit-constructor)
     182           0 :   ThreadedActionCallback(Proxy proxy, std::decay_t<Args>... args)
     183             :       : proxy_(proxy), args_(std::move(args)...) {}
     184           0 :   explicit ThreadedActionCallback(CkMigrateMessage* msg) : Callback(msg) {}
     185             :   using PUP::able::register_constructor;
     186           0 :   void invoke() override {
     187             :     std::apply(
     188             :         [this](auto&&... args) {
     189             :           Parallel::threaded_action<ThreadedAction>(proxy_, args...);
     190             :         },
     191             :         std::move(args_));
     192             :   }
     193           0 :   void pup(PUP::er& p) override {
     194             :     p | proxy_;
     195             :     p | args_;
     196             :   }
     197             : 
     198           0 :   void register_with_charm() override {
     199             :     static bool done_registration{false};
     200             :     if (done_registration) {
     201             :       return;
     202             :     }
     203             :     done_registration = true;
     204             :     register_classes_with_charm<ThreadedActionCallback>();
     205             :   }
     206             : 
     207           1 :   bool is_equal_to(const Callback& rhs) const override {
     208             :     const auto* downcast_ptr =
     209             :         dynamic_cast<const ThreadedActionCallback*>(&rhs);
     210             :     if (downcast_ptr == nullptr) {
     211             :       return false;
     212             :     }
     213             :     return detail::tuple_equal(args_, downcast_ptr->args_);
     214             :   }
     215             : 
     216           0 :   std::string name() const override {
     217             :     // Use pretty_type::get_name with the action since we want to differentiate
     218             :     // template paremeters. Only use pretty_type::name for proxy because it'll
     219             :     // likely be really long with the template parameters which is unnecessary
     220             :     return "ThreadedActionCallback(" + pretty_type::get_name<ThreadedAction>() +
     221             :            "," + pretty_type::name<Proxy>() + ")";
     222             :   }
     223             : 
     224           0 :   std::unique_ptr<Callback> get_clone() override {
     225             :     return std::make_unique<
     226             :         ThreadedActionCallback<ThreadedAction, Proxy, Args...>>(*this);
     227             :   }
     228             : 
     229             :  private:
     230           0 :   std::decay_t<Proxy> proxy_{};
     231           0 :   std::tuple<std::decay_t<Args>...> args_{};
     232             : };
     233             : 
     234             : /// Wraps a call to a threaded action without arguments.
     235             : template <typename ThreadedAction, typename Proxy>
     236           1 : class ThreadedActionCallback<ThreadedAction, Proxy> : public Callback {
     237             :  public:
     238           0 :   WRAPPED_PUPable_decl_template(ThreadedActionCallback);  // NOLINT
     239           0 :   ThreadedActionCallback() = default;
     240             :   // NOLINTNEXTLINE(google-explicit-constructor)
     241           0 :   ThreadedActionCallback(Proxy proxy) : proxy_(proxy) {}
     242           0 :   explicit ThreadedActionCallback(CkMigrateMessage* msg) : Callback(msg) {}
     243             :   using PUP::able::register_constructor;
     244           0 :   void invoke() override { Parallel::threaded_action<ThreadedAction>(proxy_); }
     245             : 
     246           0 :   void pup(PUP::er& p) override { p | proxy_; }
     247             : 
     248           0 :   void register_with_charm() override {
     249             :     static bool done_registration{false};
     250             :     if (done_registration) {
     251             :       return;
     252             :     }
     253             :     done_registration = true;
     254             :     register_classes_with_charm<ThreadedActionCallback>();
     255             :   }
     256             : 
     257           1 :   bool is_equal_to(const Callback& rhs) const override {
     258             :     const auto* downcast_ptr =
     259             :         dynamic_cast<const ThreadedActionCallback*>(&rhs);
     260             :     return downcast_ptr != nullptr;
     261             :   }
     262             : 
     263           0 :   std::string name() const override {
     264             :     // Use pretty_type::get_name with the action since we want to differentiate
     265             :     // template paremeters. Only use pretty_type::name for proxy because it'll
     266             :     // likely be really long with the template parameters which is unnecessary
     267             :     return "ThreadedActionCallback(" + pretty_type::get_name<ThreadedAction>() +
     268             :            "," + pretty_type::name<Proxy>() + ")";
     269             :   }
     270             : 
     271           0 :   std::unique_ptr<Callback> get_clone() override {
     272             :     return std::make_unique<ThreadedActionCallback<ThreadedAction, Proxy>>(
     273             :         *this);
     274             :   }
     275             : 
     276             :  private:
     277           0 :   std::decay_t<Proxy> proxy_{};
     278             : };
     279             : 
     280             : /// Wraps a call to perform_algorithm.
     281             : template <typename Proxy>
     282           1 : class PerformAlgorithmCallback : public Callback {
     283             :  public:
     284           0 :   WRAPPED_PUPable_decl_template(PerformAlgorithmCallback);  // NOLINT
     285           0 :   PerformAlgorithmCallback() = default;
     286             :   // NOLINTNEXTLINE(google-explicit-constructor)
     287           0 :   PerformAlgorithmCallback(Proxy proxy) : proxy_(proxy) {}
     288           0 :   explicit PerformAlgorithmCallback(CkMigrateMessage* msg) : Callback(msg) {}
     289             :   using PUP::able::register_constructor;
     290           0 :   void invoke() override { proxy_.perform_algorithm(); }
     291           0 :   void pup(PUP::er& p) override { p | proxy_; }
     292             : 
     293           0 :   void register_with_charm() override {
     294             :     static bool done_registration{false};
     295             :     if (done_registration) {
     296             :       return;
     297             :     }
     298             :     done_registration = true;
     299             :     register_classes_with_charm<PerformAlgorithmCallback>();
     300             :   }
     301             : 
     302           1 :   bool is_equal_to(const Callback& rhs) const override {
     303             :     const auto* downcast_ptr =
     304             :         dynamic_cast<const PerformAlgorithmCallback*>(&rhs);
     305             :     return downcast_ptr != nullptr;
     306             :   }
     307             : 
     308           0 :   std::string name() const override {
     309             :     // Only use pretty_type::name for proxy because it'll likely be really long
     310             :     // with the template parameters which is unnecessary
     311             :     return "PerformAlgorithmCallback(" + pretty_type::name<Proxy>() + ")";
     312             :   }
     313             : 
     314           0 :   std::unique_ptr<Callback> get_clone() override {
     315             :     return std::make_unique<PerformAlgorithmCallback<Proxy>>(*this);
     316             :   }
     317             : 
     318             :  private:
     319           0 :   std::decay_t<Proxy> proxy_{};
     320             : };
     321             : 
     322             : /// \cond
     323             : template <typename Proxy>
     324             : // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
     325             : PUP::able::PUP_ID PerformAlgorithmCallback<Proxy>::my_PUP_ID = 0;
     326             : template <typename SimpleAction, typename Proxy, typename... Args>
     327             : PUP::able::PUP_ID
     328             :     // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
     329             :     SimpleActionCallback<SimpleAction, Proxy, Args...>::my_PUP_ID =
     330             :         0;  // NOLINT
     331             : template <typename SimpleAction, typename Proxy>
     332             : // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
     333             : PUP::able::PUP_ID SimpleActionCallback<SimpleAction, Proxy>::my_PUP_ID =
     334             :     0;  // NOLINT
     335             : template <typename ThreadedAction, typename Proxy, typename... Args>
     336             : PUP::able::PUP_ID
     337             :     // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
     338             :     ThreadedActionCallback<ThreadedAction, Proxy, Args...>::my_PUP_ID =
     339             :         0;  // NOLINT
     340             : template <typename ThreadedAction, typename Proxy>
     341             : // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
     342             : PUP::able::PUP_ID ThreadedActionCallback<ThreadedAction, Proxy>::my_PUP_ID =
     343             :     0;  // NOLINT
     344             : /// \endcond
     345             : 
     346             : }  // namespace Parallel

Generated by: LCOV version 1.14