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