Line data Source code
1 0 : // 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/Local.hpp"
11 : #include "Parallel/MaxInlineMethodsReached.hpp"
12 : #include "Parallel/TypeTraits.hpp"
13 :
14 : namespace Parallel {
15 : /*!
16 : * \ingroup ParallelGroup
17 : * \brief Send the data `args...` to the algorithm running on `proxy`, and tag
18 : * the message with the identifier `temporal_id`.
19 : *
20 : * If the algorithm was previously disabled, set `enable_if_disabled` to true to
21 : * enable the algorithm on the parallel component.
22 : */
23 : template <typename ReceiveTag, typename Proxy, typename ReceiveDataType>
24 1 : void receive_data(Proxy&& proxy, typename ReceiveTag::temporal_id temporal_id,
25 : ReceiveDataType&& receive_data,
26 : const bool enable_if_disabled = false) {
27 : // Both branches of this if statement call into the charm proxy system, but
28 : // because we specify [inline] for array chares, we must specify the
29 : // `ReceiveDataType` explicitly in the template arguments when dispatching to
30 : // array chares.
31 : // This is required because of inconsistent overloads in the generated charm++
32 : // files when [inline] is specified vs when it is not. The [inline] version
33 : // generates a function signature with template parameters associated with
34 : // each function argument, ensuring a redundant template parameter for the
35 : // `ReceiveDataType`. Then, that template parameter cannot be inferred so must
36 : // be explicitly specified.
37 : if constexpr (is_array_proxy<std::decay_t<Proxy>>::value) {
38 : proxy.template receive_data<ReceiveTag, std::decay_t<ReceiveDataType>>(
39 : std::move(temporal_id), std::forward<ReceiveDataType>(receive_data),
40 : enable_if_disabled);
41 : } else {
42 : proxy.template receive_data<ReceiveTag>(
43 : std::move(temporal_id), std::forward<ReceiveDataType>(receive_data),
44 : enable_if_disabled);
45 : }
46 : }
47 :
48 : /*!
49 : * \ingroup ParallelGroup
50 : * \brief Send a pointer `message` to the algorithm running on `proxy`.
51 : *
52 : * Here, `message` should hold all the information you need as member variables
53 : * of the object. This includes, temporal ID identifiers, the data itself, and
54 : * any auxilary information that needs to be communicated. The `ReceiveTag`
55 : * associated with this `message` should be able unpack the information that was
56 : * sent.
57 : *
58 : * If the component associated with the `proxy` you are calling this on is
59 : * running on the same charm-node, the exact pointer `message` is sent to the
60 : * receiving component. No copies of data are done. If the receiving component
61 : * is on a different charm-node, then the data pointed to by `message` is
62 : * copied, sent through charm, and unpacked on the receiving component. The
63 : * pointer that is passed to the algorithm on the receiving component then
64 : * points to the copied data on the receiving component.
65 : *
66 : * \warning You cannot use the `message` pointer after you call this function.
67 : * Doing so will result in undefined behavior because something else may be
68 : * controlling the pointer.
69 : */
70 : template <typename ReceiveTag, typename Proxy, typename MessageType>
71 1 : void receive_data(Proxy&& proxy, MessageType* message) {
72 : static_assert(is_array_proxy<std::decay_t<Proxy>>::value or
73 : is_array_element_proxy<std::decay_t<Proxy>>::value,
74 : "Charm++ messages can only be used with Array[Element] chares "
75 : "at the moment. If you want to use them with other types of "
76 : "components, you will need to implement it.");
77 : proxy.template receive_data<ReceiveTag, std::decay_t<MessageType>>(message);
78 : }
79 :
80 : /// @{
81 : /*!
82 : * \ingroup ParallelGroup
83 : * \brief Invoke a simple action on `proxy`
84 : */
85 : template <typename Action, typename Proxy>
86 1 : void simple_action(Proxy&& proxy) {
87 : proxy.template simple_action<Action>();
88 : }
89 :
90 : template <typename Action, typename Proxy, typename Arg0, typename... Args>
91 1 : void simple_action(Proxy&& proxy, Arg0&& arg0, Args&&... args) {
92 : proxy.template simple_action<Action, std::decay_t<Arg0>,
93 : std::decay_t<Args>...>(
94 : std::tuple<std::decay_t<Arg0>, std::decay_t<Args>...>(
95 : std::forward<Arg0>(arg0), std::forward<Args>(args)...));
96 : }
97 : /// @}
98 :
99 : /*!
100 : * \ingroup ParallelGroup
101 : * \brief Invoke a local synchronous action on `proxy`
102 : */
103 : template <typename Action, typename Proxy, typename... Args>
104 1 : decltype(auto) local_synchronous_action(Proxy&& proxy, Args&&... args) {
105 : return Parallel::local_branch(proxy)
106 : ->template local_synchronous_action<Action>(std::forward<Args>(args)...);
107 : }
108 :
109 : /// @{
110 : /*!
111 : * \ingroup ParallelGroup
112 : * \brief Invoke a threaded action on `proxy`, where the proxy must be a
113 : * nodegroup.
114 : */
115 : template <typename Action, typename Proxy>
116 1 : void threaded_action(Proxy&& proxy) {
117 : proxy.template threaded_action<Action>();
118 : }
119 :
120 : template <typename Action, typename Proxy, typename Arg0, typename... Args>
121 1 : void threaded_action(Proxy&& proxy, Arg0&& arg0, Args&&... args) {
122 : proxy.template threaded_action<Action>(
123 : std::tuple<std::decay_t<Arg0>, std::decay_t<Args>...>(
124 : std::forward<Arg0>(arg0), std::forward<Args>(args)...));
125 : }
126 : /// @}
127 : } // namespace Parallel
|