Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <type_traits> 7 : #include <utility> 8 : 9 : #include "Utilities/ErrorHandling/Assert.hpp" 10 : #include "Utilities/ErrorHandling/Error.hpp" 11 : #include "Utilities/Gsl.hpp" 12 : #include "Utilities/PrettyType.hpp" 13 : 14 : namespace Parallel { 15 : /// \ingroup ParallelGroup 16 : /// \brief Structs that have `insert_into_inbox` methods for commonly used 17 : /// cases. 18 : /// 19 : /// Inbox tags can inherit from the inserters to gain the `insert_into_inbox` 20 : /// static method used by the parallel infrastructure to store data in the 21 : /// inboxes. Collected in the `InboxInserters` namespace are implementations for 22 : /// the most common types of data sent that one may encounter. 23 1 : namespace InboxInserters { 24 : /*! 25 : * \brief Inserter for inserting data that is received as the `value_type` (with 26 : * non-const `key_type`) of a map data structure. 27 : * 28 : * An example would be a `std::unordered_map<int, int>`, where the first `int` 29 : * is the "spatial" id of the parallel component array. The data type that is 30 : * sent to the component would be a `std::pair<int, int>`, or more generally a 31 : * `std::pair<key_type, mapped_type>`. The inbox tag would be: 32 : * 33 : * \snippet Test_InboxInserters.cpp map tag 34 : */ 35 : template <typename InboxTag> 36 1 : struct Map { 37 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 38 0 : static void insert_into_inbox(const gsl::not_null<Inbox*> inbox, 39 : const TemporalId& temporal_id, 40 : ReceiveDataType&& data) { 41 : static_assert(std::is_same<std::decay_t<TemporalId>, 42 : typename InboxTag::temporal_id>::value, 43 : "The temporal_id of the inbox tag does not match the " 44 : "received temporal id."); 45 : auto& current_inbox = (*inbox)[temporal_id]; 46 : ASSERT(0 == current_inbox.count(data.first), 47 : "Receiving data from the 'same' source twice. The message id is: " 48 : << data.first); 49 : if (not current_inbox.insert(std::forward<ReceiveDataType>(data)).second) { 50 : ERROR("Failed to insert data to receive at instance '" 51 : << temporal_id << "' with tag '" 52 : << pretty_type::get_name<InboxTag>() << "'.\n"); 53 : } 54 : } 55 : }; 56 : 57 : /*! 58 : * \brief Inserter for inserting data that is received as the `value_type` of a 59 : * data structure that has an `insert(value_type&&)` member function. 60 : * 61 : * Can be used for receiving data into data structures like 62 : * `std::(unordered_)multiset`. 63 : * 64 : * \snippet Test_InboxInserters.cpp member insert tag 65 : */ 66 : template <typename InboxTag> 67 1 : struct MemberInsert { 68 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 69 0 : static void insert_into_inbox(const gsl::not_null<Inbox*> inbox, 70 : const TemporalId& temporal_id, 71 : ReceiveDataType&& data) { 72 : static_assert(std::is_same<std::decay_t<TemporalId>, 73 : typename InboxTag::temporal_id>::value, 74 : "The temporal_id of the inbox tag does not match the " 75 : "received temporal id."); 76 : (*inbox)[temporal_id].insert(std::forward<ReceiveDataType>(data)); 77 : } 78 : }; 79 : 80 : /*! 81 : * \brief Inserter for data that is inserted by copy/move. 82 : * 83 : * \snippet Test_InboxInserters.cpp value tag 84 : */ 85 : template <typename InboxTag> 86 1 : struct Value { 87 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 88 0 : static void insert_into_inbox(const gsl::not_null<Inbox*> inbox, 89 : const TemporalId& temporal_id, 90 : ReceiveDataType&& data) { 91 : static_assert(std::is_same<std::decay_t<TemporalId>, 92 : typename InboxTag::temporal_id>::value, 93 : "The temporal_id of the inbox tag does not match the " 94 : "received temporal id."); 95 : (*inbox)[temporal_id] = std::forward<ReceiveDataType>(data); 96 : } 97 : }; 98 : 99 : /*! 100 : * \brief Inserter for inserting data that is received as the `value_type` of a 101 : * data structure that has an `push_back(value_type&&)` member function. 102 : * 103 : * Can be used for receiving data into data structures like 104 : * `std::vector`. 105 : * 106 : * \snippet Test_InboxInserters.cpp pushback tag 107 : */ 108 : template <typename InboxTag> 109 1 : struct Pushback { 110 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 111 0 : static void insert_into_inbox(const gsl::not_null<Inbox*> inbox, 112 : const TemporalId& temporal_id, 113 : ReceiveDataType&& data) { 114 : static_assert(std::is_same<std::decay_t<TemporalId>, 115 : typename InboxTag::temporal_id>::value, 116 : "The temporal_id of the inbox tag does not match the " 117 : "received temporal id."); 118 : (*inbox)[temporal_id].push_back(std::forward<ReceiveDataType>(data)); 119 : } 120 : }; 121 : } // namespace InboxInserters 122 : } // namespace Parallel