Blender V5.0
BLI_concurrent_map.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#ifdef WITH_TBB
10/* Quiet top level deprecation message, unrelated to API usage here. */
11# if defined(WIN32) && !defined(NOMINMAX)
12/* TBB includes Windows.h which will define min/max macros causing issues
13 * when we try to use std::min and std::max later on. */
14# define NOMINMAX
15# define TBB_MIN_MAX_CLEANUP
16# endif
17# include <tbb/concurrent_hash_map.h>
18# ifdef WIN32
19/* We cannot keep this defined, since other parts of the code deal with this on their own, leading
20 * to multiple define warnings unless we un-define this, however we can only undefine this if we
21 * were the ones that made the definition earlier. */
22# ifdef TBB_MIN_MAX_CLEANUP
23# undef NOMINMAX
24# endif
25# endif
26#else
27# include "BLI_mutex.hh"
28# include "BLI_set.hh"
29#endif
30
31#include "BLI_hash.hh"
32#include "BLI_hash_tables.hh"
33
34namespace blender {
35
51template<typename Key,
52 typename Value,
53 typename Hash = DefaultHash<Key>,
54 typename IsEqual = DefaultEquality<Key>>
56 public:
58
59 /* Sometimes TBB requires the value to be constructible. */
60 static_assert(std::is_copy_constructible_v<Value>);
61
62#ifdef WITH_TBB
63 private:
64 struct Hasher {
65 template<typename T> size_t hash(const T &value) const
66 {
67 return Hash{}(value);
68 }
69
70 template<typename T1, typename T2> bool equal(const T1 &a, const T2 &b) const
71 {
72 return IsEqual{}(a, b);
73 }
74 };
75
76 using TBBMap = tbb::concurrent_hash_map<Key, Value, Hasher>;
77 TBBMap map_;
78
79 public:
80 using MutableAccessor = typename TBBMap::accessor;
81 using ConstAccessor = typename TBBMap::const_accessor;
82
90 bool lookup(MutableAccessor &accessor, const Key &key)
91 {
92 return map_.find(accessor, key);
93 }
94
99 bool lookup(ConstAccessor &accessor, const Key &key)
100 {
101 return map_.find(accessor, key);
102 }
103
108 bool add(MutableAccessor &accessor, const Key &key)
109 {
110 return map_.insert(accessor, key);
111 }
112
113 bool add(ConstAccessor &accessor, const Key &key)
114 {
115 return map_.insert(accessor, key);
116 }
117
122 bool remove(const Key &key)
123 {
124 return map_.erase(key);
125 }
126
127#else
128 private:
133 struct SetKey {
134 std::pair<Key, Value> item;
135
136 SetKey(Key key) : item(std::move(key), Value()) {}
137
138 uint64_t hash() const
139 {
140 return Hash{}(this->item.first);
141 }
142
143 static uint64_t hash_as(const Key &key)
144 {
145 return Hash{}(key);
146 }
147
148 friend bool operator==(const SetKey &a, const SetKey &b)
149 {
150 return IsEqual{}(a.item.first, b.item.first);
151 }
152
153 friend bool operator==(const Key &a, const SetKey &b)
154 {
155 return IsEqual{}(a, b.item.first);
156 }
157
158 friend bool operator==(const SetKey &a, const Key &b)
159 {
160 return IsEqual{}(a.item.first, b);
161 }
162 };
163
164 using UsedSet = Set<SetKey>;
165
166 struct Accessor {
167 std::unique_lock<Mutex> mutex;
168 std::pair<Key, Value> *data = nullptr;
169
170 std::pair<Key, Value> *operator->()
171 {
172 return this->data;
173 }
174 };
175
176 Mutex mutex_;
177 UsedSet set_;
178
179 public:
180 using MutableAccessor = Accessor;
181 using ConstAccessor = Accessor;
182
183 bool lookup(Accessor &accessor, const Key &key)
184 {
185 accessor.mutex = std::unique_lock(mutex_);
186 SetKey *stored_key = const_cast<SetKey *>(set_.lookup_key_ptr_as(key));
187 if (!stored_key) {
188 return false;
189 }
190 accessor.data = &stored_key->item;
191 return true;
192 }
193
194 bool add(Accessor &accessor, const Key &key)
195 {
196 accessor.mutex = std::unique_lock(mutex_);
197 const bool newly_added = !set_.contains_as(key);
198 SetKey &stored_key = const_cast<SetKey &>(set_.lookup_key_or_add_as(key));
199 accessor.data = &stored_key.item;
200 return newly_added;
201 }
202
203 bool remove(const Key &key)
204 {
205 std::unique_lock lock(mutex_);
206 return set_.remove_as(key);
207 }
208
209#endif
210};
211
212} // namespace blender
struct Key Key
volatile int lock
long long int int64_t
unsigned long long int uint64_t
bool lookup(Accessor &accessor, const Key &key)
bool remove(const Key &key)
bool add(Accessor &accessor, const Key &key)
VecBase< bool, D > equal(VecOp< T, D >, VecOp< T, D >) RET
#define T
#define T2
Definition md5.cpp:21
#define T1
Definition md5.cpp:20
std::mutex Mutex
Definition BLI_mutex.hh:47
#define hash
Definition noise_c.cc:154