CatapultServer  v0.5.0.1 (Elephant)
BaseSetDelta.h
Go to the documentation of this file.
1 
21 #pragma once
22 #include "BaseSetDefaultTraits.h"
23 #include "BaseSetFindIterator.h"
24 #include "DeltaElements.h"
26 #include "catapult/exceptions.h"
27 #include <memory>
28 #include <type_traits>
29 #include <unordered_map>
30 
31 namespace catapult { namespace deltaset {
32 
34  enum class InsertResult {
36  Unremoved,
37 
39  Updated,
40 
42  Redundant,
43 
45  Inserted
46  };
47 
49  enum class RemoveResult {
51  None,
52 
55 
57  Uninserted,
58 
60  Redundant,
61 
63  Removed
64  };
65 
66  template<typename TSetTraits>
68 
74  template<typename TElementTraits, typename TSetTraits>
75  class BaseSetDelta : public utils::NonCopyable {
76  public:
77  using ElementType = typename TElementTraits::ElementType;
78  using ElementMutabilityTag = typename TElementTraits::MutabilityTag;
79 
80  using SetType = typename TSetTraits::SetType;
81  using MemorySetType = typename TSetTraits::MemorySetType;
82 
83  using KeyType = typename TSetTraits::KeyType;
85  using SetTraits = TSetTraits;
86 
87  using FindIterator = std::conditional_t<
88  std::is_same_v<ElementMutabilityTag, ImmutableTypeTag>,
91  >;
93 
94  public:
96  explicit BaseSetDelta(const SetType& originalElements)
97  : m_originalElements(originalElements)
98  , m_generationId(1)
99  {}
100 
101  public:
103  bool empty() const {
104  return 0 == size();
105  }
106 
108  size_t size() const {
109  return m_originalElements.size() - m_removedElements.size() + m_addedElements.size();
110  }
111 
112  public:
115  FindConstIterator find(const KeyType& key) const {
116  return Find<FindConstIterator>(*this, key);
117  }
118 
121  FindIterator find(const KeyType& key) {
122  auto iter = Find<FindIterator>(*this, key);
123  if (!!iter.get())
125 
126  return iter;
127  }
128 
129  private:
130  template<typename TResultIterator, typename TBaseSetDelta>
131  static TResultIterator Find(TBaseSetDelta& set, const KeyType& key) {
132  if (Contains(set.m_removedElements, key))
133  return TResultIterator();
134 
135  auto originalIter = set.find(key, ElementMutabilityTag());
136  if (originalIter.get())
137  return originalIter;
138 
139  auto addedIter = set.m_addedElements.find(key);
140  return set.m_addedElements.cend() != addedIter ? TResultIterator(std::move(addedIter)) : TResultIterator();
141  }
142 
144  auto copiedIter = m_copiedElements.find(key);
145  if (m_copiedElements.cend() != copiedIter)
146  return FindIterator(std::move(copiedIter));
147 
148  auto originalIter = find(key, ImmutableTypeTag());
149  if (!originalIter.get())
150  return FindIterator();
151 
152  auto copy = TElementTraits::Copy(originalIter.get());
153  auto result = m_copiedElements.insert(SetTraits::ToStorage(copy));
154  return FindIterator(std::move(result.first));
155  }
156 
158  auto copiedIter = m_copiedElements.find(key);
159  return m_copiedElements.cend() != copiedIter
160  ? FindConstIterator(std::move(copiedIter))
161  : find(key, ImmutableTypeTag());
162  }
163 
165  auto originalIter = m_originalElements.find(key);
166  return m_originalElements.cend() != originalIter ? FindConstIterator(std::move(originalIter)) : FindConstIterator();
167  }
168 
170  markKey(key);
171  }
172 
174  // find can never modify an immutable element
175  }
176 
177  public:
180  bool contains(const KeyType& key) const {
182  }
183 
184  private:
185  template<typename TSet> // SetType or MemorySetType
186  static constexpr bool Contains(const TSet& set, const KeyType& key) {
187  return set.cend() != set.find(key);
188  }
189 
190  public:
193  InsertResult insert(const ElementType& element) {
194  return insert(element, ElementMutabilityTag());
195  }
196 
198  template<typename... TArgs>
199  InsertResult emplace(TArgs&&... args) {
200  return insert(ElementType(std::forward<TArgs>(args)...));
201  }
202 
203  private:
205  // copy the storage before erasing in case element is sourced from the same container being updated
206  const auto& key = TSetTraits::ToKey(element);
207  auto storage = TSetTraits::ToStorage(element);
208  markKey(key);
209 
210  auto insertResult = InsertResult::Inserted;
211  decltype(m_copiedElements)* pTargetElements;
212  auto removedIter = m_removedElements.find(key);
213  if (m_removedElements.cend() != removedIter) {
214  m_removedElements.erase(removedIter);
215  pTargetElements = Contains(m_addedElements, key) ? &m_addedElements : &m_copiedElements;
216  insertResult = InsertResult::Unremoved;
217  } else if (Contains(m_originalElements, key)) {
218  pTargetElements = &m_copiedElements; // original element, possibly modified
219  insertResult = InsertResult::Updated;
220  } else {
221  pTargetElements = &m_addedElements; // not an original element
222  if (Contains(m_addedElements, key))
223  insertResult = InsertResult::Updated;
224  }
225 
226  pTargetElements->erase(key);
227  pTargetElements->insert(std::move(storage));
228  return insertResult;
229  }
230 
232  const auto& key = TSetTraits::ToKey(element);
233  auto removedIter = m_removedElements.find(key);
234  if (m_removedElements.cend() != removedIter) {
235  // since element is immutable, always preserve the first seen element
236  if (Contains(m_addedElements, key))
237  markKey(key);
238  else
239  clearKey(key);
240 
241  m_removedElements.erase(removedIter);
243  }
244 
247 
248  markKey(key);
249  m_addedElements.insert(TSetTraits::ToStorage(element));
250  return InsertResult::Inserted;
251  }
252 
253  public:
256  if (Contains(m_removedElements, key))
258 
259  return remove(key, ElementMutabilityTag());
260  }
261 
262  private:
264  auto copiedIter = m_copiedElements.find(key);
265  if (m_copiedElements.cend() != copiedIter) {
266  markKey(key);
267  m_removedElements.insert(*copiedIter);
268  m_copiedElements.erase(copiedIter);
270  }
271 
272  return remove(key, ImmutableTypeTag());
273  }
274 
276  auto addedIter = m_addedElements.find(key);
277  if (m_addedElements.cend() != addedIter) {
278  // in order for generations to work correctly, deltas must reflect removal of temporarily added elements
279  // so that subsequent generation processing can process their removal
280  //
281  // consider:
282  // 1. add(x) at generation y
283  // 2. remove(x) at generation y+1
284  //
285  // processing at generation y+1 must be able to detect removal of x
286  // chosen solution is to include x in both Added and Removed at generation y+1
287  markKey(key);
288  m_removedElements.insert(*addedIter);
290  }
291 
292  auto originalIter = m_originalElements.find(key);
293  if (m_originalElements.cend() != originalIter) {
294  markKey(key);
295  m_removedElements.insert(TSetTraits::ToStorage(key, std::move(originalIter)));
296  return RemoveResult::Removed;
297  }
298 
299  return RemoveResult::None;
300  }
301 
302  public:
306  }
307 
309  void reset() {
310  m_addedElements.clear();
311  m_removedElements.clear();
312  m_copiedElements.clear();
313 
314  m_generationId = 1;
315  m_keyGenerationIdMap.clear();
316  }
317 
318  public:
320  uint32_t generationId() const {
321  return m_generationId;
322  }
323 
325  uint32_t generationId(const KeyType& key) const {
326  auto iter = m_keyGenerationIdMap.find(key);
327  return m_keyGenerationIdMap.cend() == iter ? 0 : iter->second;
328  }
329 
332  ++m_generationId;
333  }
334 
335  private:
336  void markKey(const KeyType& key) {
337  // latest generation id should always be stored
339  }
340 
341  void clearKey(const KeyType& key) {
342  m_keyGenerationIdMap.erase(key);
343  }
344 
345  private:
346  // for sorted containers, use map because no hasher is specified
347  template<typename T, typename = void>
349  using Type = std::map<KeyType, uint32_t, typename T::key_compare>;
350  };
351 
352  // for hashed containers, use unordered_map because hasher is specified
353  template<typename T>
354  struct KeyGenerationIdMap<T, utils::traits::is_type_expression_t<typename T::hasher>> {
355  using Type = std::unordered_map<KeyType, uint32_t, typename T::hasher, typename T::key_equal>;
356  };
357 
358  private:
363 
364  uint32_t m_generationId;
366 
367  private:
368  template<typename TElementTraits2, typename TSetTraits2>
370  };
371 }}
catapult::deltaset::BaseSetDelta::find
FindConstIterator find(const KeyType &key, ImmutableTypeTag) const
Definition: BaseSetDelta.h:164
catapult::deltaset::BaseSetDelta::Find
static TResultIterator Find(TBaseSetDelta &set, const KeyType &key)
Definition: BaseSetDelta.h:131
catapult::deltaset::BaseSetDelta::find
FindConstIterator find(const KeyType &key, MutableTypeTag) const
Definition: BaseSetDelta.h:157
catapult::deltaset::BaseSetDelta::generationId
uint32_t generationId() const
Gets the current generation id.
Definition: BaseSetDelta.h:320
catapult::deltaset::BaseSetDelta::m_copiedElements
MemorySetType m_copiedElements
Definition: BaseSetDelta.h:362
catapult::deltaset::InsertResult::Redundant
Insert failed because the element already exists (immutable elements only).
exceptions.h
catapult::deltaset::BaseSetDelta
Definition: BaseSet.h:30
catapult::deltaset::BaseSetDelta::find
FindIterator find(const KeyType &key)
Definition: BaseSetDelta.h:121
catapult::deltaset::BaseSetDelta::insert
InsertResult insert(const ElementType &element, MutableTypeTag)
Definition: BaseSetDelta.h:204
catapult::deltaset::BaseSetDelta::m_originalElements
const SetType & m_originalElements
Definition: BaseSetDelta.h:359
catapult::deltaset::BaseSetDelta::FindIterator
std::conditional_t< std::is_same_v< ElementMutabilityTag, ImmutableTypeTag >, BaseSetDeltaFindConstIterator< FindTraits, TSetTraits >, BaseSetDeltaFindIterator< FindTraits, TSetTraits > > FindIterator
Definition: BaseSetDelta.h:91
catapult::deltaset::BaseSetDelta::FindConstIterator
BaseSetDeltaFindConstIterator< FindTraits, TSetTraits > FindConstIterator
Definition: BaseSetDelta.h:92
catapult::deltaset::BaseSetDelta::clearKey
void clearKey(const KeyType &key)
Definition: BaseSetDelta.h:341
catapult::deltaset::BaseSetDelta::m_generationId
uint32_t m_generationId
Definition: BaseSetDelta.h:364
catapult::deltaset::BaseSetDelta::empty
bool empty() const
Gets a value indicating whether or not the set is empty.
Definition: BaseSetDelta.h:103
catapult::deltaset::DeltaElements
Slim wrapper around changed elements.
Definition: DeltaElements.h:27
catapult::deltaset::BaseSetDelta::markFoundElement
void markFoundElement(const KeyType &key, MutableTypeTag)
Definition: BaseSetDelta.h:169
catapult::deltaset::ImmutableTypeTag
Tag that indicates a type is immutable.
Definition: BaseSetDefaultTraits.h:162
catapult::deltaset::RemoveResult::Uninserted
An element pending insert was reverted.
catapult::deltaset::BaseSetDelta::KeyGenerationIdMap< SetType >::Type
std::map< KeyType, uint32_t, typename SetType ::key_compare > Type
Definition: BaseSetDelta.h:349
catapult::deltaset::BaseSetDelta::insert
InsertResult insert(const ElementType &element, ImmutableTypeTag)
Definition: BaseSetDelta.h:231
BaseSetFindIterator.h
catapult::deltaset::BaseSetDelta::reset
void reset()
Resets all pending modifications.
Definition: BaseSetDelta.h:309
catapult::deltaset::FindTraitsT
Traits for customizing the behavior of find depending on element type.
Definition: BaseSetDefaultTraits.h:180
catapult::deltaset::BaseSetDeltaIterationView
Definition: BaseSetDelta.h:67
catapult::deltaset::BaseSetDelta::ElementMutabilityTag
typename TElementTraits::MutabilityTag ElementMutabilityTag
Definition: BaseSetDelta.h:78
catapult::deltaset::BaseSetDelta::KeyType
typename TSetTraits::KeyType KeyType
Definition: BaseSetDelta.h:83
catapult::deltaset::BaseSetDelta::remove
RemoveResult remove(const KeyType &key, MutableTypeTag)
Definition: BaseSetDelta.h:263
catapult::deltaset::BaseSetDelta::KeyGenerationIdMap< T, utils::traits::is_type_expression_t< typename T::hasher > >::Type
std::unordered_map< KeyType, uint32_t, typename T::hasher, typename T::key_equal > Type
Definition: BaseSetDelta.h:355
catapult::deltaset::BaseSetDelta::SetTraits
TSetTraits SetTraits
Definition: BaseSetDelta.h:85
catapult::deltaset::BaseSetDelta::KeyGenerationIdMap
Definition: BaseSetDelta.h:348
catapult::deltaset::BaseSetDelta::emplace
InsertResult emplace(TArgs &&... args)
Creates an element around the passed arguments (args) and inserts the element into this set.
Definition: BaseSetDelta.h:199
catapult::deltaset::BaseSetDelta::insert
InsertResult insert(const ElementType &element)
Definition: BaseSetDelta.h:193
catapult::deltaset::BaseSetDelta::generationId
uint32_t generationId(const KeyType &key) const
Gets the generation id associated with key.
Definition: BaseSetDelta.h:325
catapult::deltaset::InsertResult
InsertResult
Possible results of an insert into a base set delta.
Definition: BaseSetDelta.h:34
catapult::deltaset::BaseSetDelta::incrementGenerationId
void incrementGenerationId()
Increments the generation id.
Definition: BaseSetDelta.h:331
catapult::deltaset::detail::BaseSetSingleIteratorWrapper
Definition: BaseSetFindIterator.h:30
catapult::deltaset::BaseSetDeltaFindConstIterator
detail::BaseSetConditionalIteratorWrapper< TFindTraits, TSetTraits, typename TSetTraits::SetType::const_iterator, typename TSetTraits::MemorySetType::const_iterator, typename TFindTraits::ConstResultType > BaseSetDeltaFindConstIterator
Iterator that returns a find (const) result from a base set delta.
Definition: BaseSetFindIterator.h:131
catapult::deltaset::RemoveResult::Removed
An existing element was removed.
catapult::utils::traits::is_type_expression_t
typename is_type_expression< T, Enable >::type is_type_expression_t
true if the expression is valid and evaluates to a type, false otherwise.
Definition: Traits.h:98
catapult::deltaset::RemoveResult
RemoveResult
Possible results of a remove from a base set delta.
Definition: BaseSetDelta.h:49
catapult::deltaset::BaseSetDelta::find
FindIterator find(const KeyType &key, MutableTypeTag)
Definition: BaseSetDelta.h:143
catapult::deltaset::BaseSetDelta::size
size_t size() const
Gets the size of this set.
Definition: BaseSetDelta.h:108
catapult::deltaset::BaseSetDelta::deltas
DeltaElements< MemorySetType > deltas() const
Gets const references to the pending modifications.
Definition: BaseSetDelta.h:304
catapult::deltaset::BaseSetDelta::find
FindConstIterator find(const KeyType &key) const
Definition: BaseSetDelta.h:115
catapult::deltaset::RemoveResult::Unmodified_And_Removed
An element pending modification was reverted and removed (mutable elements only).
catapult::deltaset::BaseSetDelta::SetType
typename TSetTraits::SetType SetType
Definition: BaseSetDelta.h:80
DeltaElements.h
catapult::deltaset::InsertResult::Unremoved
An element pending removal was reverted.
catapult::deltaset::InsertResult::Updated
An existing element was updated (mutable elements only).
catapult::deltaset::RemoveResult::None
No matching element was found.
catapult::deltaset::BaseSetDelta::markKey
void markKey(const KeyType &key)
Definition: BaseSetDelta.h:336
catapult::deltaset::BaseSetDelta::m_keyGenerationIdMap
KeyGenerationIdMap< SetType >::Type m_keyGenerationIdMap
Definition: BaseSetDelta.h:365
BaseSetDefaultTraits.h
catapult::deltaset::BaseSetDelta::m_addedElements
MemorySetType m_addedElements
Definition: BaseSetDelta.h:360
catapult::deltaset::BaseSetDelta::remove
RemoveResult remove(const KeyType &key, ImmutableTypeTag)
Definition: BaseSetDelta.h:275
catapult::deltaset::BaseSetDelta::MakeIterableView
friend BaseSetDeltaIterationView< TSetTraits2 > MakeIterableView(const BaseSetDelta< TElementTraits2, TSetTraits2 > &set)
catapult
Definition: AddressExtractionExtension.cpp:28
catapult::deltaset::BaseSetDelta::Contains
static constexpr bool Contains(const TSet &set, const KeyType &key)
Definition: BaseSetDelta.h:186
catapult::deltaset::BaseSetDelta::contains
bool contains(const KeyType &key) const
Definition: BaseSetDelta.h:180
catapult::deltaset::BaseSetDelta::remove
RemoveResult remove(const KeyType &key)
Removes the element identified by key from the delta.
Definition: BaseSetDelta.h:255
catapult::deltaset::InsertResult::Inserted
A new element was inserted.
catapult::deltaset::BaseSetDelta::ElementType
typename TElementTraits::ElementType ElementType
Definition: BaseSetDelta.h:77
catapult::utils::NonCopyable
A class that can neither be copied nor moved.
Definition: NonCopyable.h:26
catapult::deltaset::BaseSetDelta::BaseSetDelta
BaseSetDelta(const SetType &originalElements)
Creates a delta around originalElements.
Definition: BaseSetDelta.h:96
catapult::deltaset::BaseSetDelta::MemorySetType
typename TSetTraits::MemorySetType MemorySetType
Definition: BaseSetDelta.h:81
catapult::deltaset::BaseSetDelta::markFoundElement
void markFoundElement(const KeyType &, ImmutableTypeTag)
Definition: BaseSetDelta.h:173
catapult::deltaset::MutableTypeTag
Tag that indicates a type is mutable.
Definition: BaseSetDefaultTraits.h:148
catapult::deltaset::BaseSetDelta::m_removedElements
MemorySetType m_removedElements
Definition: BaseSetDelta.h:361
NonCopyable.h