CharmRegistration.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <algorithm>
7 #include <cstddef>
8 #include <memory>
9 #include <string>
10 #include <unordered_map>
11 #include <unordered_set>
12 
13 #include "Parallel/ParallelComponentHelpers.hpp"
14 #include "Parallel/TypeTraits.hpp"
15 
16 /// \cond
17 template <size_t MaxSize, class Key, class ValueType, class Hash,
18  class KeyEqual>
19 class FixedHashMap;
20 /// \endcond
21 
22 namespace Parallel {
23 namespace charmxx {
24 /*!
25  * \ingroup CharmExtensionsGroup
26  * \brief Class to mark a constructor as a constructor for the main chare.
27  *
28  * The main chare must have a constructor that takes a `const
29  * Parallel::charmxx::MainChareRegistrationConstructor&` as its only argument.
30  * This constructor is only used to trigger the `RegisterChare::registrar` code
31  * needed for automatic registration.
32  * \see RegisterChare
33  */
35 
36 /// \cond
37 struct RegistrationHelper;
38 extern std::unique_ptr<RegistrationHelper>* charm_register_list;
39 extern size_t charm_register_list_capacity;
40 extern size_t charm_register_list_size;
41 /// \endcond
42 
43 /*!
44  * \ingroup CharmExtensionsGroup
45  * \brief Returns the template parameter as a `std::string`
46  *
47  * Uses the __PRETTY_FUNCTION__ compiler intrinsic to extract the template
48  * parameter names in the same form that Charm++ uses to register entry methods.
49  * This is used by the generated Singleton, Array, Group and Nodegroup headers,
50  * as well as in CharmMain.tpp.
51  */
52 template <class... Args>
54  std::string function_name(static_cast<char const*>(__PRETTY_FUNCTION__));
55  std::string template_params =
56  function_name.substr(function_name.find(std::string("Args = ")) + 8);
57  template_params.erase(template_params.end() - 2, template_params.end());
58  size_t pos = 0;
59  while ((pos = template_params.find(" >")) != std::string::npos) {
60  template_params.replace(pos, 1, ">");
61  template_params.erase(pos + 1, 1);
62  }
63  pos = 0;
64  while ((pos = template_params.find(", ", pos)) != std::string::npos) {
65  template_params.erase(pos + 1, 1);
66  }
67  pos = 0;
68  while ((pos = template_params.find('>', pos + 2)) != std::string::npos) {
69  template_params.replace(pos, 1, " >");
70  }
71  std::replace(template_params.begin(), template_params.end(), '%', '>');
72  // GCC's __PRETTY_FUNCTION__ adds the return type at the end, so we remove it.
73  if (template_params.find('}') != std::string::npos) {
74  template_params.erase(template_params.find('}'), template_params.size());
75  }
76  return template_params;
77 }
78 
79 /*!
80  * \ingroup CharmExtensionsGroup
81  * \brief The base class used for automatic registration of entry methods.
82  *
83  * Entry methods are automatically registered by building a list of the entry
84  * methods that need to be registered in the `charm_register_list`. All entry
85  * methods in the list are later registered in the
86  * `register_parallel_components` function, at which point the list is also
87  * deleted.
88  *
89  * The reason for using an abstract base class mechanism is that we need to be
90  * able to register entry method templates. The derived classes keep track of
91  * the template parameters and override the `register_with_charm` function.
92  * The result is that there must be one derived class template for each entry
93  * method template, but since we only have a few entry method templates this is
94  * not an issue.
95  */
97  RegistrationHelper() = default;
98  RegistrationHelper(const RegistrationHelper&) = default;
99  RegistrationHelper& operator=(const RegistrationHelper&) = default;
101  RegistrationHelper& operator=(RegistrationHelper&&) = default;
102  virtual ~RegistrationHelper() = default;
103 
104  virtual void register_with_charm() const noexcept = 0;
105  virtual std::string name() const noexcept = 0;
106  virtual bool is_registering_chare() const noexcept { return false; };
107 };
108 
109 /*!
110  * \ingroup CharmExtensionsGroup
111  * \brief Derived class for registering parallel components.
112  *
113  * Calls the appropriate Charm++ function to register a parallel component.
114  */
115 template <typename ParallelComponent>
117  using chare_type = typename ParallelComponent::chare_type;
118  using charm_type = charm_types_with_parameters<
119  ParallelComponent,
120  typename get_array_index<chare_type>::template f<ParallelComponent>>;
121  using ckindex = typename charm_type::ckindex;
122  using algorithm = typename charm_type::algorithm;
123 
124  RegisterParallelComponent() = default;
127  default;
130  ~RegisterParallelComponent() override = default;
131 
132  void register_with_charm() const noexcept override {
133  static bool done_registration{false};
134  if (done_registration) {
135  return; // LCOV_EXCL_LINE
136  }
137  done_registration = true;
138  ckindex::__register(get_template_parameters_as_string<algorithm>().c_str(),
139  sizeof(algorithm));
140  }
141 
142  bool is_registering_chare() const noexcept override { return true; }
143 
144  std::string name() const noexcept override {
145  return get_template_parameters_as_string<RegisterParallelComponent>();
146  }
147 
148  static bool registrar;
149 };
150 
151 /*!
152  * \ingroup CharmExtensionsGroup
153  * \brief Derived class for registering chares.
154  *
155  * Calls the appropriate Charm++ function to register a chare
156  *
157  * The chare that is being registered must have the following in the destructor:
158  * \code
159  * (void)Parallel::charmxx::RegisterChare<ChareName,
160  * CkIndex_ChareName>::registrar;
161  * \endcode
162  *
163  * The main chare must also have a constructor that takes a `const
164  * Parallel::charmxx::MainChareRegistrationConstructor&` as its only argument.
165  * This constructor is only used to trigger the `RegisterChare::registrar` code
166  * needed for automatic registration. The main chare is determined by specifying
167  * the type alias `charmxx_main_component` before the `Parallel/CharmMain.tpp`
168  * include.
169  * \snippet Test_AlgorithmCore.cpp charm_main_example
170  */
171 template <typename Chare, typename CkIndex>
173  RegisterChare() = default;
174  RegisterChare(const RegisterChare&) = default;
175  RegisterChare& operator=(const RegisterChare&) = default;
176  RegisterChare(RegisterChare&&) = default;
177  RegisterChare& operator=(RegisterChare&&) = default;
178  ~RegisterChare() override = default;
179 
180  void register_with_charm() const noexcept override {
181  static bool done_registration{false};
182  if (done_registration) {
183  return; // LCOV_EXCL_LINE
184  }
185  done_registration = true;
186  CkIndex::__register(get_template_parameters_as_string<Chare>().c_str(),
187  sizeof(Chare));
188  }
189 
190  bool is_registering_chare() const noexcept override { return true; }
191 
192  std::string name() const noexcept override {
193  return get_template_parameters_as_string<RegisterChare>();
194  }
195 
196  static bool registrar;
197 };
198 
199 /*!
200  * \ingroup CharmExtensionsGroup
201  * \brief Derived class for registering simple actions.
202  *
203  * Calls the appropriate Charm++ function to register a simple action.
204  */
205 template <typename ParallelComponent, typename Action, typename... Args>
207  using chare_type = typename ParallelComponent::chare_type;
208  using charm_type = charm_types_with_parameters<
209  ParallelComponent,
210  typename get_array_index<chare_type>::template f<ParallelComponent>>;
211  using cproxy = typename charm_type::cproxy;
212  using ckindex = typename charm_type::ckindex;
213  using algorithm = typename charm_type::algorithm;
214 
215  RegisterSimpleAction() = default;
216  RegisterSimpleAction(const RegisterSimpleAction&) = default;
217  RegisterSimpleAction& operator=(const RegisterSimpleAction&) = default;
219  RegisterSimpleAction& operator=(RegisterSimpleAction&&) = default;
220  ~RegisterSimpleAction() override = default;
221 
222  void register_with_charm() const noexcept override {
223  static bool done_registration{false};
224  if (done_registration) {
225  return; // LCOV_EXCL_LINE
226  }
227  done_registration = true;
228  ckindex::template idx_simple_action<Action>(
229  static_cast<void (algorithm::*)(const std::tuple<Args...>&)>(nullptr));
230  }
231 
232  std::string name() const noexcept override {
233  return get_template_parameters_as_string<RegisterSimpleAction>();
234  }
235 
236  static bool registrar;
237 };
238 
239 /// \cond
240 template <typename ParallelComponent, typename Action>
241 struct RegisterSimpleAction<ParallelComponent, Action> : RegistrationHelper {
242  using chare_type = typename ParallelComponent::chare_type;
243  using charm_type = charm_types_with_parameters<
244  ParallelComponent,
245  typename get_array_index<chare_type>::template f<ParallelComponent>>;
246  using cproxy = typename charm_type::cproxy;
247  using ckindex = typename charm_type::ckindex;
248  using algorithm = typename charm_type::algorithm;
249 
250  RegisterSimpleAction() = default;
251  RegisterSimpleAction(const RegisterSimpleAction&) = default;
252  RegisterSimpleAction& operator=(const RegisterSimpleAction&) = default;
254  RegisterSimpleAction& operator=(RegisterSimpleAction&&) = default;
255  ~RegisterSimpleAction() override = default;
256 
257  void register_with_charm() const noexcept override {
258  static bool done_registration{false};
259  if (done_registration) {
260  return; // LCOV_EXCL_LINE
261  }
262  done_registration = true;
263  ckindex::template idx_simple_action<Action>(
264  static_cast<void (algorithm::*)()>(nullptr));
265  }
266 
267  std::string name() const noexcept override {
268  return get_template_parameters_as_string<RegisterSimpleAction>();
269  }
270 
271  static bool registrar;
272 };
273 /// \endcond
274 
275 /*!
276  * \ingroup CharmExtensionsGroup
277  * \brief Derived class for registering threaded actions.
278  *
279  * Calls the appropriate Charm++ function to register a threaded action.
280  */
281 template <typename ParallelComponent, typename Action, typename... Args>
283  using chare_type = typename ParallelComponent::chare_type;
284  using charm_type = charm_types_with_parameters<
285  ParallelComponent,
286  typename get_array_index<chare_type>::template f<ParallelComponent>>;
287  using cproxy = typename charm_type::cproxy;
288  using ckindex = typename charm_type::ckindex;
289  using algorithm = typename charm_type::algorithm;
290 
291  RegisterThreadedAction() = default;
293  RegisterThreadedAction& operator=(const RegisterThreadedAction&) = default;
295  RegisterThreadedAction& operator=(RegisterThreadedAction&&) = default;
296  ~RegisterThreadedAction() override = default;
297 
298  void register_with_charm() const noexcept override {
299  static bool done_registration{false};
300  if (done_registration) {
301  return; // LCOV_EXCL_LINE
302  }
303  done_registration = true;
304  ckindex::template idx_threaded_action<Action>(
305  static_cast<void (algorithm::*)(const std::tuple<Args...>&)>(nullptr));
306  }
307 
308  std::string name() const noexcept override {
309  return get_template_parameters_as_string<RegisterThreadedAction>();
310  }
311 
312  static bool registrar;
313 };
314 
315 /// \cond
316 template <typename ParallelComponent, typename Action>
317 struct RegisterThreadedAction<ParallelComponent, Action> : RegistrationHelper {
318  using chare_type = typename ParallelComponent::chare_type;
319  using charm_type = charm_types_with_parameters<
320  ParallelComponent,
321  typename get_array_index<chare_type>::template f<ParallelComponent>>;
322  using cproxy = typename charm_type::cproxy;
323  using ckindex = typename charm_type::ckindex;
324  using algorithm = typename charm_type::algorithm;
325 
326  RegisterThreadedAction() = default;
328  RegisterThreadedAction& operator=(const RegisterThreadedAction&) = default;
330  RegisterThreadedAction& operator=(RegisterThreadedAction&&) = default;
331  ~RegisterThreadedAction() override = default;
332 
333  void register_with_charm() const noexcept override {
334  static bool done_registration{false};
335  if (done_registration) {
336  return; // LCOV_EXCL_LINE
337  }
338  done_registration = true;
339  ckindex::template idx_threaded_action<Action>(
340  static_cast<void (algorithm::*)()>(nullptr));
341  }
342 
343  std::string name() const noexcept override {
344  return get_template_parameters_as_string<RegisterThreadedAction>();
345  }
346 
347  static bool registrar;
348 };
349 /// \endcond
350 
351 namespace detail {
352 template <class T>
353 struct get_value_type;
354 
355 template <class Key, class Mapped, class Hash, class KeyEqual, class Allocator>
356 struct get_value_type<
357  std::unordered_map<Key, Mapped, Hash, KeyEqual, Allocator>> {
358  // When sending data it is typical to use `std::make_pair(a, b)` which results
359  // in a non-const Key type, which is different from what
360  // `unordered_map::value_type` is (e.g. `std::pair<const Key, Mapped>`). This
361  // difference leads to issues with function registration with Charm++ because
362  // when registering `receive_data` methods we register the `inbox_type`'s
363  // `value_type` (`std::pair<const Key, Mapped>` in this case), not the type
364  // passed to `receive_data`.
365  using type = std::pair<Key, Mapped>;
366 };
367 
368 template <size_t Size, class Key, class Mapped, class Hash, class KeyEqual>
369 struct get_value_type<FixedHashMap<Size, Key, Mapped, Hash, KeyEqual>> {
370  // When sending data it is typical to use `std::make_pair(a, b)` which results
371  // in a non-const Key type, which is different from what
372  // `FixedHashMap::value_type` is (e.g. `std::pair<const Key, Mapped>`). This
373  // difference leads to issues with function registration with Charm++ because
374  // when registering `receive_data` methods we register the `inbox_type`'s
375  // `value_type` (`std::pair<const Key, Mapped>` in this case), not the type
376  // passed to `receive_data`.
377  using type = std::pair<Key, Mapped>;
378 };
379 
380 template <class Key, class Hash, class KeyEqual, class Allocator>
381 struct get_value_type<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>> {
382  using type = Key;
383 };
384 
385 template <class T>
386 using get_value_type_t = typename get_value_type<T>::type;
387 } // namespace detail
388 
389 /*!
390  * \ingroup CharmExtensionsGroup
391  * \brief Derived class for registering receive_data functions
392  *
393  * Calls the appropriate Charm++ function to register a receive_data function.
394  * There is a bug in Charm++ that doesn't allow default values for entry method
395  * arguments for groups and nodegroups, so we have to handle the (node)group
396  * cases separately from the singleton and array cases.
397  */
398 template <typename ParallelComponent, typename ReceiveTag>
400  using chare_type = typename ParallelComponent::chare_type;
401  using charm_type = charm_types_with_parameters<
402  ParallelComponent,
403  typename get_array_index<chare_type>::template f<ParallelComponent>>;
404  using cproxy = typename charm_type::cproxy;
405  using ckindex = typename charm_type::ckindex;
406  using algorithm = typename charm_type::algorithm;
407 
408  RegisterReceiveData() = default;
409  RegisterReceiveData(const RegisterReceiveData&) = default;
410  RegisterReceiveData& operator=(const RegisterReceiveData&) = default;
412  RegisterReceiveData& operator=(RegisterReceiveData&&) = default;
413  ~RegisterReceiveData() override = default;
414 
415  void register_with_charm() const noexcept override {
416  static bool done_registration{false};
417  if (done_registration) {
418  return; // LCOV_EXCL_LINE
419  }
420  done_registration = true;
421  register_with_charm_helper(
425  }
426 
427  std::string name() const noexcept override {
428  return get_template_parameters_as_string<RegisterReceiveData>();
429  }
430 
431  static bool registrar;
432 
433  private:
434  void register_with_charm_helper(std::true_type /*not is_group*/) const
435  noexcept {
436  ckindex::template idx_receive_data<ReceiveTag>(
437  static_cast<void (algorithm::*)(
438  const typename ReceiveTag::temporal_id&,
439  const detail::get_value_type_t<
440  typename ReceiveTag::type::mapped_type>&,
441  bool)>(nullptr));
442  }
443  void register_with_charm_helper(std::false_type /*is_group*/) const noexcept {
444  ckindex::template idx_receive_data<ReceiveTag>(
445  static_cast<void (algorithm::*)(
446  const typename ReceiveTag::temporal_id&,
447  const typename std::decay<
448  typename ReceiveTag::type::mapped_type::value_type>::type&)>(
449  nullptr));
450  }
451 };
452 
453 /*!
454  * \ingroup CharmExtensionsGroup
455  * \brief Derived class for registering reduction actions
456  *
457  * Calls the appropriate Charm++ functions to register a reduction action.
458  */
459 template <typename ParallelComponent, typename Action, typename ReductionType>
461  using chare_type = typename ParallelComponent::chare_type;
462  using charm_type = charm_types_with_parameters<
463  ParallelComponent,
464  typename get_array_index<chare_type>::template f<ParallelComponent>>;
465  using cproxy = typename charm_type::cproxy;
466  using ckindex = typename charm_type::ckindex;
467  using algorithm = typename charm_type::algorithm;
468 
469  RegisterReductionAction() = default;
471  RegisterReductionAction& operator=(const RegisterReductionAction&) = default;
473  RegisterReductionAction& operator=(RegisterReductionAction&&) = default;
474  ~RegisterReductionAction() override = default;
475 
476  void register_with_charm() const noexcept override {
477  static bool done_registration{false};
478  if (done_registration) {
479  return; // LCOV_EXCL_LINE
480  }
481  done_registration = true;
482  ckindex::template idx_reduction_action<Action, ReductionType>(
483  static_cast<void (algorithm::*)(const ReductionType&)>(nullptr));
484  ckindex::template redn_wrapper_reduction_action<Action, ReductionType>(
485  nullptr);
486  }
487 
488  std::string name() const noexcept override {
489  return get_template_parameters_as_string<RegisterReductionAction>();
490  }
491 
492  static bool registrar;
493 };
494 
495 /*!
496  * \ingroup CharmExtensionsGroup
497  * \brief Function that adds a pointer to a specific derived class to the
498  * `charm_register_list`
499  *
500  * Used to initialize the `registrar` bool of derived classes of
501  * `RegistrationHelper`. When the function is invoked it appends the derived
502  * class to the `charm_register_list`.
503  *
504  * \note The reason for not using a `std::vector` is that this did not behave
505  * correctly when calling `push_back`. Specifically, the final vector was always
506  * size 1, even though multiple elements were pushed back. The reason for that
507  * behavior was never tracked down and so in the future it could be possible to
508  * use a `std::vector`.
509  */
510 template <typename Derived>
511 bool register_func_with_charm() noexcept {
512  if (charm_register_list_size >= charm_register_list_capacity) {
513  // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
514  // necessary)
515  auto* const t = // NOLINT
516  new std::unique_ptr<RegistrationHelper>[charm_register_list_capacity +
517  10];
518  for (size_t i = 0; i < charm_register_list_capacity; ++i) {
519  // clang-tidy: do not use pointer arithmetic
520  t[i] = std::move(charm_register_list[i]); // NOLINT
521  }
522  // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
523  // necessary)
524  delete[] charm_register_list; // NOLINT
525  charm_register_list = t;
526  charm_register_list_capacity += 10;
527  }
528  charm_register_list_size++;
529  // clang-tidy: do not use pointer arithmetic
530  charm_register_list[charm_register_list_size - 1] = // NOLINT
531  std::make_unique<Derived>();
532  return true;
533 }
534 } // namespace charmxx
535 } // namespace Parallel
536 
537 // clang-tidy: redundant declaration
538 template <typename ParallelComponent>
540  ParallelComponent>::registrar = // NOLINT
543 
544 // clang-tidy: redundant declaration
545 template <typename Chare, typename CkIndex>
549 
550 // clang-tidy: redundant declaration
551 template <typename ParallelComponent, typename Action, typename... Args>
552 bool Parallel::charmxx::RegisterSimpleAction<ParallelComponent, Action,
553  Args...>::registrar = // NOLINT
555  RegisterSimpleAction<ParallelComponent, Action, Args...>>();
556 
557 // clang-tidy: redundant declaration
558 template <typename ParallelComponent, typename Action>
559 bool Parallel::charmxx::RegisterSimpleAction<ParallelComponent,
560  Action>::registrar = // NOLINT
563 
564 // clang-tidy: redundant declaration
565 template <typename ParallelComponent, typename Action, typename... Args>
566 bool Parallel::charmxx::RegisterThreadedAction<ParallelComponent, Action,
567  Args...>::registrar = // NOLINT
569  RegisterThreadedAction<ParallelComponent, Action, Args...>>();
570 
571 // clang-tidy: redundant declaration
572 template <typename ParallelComponent, typename Action>
573 bool Parallel::charmxx::RegisterThreadedAction<ParallelComponent,
574  Action>::registrar = // NOLINT
577 
578 // clang-tidy: redundant declaration
579 template <typename ParallelComponent, typename ReceiveTag>
580 bool Parallel::charmxx::RegisterReceiveData<ParallelComponent,
581  ReceiveTag>::registrar = // NOLINT
584 
585 // clang-tidy: redundant declaration
586 template <typename ParallelComponent, typename Action, typename ReductionType>
588  ParallelComponent, Action, ReductionType>::registrar = // NOLINT
591 
592 /// \cond
593 class CkReductionMsg;
594 /// \endcond
595 
596 namespace Parallel {
597 namespace charmxx {
598 /*!
599  * \ingroup CharmExtensionsGroup
600  * \brief The type of a function pointer to a Charm++ custom reduction function.
601  */
602 using ReducerFunctions = CkReductionMsg* (*)(int, CkReductionMsg**);
603 /// \cond
604 extern ReducerFunctions* charm_reducer_functions_list;
605 extern size_t charm_reducer_functions_capacity;
606 extern size_t charm_reducer_functions_size;
608  charm_reducer_functions;
609 /// \endcond
610 
611 /*!
612  * \ingroup CharmExtensionsGroup
613  * \brief Class used for registering custom reduction function
614  *
615  * The static member variable is initialized before main is entered. This means
616  * we are able to inject code into the beginning of the execution of an
617  * executable by "using" the variable (casting to void counts) the function that
618  * initializes the variable is called. We "use" `registrar` inside the
619  * `Parallel::contribute_to_reduction` function.
620  */
621 template <ReducerFunctions>
623  static bool registrar;
624 };
625 
626 /*!
627  * \ingroup CharmExtensionsGroup
628  * \brief Function that stores a function pointer to the custom reduction
629  * function to be registered later.
630  *
631  * Used to initialize the `registrar` bool of `RegisterReducerFunction`. When
632  * invoked it adds the function `F` of type `ReducerFunctions` to the list
633  * `charm_reducer_functions_list`.
634  *
635  * \note The reason for not using a `std::vector<ReducerFunctions>` is that this
636  * did not behave correctly when calling `push_back`. Specifically, the final
637  * vector was always size 1, even though multiple elements were pushed back. The
638  * reason for that behavior was never tracked down and so in the future it could
639  * be possible to use a `std::vector`.
640  */
641 template <ReducerFunctions F>
642 bool register_reducer_function() noexcept {
643  if (charm_reducer_functions_size >= charm_reducer_functions_capacity) {
644  // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
645  // necessary)
646  auto* const t = // NOLINT
647  new ReducerFunctions[charm_reducer_functions_capacity + 10];
648  for (size_t i = 0; i < charm_reducer_functions_capacity; ++i) {
649  // clang-tidy: do not use pointer arithmetic
650  t[i] = std::move(charm_reducer_functions_list[i]); // NOLINT
651  }
652  // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
653  // necessary)
654  delete[] charm_reducer_functions_list; // NOLINT
655  charm_reducer_functions_list = t;
656  charm_reducer_functions_capacity += 10;
657  }
658  charm_reducer_functions_size++;
659  // clang-tidy: do not use pointer arithmetic
660  charm_reducer_functions_list[charm_reducer_functions_size - 1] = F; // NOLINT
661  return true;
662 }
663 } // namespace charmxx
664 } // namespace Parallel
665 
666 // clang-tidy: do not use pointer arithmetic
667 template <Parallel::charmxx::ReducerFunctions F>
669  Parallel::charmxx::register_reducer_function<F>();
Derived class for registering receive_data functions.
Definition: CharmRegistration.hpp:399
Defines type traits related to Charm++ types.
A hash table with a compile-time specified maximum size and ability to efficiently handle perfect has...
Definition: FixedHashMap.hpp:81
Class to mark a constructor as a constructor for the main chare.
Definition: CharmRegistration.hpp:34
Contains functions that forward to Charm++ parallel functions.
Definition: Abort.hpp:13
Check if T is a Charm++ proxy for a group chare.
Definition: TypeTraits.hpp:29
Derived class for registering simple actions.
Definition: CharmRegistration.hpp:206
CkReductionMsg *(*)(int, CkReductionMsg **) ReducerFunctions
The type of a function pointer to a Charm++ custom reduction function.
Definition: CharmRegistration.hpp:602
Derived class for registering threaded actions.
Definition: CharmRegistration.hpp:282
std::string get_template_parameters_as_string()
Returns the template parameter as a std::string
Definition: CharmRegistration.hpp:53
Check if T is a Charm++ proxy for a node group chare.
Definition: TypeTraits.hpp:34
Definition: Determinant.hpp:11
Derived class for registering parallel components.
Definition: CharmRegistration.hpp:116
bool register_func_with_charm() noexcept
Function that adds a pointer to a specific derived class to the charm_register_list ...
Definition: CharmRegistration.hpp:511
bool register_reducer_function() noexcept
Function that stores a function pointer to the custom reduction function to be registered later...
Definition: CharmRegistration.hpp:642
Derived class for registering chares.
Definition: CharmRegistration.hpp:172
Class used for registering custom reduction function.
Definition: CharmRegistration.hpp:622
Derived class for registering reduction actions.
Definition: CharmRegistration.hpp:460
The base class used for automatic registration of entry methods.
Definition: CharmRegistration.hpp:96