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 bool 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 : return true; 55 : } 56 : }; 57 : 58 : /*! 59 : * \brief Inserter for inserting data that is received as the `value_type` of a 60 : * data structure that has an `insert(value_type&&)` member function. 61 : * 62 : * Can be used for receiving data into data structures like 63 : * `std::(unordered_)multiset`. 64 : * 65 : * \snippet Test_InboxInserters.cpp member insert tag 66 : */ 67 : template <typename InboxTag> 68 1 : struct MemberInsert { 69 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 70 0 : static bool insert_into_inbox(const gsl::not_null<Inbox*> inbox, 71 : const TemporalId& temporal_id, 72 : ReceiveDataType&& data) { 73 : static_assert(std::is_same<std::decay_t<TemporalId>, 74 : typename InboxTag::temporal_id>::value, 75 : "The temporal_id of the inbox tag does not match the " 76 : "received temporal id."); 77 : (*inbox)[temporal_id].insert(std::forward<ReceiveDataType>(data)); 78 : return true; 79 : } 80 : }; 81 : 82 : /*! 83 : * \brief Inserter for data that is inserted by copy/move. 84 : * 85 : * \snippet Test_InboxInserters.cpp value tag 86 : */ 87 : template <typename InboxTag> 88 1 : struct Value { 89 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 90 0 : static bool insert_into_inbox(const gsl::not_null<Inbox*> inbox, 91 : const TemporalId& temporal_id, 92 : ReceiveDataType&& data) { 93 : static_assert(std::is_same<std::decay_t<TemporalId>, 94 : typename InboxTag::temporal_id>::value, 95 : "The temporal_id of the inbox tag does not match the " 96 : "received temporal id."); 97 : (*inbox)[temporal_id] = std::forward<ReceiveDataType>(data); 98 : return true; 99 : } 100 : }; 101 : 102 : /*! 103 : * \brief Inserter for inserting data that is received as the `value_type` of a 104 : * data structure that has an `push_back(value_type&&)` member function. 105 : * 106 : * Can be used for receiving data into data structures like 107 : * `std::vector`. 108 : * 109 : * \snippet Test_InboxInserters.cpp pushback tag 110 : */ 111 : template <typename InboxTag> 112 1 : struct Pushback { 113 : template <typename Inbox, typename TemporalId, typename ReceiveDataType> 114 0 : static bool insert_into_inbox(const gsl::not_null<Inbox*> inbox, 115 : const TemporalId& temporal_id, 116 : ReceiveDataType&& data) { 117 : static_assert(std::is_same<std::decay_t<TemporalId>, 118 : typename InboxTag::temporal_id>::value, 119 : "The temporal_id of the inbox tag does not match the " 120 : "received temporal id."); 121 : (*inbox)[temporal_id].push_back(std::forward<ReceiveDataType>(data)); 122 : return true; 123 : } 124 : }; 125 : } // namespace InboxInserters 126 : } // namespace Parallel