Invoke.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <type_traits>
8 #include <utility>
9 
10 #include "Parallel/TypeTraits.hpp"
11 #include "Utilities/Requires.hpp"
12 
13 namespace Parallel {
14 namespace detail {
15 // Allow 64 inline entry method calls before we fall back to Charm++. This is
16 // done to avoid blowing the stack.
17 inline bool max_inline_entry_methods_reached() noexcept {
18  thread_local size_t approx_stack_depth = 0;
19  approx_stack_depth++;
20  if (approx_stack_depth < 64) {
21  return false;
22  }
23  approx_stack_depth = 0;
24  return true;
25 }
26 
27 template <typename T, typename = cpp17::void_t<>>
28 struct has_ckLocal_method : std::false_type {};
29 
30 template <typename T>
31 struct has_ckLocal_method<T,
32  cpp17::void_t<decltype(std::declval<T>().ckLocal())>>
33  : std::true_type {};
34 } // namespace detail
35 
36 // @{
37 /*!
38  * \ingroup ParallelGroup
39  * \brief Send the data `args...` to the algorithm running on `proxy`, and tag
40  * the message with the identifier `temporal_id`.
41  *
42  * If the algorithm was previously disabled, set `enable_if_disabled` to true to
43  * enable the algorithm on the parallel component.
44  *
45  * \note The reason there are two separate functions is because Charm++ does not
46  * allow defaulted arguments for group and nodegroup chares.
47  */
48 template <
49  typename ReceiveTag, typename Proxy, typename ReceiveDataType,
51 void receive_data(Proxy&& proxy, typename ReceiveTag::temporal_id temporal_id,
52  ReceiveDataType&& receive_data,
53  const bool enable_if_disabled) noexcept {
54  auto* obj = proxy.ckLocal();
55  // Only elide the Charm++ RTS if the object is local and if we won't blow the
56  // stack by having too many recursive function calls.
57  if (obj != nullptr and not detail::max_inline_entry_methods_reached()) {
58  obj->template receive_data<ReceiveTag>(
59  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data),
60  enable_if_disabled);
61  } else {
62  proxy.template receive_data<ReceiveTag>(
63  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data),
64  enable_if_disabled);
65  }
66 }
67 
68 template <
69  typename ReceiveTag, typename Proxy, typename ReceiveDataType,
71 void receive_data(Proxy&& proxy, typename ReceiveTag::temporal_id temporal_id,
72  ReceiveDataType&& receive_data) noexcept {
73  auto* obj = proxy.ckLocal();
74  // Only elide the Charm++ RTS if the object is local and if we won't blow the
75  // stack by having too many recursive function calls.
76  if (obj != nullptr and not detail::max_inline_entry_methods_reached()) {
77  obj->template receive_data<ReceiveTag>(
78  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data));
79  } else {
80  proxy.template receive_data<ReceiveTag>(
81  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data));
82  }
83 }
84 
85 template <typename ReceiveTag, typename Proxy, typename ReceiveDataType,
87  nullptr>
88 void receive_data(Proxy&& proxy, typename ReceiveTag::temporal_id temporal_id,
89  ReceiveDataType&& receive_data,
90  const bool enable_if_disabled) noexcept {
91  proxy.template receive_data<ReceiveTag>(
92  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data),
93  enable_if_disabled);
94 }
95 
96 template <typename ReceiveTag, typename Proxy, typename ReceiveDataType,
98  nullptr>
99 void receive_data(Proxy&& proxy, typename ReceiveTag::temporal_id temporal_id,
100  ReceiveDataType&& receive_data) noexcept {
101  proxy.template receive_data<ReceiveTag>(
102  std::move(temporal_id), std::forward<ReceiveDataType>(receive_data));
103 }
104 // @}
105 
106 // @{
107 /*!
108  * \ingroup ParallelGroup
109  * \brief Invoke a simple action on `proxy`
110  */
111 template <typename Action, typename Proxy>
112 void simple_action(Proxy&& proxy) noexcept {
113  proxy.template simple_action<Action>();
114 }
115 
116 template <typename Action, typename Proxy, typename Arg0, typename... Args>
117 void simple_action(Proxy&& proxy, Arg0&& arg0, Args&&... args) noexcept {
118  proxy.template simple_action<Action>(
120  std::forward<Arg0>(arg0), std::forward<Args>(args)...));
121 }
122 // @}
123 
124 // @{
125 /*!
126  * \ingroup ParallelGroup
127  * \brief Invoke a threaded action on `proxy`, where the proxy must be a
128  * nodegroup.
129  */
130 template <typename Action, typename Proxy>
131 void threaded_action(Proxy&& proxy) noexcept {
132  proxy.template threaded_action<Action>();
133 }
134 
135 template <typename Action, typename Proxy, typename Arg0, typename... Args>
136 void threaded_action(Proxy&& proxy, Arg0&& arg0, Args&&... args) noexcept {
137  proxy.template threaded_action<Action>(
139  std::forward<Arg0>(arg0), std::forward<Args>(args)...));
140 }
141 // @}
142 } // namespace Parallel
void threaded_action(Proxy &&proxy) noexcept
Invoke a threaded action on proxy, where the proxy must be a nodegroup.
Definition: Invoke.hpp:131
void receive_data(Proxy &&proxy, typename ReceiveTag::temporal_id temporal_id, ReceiveDataType &&receive_data, const bool enable_if_disabled) noexcept
Send the data args... to the algorithm running on proxy, and tag the message with the identifier temp...
Definition: Invoke.hpp:51
Defines type traits related to Charm++ types.
void void_t
Given a set of types, returns void
Definition: TypeTraits.hpp:214
Contains functions that forward to Charm++ parallel functions.
Definition: Abort.hpp:13
Defines the type alias Requires.
Definition: Determinant.hpp:11
void simple_action(Proxy &&proxy) noexcept
Invoke a simple action on proxy
Definition: Invoke.hpp:112
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
C++ STL code present in C++17.
Definition: Array.hpp:16