My Project
Loading...
Searching...
No Matches
ThreadSafeMapBuilder.hpp
1/*
2 This file is part of the Open Porous Media project (OPM).
3
4 Copyright 2025 SINTEF Digital
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
23#ifndef OPM_THREAD_SAFE_MAP_BUILDER_HPP
24#define OPM_THREAD_SAFE_MAP_BUILDER_HPP
25
26#include <algorithm>
27#include <cassert>
28#include <cstddef>
29#include <list>
30#include <map>
31#include <numeric>
32#include <vector>
33
34#if _OPENMP
35#include <omp.h>
36#endif
37
38namespace Opm {
39
53
56 Emplace, // Use first inserted value encountered
57 Insert_Or_Assign // Use last inserted value encountered (last thread wins)
58};
59
60template<class Map>
62{
64 template<class T>
65 struct is_ordered
66 {
67 constexpr static bool value = false;
68 };
69
70 template<class Key, class T, class Compare, class Allocator>
71 struct is_ordered<std::map<Key,T,Compare,Allocator>>
72 {
73 constexpr static bool value = true;
74 };
75
76public:
77 using Key = typename Map::key_type;
78 using Value = typename Map::mapped_type;
79
81 ThreadSafeMapBuilder(Map& map, const int num_threads,
82 const MapBuilderInsertionMode mode)
83 : map_(map), num_threads_(num_threads), mode_(mode)
84 {
85 if (num_threads_ > 1) {
86 thread_values_.resize(num_threads_);
87 }
88 }
89
95
97 template<class M>
98 void insert_or_assign(const Key& key, M&& value)
99 {
100 assert(mode_ == MapBuilderInsertionMode::Insert_Or_Assign);
101#if _OPENMP
102 if (num_threads_ > 1) {
103 thread_values_[omp_get_thread_num()].
104 emplace_back(key, std::forward<M>(value));
105 } else
106#endif // _OPENMP
107 {
108 map_.insert_or_assign(key, std::forward<M>(value));
109 }
110 }
111
113 template<class... Args>
114 void emplace(Args&&... args)
115 {
116 assert(mode_ == MapBuilderInsertionMode::Emplace);
117#if _OPENMP
118 if (num_threads_ > 1) {
119 thread_values_[omp_get_thread_num()].
120 emplace_back(std::forward<Args>(args)...);
121 } else
122#endif // _OPENMP
123 {
124 map_.emplace(std::forward<Args>(args)...);
125 }
126 }
127
129 void finalize()
130 {
131 if (num_threads_ > 1 && !thread_values_.empty()) {
132 if constexpr (!is_ordered<Map>::value) {
133 const std::size_t size =
134 std::accumulate(thread_values_.begin(),
135 thread_values_.end(), std::size_t(0),
136 [](std::size_t s, const auto& v) { return s + v.size(); });
137 map_.reserve(size);
138 }
139 for (int i = 0; i < num_threads_; ++i) {
140 for (const auto& it : thread_values_[i]) {
141 if (mode_== MapBuilderInsertionMode::Insert_Or_Assign) {
142 map_.insert_or_assign(std::move(it.first), std::move(it.second));
143 } else {
144 map_.emplace(std::move(it.first), std::move(it.second));
145 }
146 }
147 }
148 }
149 thread_values_.clear();
150 }
151
152private:
153 std::vector<std::list<std::pair<Key,Value>>> thread_values_;
154 Map& map_;
155 int num_threads_;
157};
158
159}
160
161#endif // OPM_THREAD_SAFE_MAP_BUILDER_HPP
Definition ThreadSafeMapBuilder.hpp:62
~ThreadSafeMapBuilder()
The destructor (optionally) assembles the final map.
Definition ThreadSafeMapBuilder.hpp:91
void insert_or_assign(const Key &key, M &&value)
Insert a value into the map.
Definition ThreadSafeMapBuilder.hpp:98
ThreadSafeMapBuilder(Map &map, const int num_threads, const MapBuilderInsertionMode mode)
Constructor for a given map and number of threads.
Definition ThreadSafeMapBuilder.hpp:81
void emplace(Args &&... args)
Insert a value into the map.
Definition ThreadSafeMapBuilder.hpp:114
void finalize()
Assembles the final map.
Definition ThreadSafeMapBuilder.hpp:129
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30
MapBuilderInsertionMode
Utility class for adding multi-threading to loops that are building maps.
Definition ThreadSafeMapBuilder.hpp:55