InboxInserters.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <type_traits>
7 #include <utility>
8 
10 #include "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 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 struct Map {
37  template <typename Inbox, typename TemporalId, typename ReceiveDataType>
38  static void insert_into_inbox(const gsl::not_null<Inbox*> inbox,
39  const TemporalId& temporal_id,
40  ReceiveDataType&& data) noexcept {
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 struct MemberInsert {
68  template <typename Inbox, typename TemporalId, typename ReceiveDataType>
69  static void insert_into_inbox(const gsl::not_null<Inbox*> inbox,
70  const TemporalId& temporal_id,
71  ReceiveDataType&& data) noexcept {
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 struct Value {
87  template <typename Inbox, typename TemporalId, typename ReceiveDataType>
88  static void insert_into_inbox(const gsl::not_null<Inbox*> inbox,
89  const TemporalId& temporal_id,
90  ReceiveDataType&& data) noexcept {
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 struct Pushback {
110  template <typename Inbox, typename TemporalId, typename ReceiveDataType>
111  static void insert_into_inbox(const gsl::not_null<Inbox*> inbox,
112  const TemporalId& temporal_id,
113  ReceiveDataType&& data) noexcept {
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
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:36
Inserter for inserting data that is received as the value_type (with non-const key_type) of a map dat...
Definition: InboxInserters.hpp:36
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:51
Contains functions that forward to Charm++ parallel functions.
Definition: Abort.hpp:13
Inserter for inserting data that is received as the value_type of a data structure that has an push_b...
Definition: InboxInserters.hpp:109
Inserter for data that is inserted by copy/move.
Definition: InboxInserters.hpp:86
Defines macro ASSERT.
Contains a pretty_type library to write types in a "pretty" format.
Defines functions and classes from the GSL.
Inserter for inserting data that is received as the value_type of a data structure that has an insert...
Definition: InboxInserters.hpp:67
Defines macro ERROR.
Require a pointer to not be a nullptr
Definition: Gsl.hpp:182