SpECTRE Documentation Coverage Report
Current view: top level - Parallel - Callback.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 16.9 % 77 13
Test Date: 2026-10-22 17:29:42
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 2.0-1