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
|