Blender  V3.3
BLI_map_slots.hh
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #pragma once
4 
23 #include "BLI_memory_utils.hh"
24 
25 namespace blender {
26 
27 template<typename Src1, typename Src2, typename Dst1, typename Dst2>
28 void initialize_pointer_pair(Src1 &&src1, Src2 &&src2, Dst1 *dst1, Dst2 *dst2)
29 {
30  new ((void *)dst1) Dst1(std::forward<Src1>(src1));
31  try {
32  new ((void *)dst2) Dst2(std::forward<Src2>(src2));
33  }
34  catch (...) {
35  dst1->~Dst1();
36  throw;
37  }
38 }
39 
45 template<typename Key, typename Value> class SimpleMapSlot {
46  private:
47  enum State : uint8_t {
48  Empty = 0,
49  Occupied = 1,
50  Removed = 2,
51  };
52 
53  State state_;
54  TypedBuffer<Key> key_buffer_;
55  TypedBuffer<Value> value_buffer_;
56 
57  public:
62  {
63  state_ = Empty;
64  }
65 
70  {
71  if (state_ == Occupied) {
72  key_buffer_.ref().~Key();
73  value_buffer_.ref().~Value();
74  }
75  }
76 
82  {
83  state_ = other.state_;
84  if (other.state_ == Occupied) {
85  initialize_pointer_pair(other.key_buffer_.ref(),
86  other.value_buffer_.ref(),
87  key_buffer_.ptr(),
88  value_buffer_.ptr());
89  }
90  }
91 
97  SimpleMapSlot(SimpleMapSlot &&other) noexcept(
98  std::is_nothrow_move_constructible_v<Key> &&std::is_nothrow_move_constructible_v<Value>)
99  {
100  state_ = other.state_;
101  if (other.state_ == Occupied) {
102  initialize_pointer_pair(std::move(other.key_buffer_.ref()),
103  std::move(other.value_buffer_.ref()),
104  key_buffer_.ptr(),
105  value_buffer_.ptr());
106  }
107  }
108 
112  Key *key()
113  {
114  return key_buffer_;
115  }
116 
120  const Key *key() const
121  {
122  return key_buffer_;
123  }
124 
129  {
130  return value_buffer_;
131  }
132 
136  const Value *value() const
137  {
138  return value_buffer_;
139  }
140 
144  bool is_occupied() const
145  {
146  return state_ == Occupied;
147  }
148 
152  bool is_empty() const
153  {
154  return state_ == Empty;
155  }
156 
161  template<typename Hash> uint64_t get_hash(const Hash &hash)
162  {
163  BLI_assert(this->is_occupied());
164  return hash(*key_buffer_);
165  }
166 
171  template<typename ForwardKey, typename IsEqual>
172  bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
173  {
174  if (state_ == Occupied) {
175  return is_equal(key, *key_buffer_);
176  }
177  return false;
178  }
179 
184  template<typename ForwardKey, typename... ForwardValue>
185  void occupy(ForwardKey &&key, uint64_t hash, ForwardValue &&...value)
186  {
187  BLI_assert(!this->is_occupied());
188  new (&value_buffer_) Value(std::forward<ForwardValue>(value)...);
189  this->occupy_no_value(std::forward<ForwardKey>(key), hash);
190  state_ = Occupied;
191  }
192 
197  template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
198  {
199  BLI_assert(!this->is_occupied());
200  try {
201  new (&key_buffer_) Key(std::forward<ForwardKey>(key));
202  }
203  catch (...) {
204  /* The value is assumed to be constructed already, so it has to be destructed as well. */
205  value_buffer_.ref().~Value();
206  throw;
207  }
208  state_ = Occupied;
209  }
210 
215  void remove()
216  {
217  BLI_assert(this->is_occupied());
218  key_buffer_.ref().~Key();
219  value_buffer_.ref().~Value();
220  state_ = Removed;
221  }
222 };
223 
232 template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot {
233  private:
234  Key key_ = KeyInfo::get_empty();
235  TypedBuffer<Value> value_buffer_;
236 
237  public:
238  IntrusiveMapSlot() = default;
239 
241  {
242  if (KeyInfo::is_not_empty_or_removed(key_)) {
243  value_buffer_.ref().~Value();
244  }
245  }
246 
247  IntrusiveMapSlot(const IntrusiveMapSlot &other) : key_(other.key_)
248  {
249  if (KeyInfo::is_not_empty_or_removed(key_)) {
250  new (&value_buffer_) Value(*other.value_buffer_);
251  }
252  }
253 
254  IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept : key_(other.key_)
255  {
256  if (KeyInfo::is_not_empty_or_removed(key_)) {
257  new (&value_buffer_) Value(std::move(*other.value_buffer_));
258  }
259  }
260 
261  Key *key()
262  {
263  return &key_;
264  }
265 
266  const Key *key() const
267  {
268  return &key_;
269  }
270 
272  {
273  return value_buffer_;
274  }
275 
276  const Value *value() const
277  {
278  return value_buffer_;
279  }
280 
281  bool is_occupied() const
282  {
283  return KeyInfo::is_not_empty_or_removed(key_);
284  }
285 
286  bool is_empty() const
287  {
288  return KeyInfo::is_empty(key_);
289  }
290 
291  template<typename Hash> uint64_t get_hash(const Hash &hash)
292  {
293  BLI_assert(this->is_occupied());
294  return hash(key_);
295  }
296 
297  template<typename ForwardKey, typename IsEqual>
298  bool contains(const ForwardKey &key, const IsEqual &is_equal, uint64_t UNUSED(hash)) const
299  {
300  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
301  return is_equal(key, key_);
302  }
303 
304  template<typename ForwardKey, typename... ForwardValue>
305  void occupy(ForwardKey &&key, uint64_t hash, ForwardValue &&...value)
306  {
307  BLI_assert(!this->is_occupied());
308  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
309  new (&value_buffer_) Value(std::forward<ForwardValue>(value)...);
310  this->occupy_no_value(std::forward<ForwardKey>(key), hash);
311  }
312 
313  template<typename ForwardKey> void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
314  {
315  BLI_assert(!this->is_occupied());
316  BLI_assert(KeyInfo::is_not_empty_or_removed(key));
317  try {
318  key_ = std::forward<ForwardKey>(key);
319  }
320  catch (...) {
321  value_buffer_.ref().~Value();
322  throw;
323  }
324  }
325 
326  void remove()
327  {
328  BLI_assert(this->is_occupied());
329  value_buffer_.ref().~Value();
330  KeyInfo::remove(key_);
331  }
332 };
333 
334 template<typename Key, typename Value> struct DefaultMapSlot;
335 
339 template<typename Key, typename Value> struct DefaultMapSlot {
341 };
342 
347 template<typename Key, typename Value> struct DefaultMapSlot<Key *, Value> {
349 };
350 
351 } // namespace blender
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define UNUSED(x)
struct Key Key
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a producing a negative Combine Generate a color from its and blue Hue Saturation Value
const Key * key() const
void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
IntrusiveMapSlot(IntrusiveMapSlot &&other) noexcept
IntrusiveMapSlot(const IntrusiveMapSlot &other)
void occupy(ForwardKey &&key, uint64_t hash, ForwardValue &&...value)
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, uint64_t hash, ForwardValue &&...value)
void occupy_no_value(ForwardKey &&key, uint64_t UNUSED(hash))
bool remove(void *owner, const AttributeIDRef &attribute_id)
void initialize_pointer_pair(Src1 &&src1, Src2 &&src2, Dst1 *dst1, Dst2 *dst2)
#define hash
Definition: noise.c:153
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90