Blender  V2.93
BLI_map_slots.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
37 #include "BLI_memory_utils.hh"
38 
39 namespace blender {
40 
41 template<typename Src1, typename Src2, typename Dst1, typename Dst2>
42 void initialize_pointer_pair(Src1 &&src1, Src2 &&src2, Dst1 *dst1, Dst2 *dst2)
43 {
44  new ((void *)dst1) Dst1(std::forward<Src1>(src1));
45  try {
46  new ((void *)dst2) Dst2(std::forward<Src2>(src2));
47  }
48  catch (...) {
49  dst1->~Dst1();
50  throw;
51  }
52 }
53 
59 template<typename Key, typename Value> class SimpleMapSlot {
60  private:
61  enum State : uint8_t {
62  Empty = 0,
63  Occupied = 1,
64  Removed = 2,
65  };
66 
67  State state_;
68  TypedBuffer<Key> key_buffer_;
69  TypedBuffer<Value> value_buffer_;
70 
71  public:
76  {
77  state_ = Empty;
78  }
79 
84  {
85  if (state_ == Occupied) {
86  key_buffer_.ref().~Key();
87  value_buffer_.ref().~Value();
88  }
89  }
90 
96  {
97  state_ = other.state_;
98  if (other.state_ == Occupied) {
99  initialize_pointer_pair(other.key_buffer_.ref(),
100  other.value_buffer_.ref(),
101  key_buffer_.ptr(),
102  value_buffer_.ptr());
103  }
104  }
105 
111  SimpleMapSlot(SimpleMapSlot &&other) noexcept(
112  std::is_nothrow_move_constructible_v<Key> &&std::is_nothrow_move_constructible_v<Value>)
113  {
114  state_ = other.state_;
115  if (other.state_ == Occupied) {
116  initialize_pointer_pair(std::move(other.key_buffer_.ref()),
117  std::move(other.value_buffer_.ref()),
118  key_buffer_.ptr(),
119  value_buffer_.ptr());
120  }
121  }
122 
126  Key *key()
127  {
128  return key_buffer_;
129  }
130 
134  const Key *key() const
135  {
136  return key_buffer_;
137  }
138 
143  {
144  return value_buffer_;
145  }
146 
150  const Value *value() const
151  {
152  return value_buffer_;
153  }
154 
158  bool is_occupied() const
159  {
160  return state_ == Occupied;
161  }
162 
166  bool is_empty() const
167  {
168  return state_ == Empty;
169  }
170 
175  template<typename Hash> uint64_t get_hash(const Hash &hash)
176  {
177  BLI_assert(this->is_occupied());
178  return hash(*key_buffer_);
179  }
180 
185  template<typename ForwardKey, typename IsEqual>
186  bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
187  {
188  if (state_ == Occupied) {
189  return is_equal(key, *key_buffer_);
190  }
191  return false;
192  }
193 
198  template<typename ForwardKey, typename ForwardValue>
199  void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
200  {
201  BLI_assert(!this->is_occupied());
202  new (&value_buffer_) Value(std::forward<ForwardValue>(value));
203  this->occupy_no_value(std::forward<ForwardKey>(key), hash);
204  state_ = Occupied;
205  }
206 
211  template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
212  {
213  BLI_assert(!this->is_occupied());
214  try {
215  new (&key_buffer_) Key(std::forward<ForwardKey>(key));
216  }
217  catch (...) {
218  /* The value is assumed to be constructed already, so it has to be destructed as well. */
219  value_buffer_.ref().~Value();
220  throw;
221  }
222  state_ = Occupied;
223  }
224 
229  void remove()
230  {
231  BLI_assert(this->is_occupied());
232  key_buffer_.ref().~Key();
233  value_buffer_.ref().~Value();
234  state_ = Removed;
235  }
236 };
237 
246 template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot {
247  private:
248  Key key_ = KeyInfo::get_empty();
249  TypedBuffer<Value> value_buffer_;
250 
251  public:
252  IntrusiveMapSlot() = default;
253 
255  {
256  if (KeyInfo::is_not_empty_or_removed(key_)) {
257  value_buffer_.ref().~Value();
258  }
259  }
260 
261  IntrusiveMapSlot(const IntrusiveMapSlot &other) : key_(other.key_)
262  {
263  if (KeyInfo::is_not_empty_or_removed(key_)) {
264  new (&value_buffer_) Value(*other.value_buffer_);
265  }
266  }
267 
268  IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept : key_(other.key_)
269  {
270  if (KeyInfo::is_not_empty_or_removed(key_)) {
271  new (&value_buffer_) Value(std::move(*other.value_buffer_));
272  }
273  }
274 
275  Key *key()
276  {
277  return &key_;
278  }
279 
280  const Key *key() const
281  {
282  return &key_;
283  }
284 
286  {
287  return value_buffer_;
288  }
289 
290  const Value *value() const
291  {
292  return value_buffer_;
293  }
294 
295  bool is_occupied() const
296  {
297  return KeyInfo::is_not_empty_or_removed(key_);
298  }
299 
300  bool is_empty() const
301  {
302  return KeyInfo::is_empty(key_);
303  }
304 
305  template<typename Hash> uint64_t get_hash(const Hash &hash)
306  {
307  BLI_assert(this->is_occupied());
308  return hash(key_);
309  }
310 
311  template<typename ForwardKey, typename IsEqual>
312  bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
313  {
314  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
315  return is_equal(key, key_);
316  }
317 
318  template<typename ForwardKey, typename ForwardValue>
319  void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
320  {
321  BLI_assert(!this->is_occupied());
322  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
323  new (&value_buffer_) Value(std::forward<ForwardValue>(value));
324  this->occupy_no_value(std::forward<ForwardKey>(key), hash);
325  }
326 
327  template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
328  {
329  BLI_assert(!this->is_occupied());
330  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
331  try {
332  key_ = std::forward<ForwardKey>(key);
333  }
334  catch (...) {
335  value_buffer_.ref().~Value();
336  throw;
337  }
338  }
339 
340  void remove()
341  {
342  BLI_assert(this->is_occupied());
343  value_buffer_.ref().~Value();
344  KeyInfo::remove(key_);
345  }
346 };
347 
348 template<typename Key, typename Value> struct DefaultMapSlot;
349 
353 template<typename Key, typename Value> struct DefaultMapSlot {
355 };
356 
361 template<typename Key, typename Value> struct DefaultMapSlot<Key *, Value> {
363 };
364 
365 } // namespace blender
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED(x)
struct Key Key
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White Value
void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
const Key * key() const
void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept
IntrusiveMapSlot(const IntrusiveMapSlot &other)
bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
uint64_t get_hash(const Hash &hash)
const Value * value() const
SimpleMapSlot(const SimpleMapSlot &other)
const Value * value() const
bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
const Key * key() const
SimpleMapSlot(SimpleMapSlot &&other) noexcept(std::is_nothrow_move_constructible_v< Key > &&std::is_nothrow_move_constructible_v< Value >)
uint64_t get_hash(const Hash &hash)
void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
void initialize_pointer_pair(Src1 &&src1, Src2 &&src2, Dst1 *dst1, Dst2 *dst2)
#define hash
Definition: noise.c:169
unsigned char uint8_t
Definition: stdint.h:81
unsigned __int64 uint64_t
Definition: stdint.h:93