aboutsummaryrefslogtreecommitdiffhomepage
path: root/tdutils/td/utils/MapNode.h
diff options
context:
space:
mode:
authorlevlam <levlam@telegram.org>2022-04-19 02:33:12 +0300
committerlevlam <levlam@telegram.org>2022-04-19 02:33:12 +0300
commit43ea7be0fbca64995eca3c902a4c77e6d44c2de2 (patch)
tree455221a968c2bde20ae5e359d4ea60c1708fbaff /tdutils/td/utils/MapNode.h
parente8c3792776f9c63590aa51bc9bbc472af0bd3fca (diff)
Add fast-moved implementation for big HashSet nodes.
Diffstat (limited to 'tdutils/td/utils/MapNode.h')
-rw-r--r--tdutils/td/utils/MapNode.h75
1 files changed, 74 insertions, 1 deletions
diff --git a/tdutils/td/utils/MapNode.h b/tdutils/td/utils/MapNode.h
index 3304fcd56..806abe0a5 100644
--- a/tdutils/td/utils/MapNode.h
+++ b/tdutils/td/utils/MapNode.h
@@ -10,11 +10,12 @@
#include "td/utils/HashTableUtils.h"
#include <new>
+#include <type_traits>
#include <utility>
namespace td {
-template <class KeyT, class ValueT>
+template <class KeyT, class ValueT, class Enable = void>
struct MapNode {
using first_type = KeyT;
using second_type = ValueT;
@@ -90,4 +91,76 @@ struct MapNode {
}
};
+template <class KeyT, class ValueT>
+struct MapNode<KeyT, ValueT, typename std::enable_if_t<(sizeof(KeyT) + sizeof(ValueT) > 6 * sizeof(void *))>> {
+ struct Impl {
+ using first_type = KeyT;
+ using second_type = ValueT;
+
+ KeyT first{};
+ union {
+ ValueT second;
+ };
+
+ template <class InputKeyT, class... ArgsT>
+ Impl(InputKeyT &&key, ArgsT &&...args) : first(std::forward<InputKeyT>(key)) {
+ new (&second) ValueT(std::forward<ArgsT>(args)...);
+ DCHECK(!is_hash_table_key_empty(first));
+ }
+ Impl(const Impl &other) = delete;
+ Impl &operator=(const Impl &other) = delete;
+ Impl(Impl &&other) = delete;
+ void operator=(Impl &&other) = delete;
+ ~Impl() {
+ second.~ValueT();
+ }
+ };
+
+ using first_type = KeyT;
+ using second_type = ValueT;
+ using public_key_type = KeyT;
+ using public_type = Impl;
+
+ unique_ptr<Impl> impl_;
+
+ const KeyT &key() const {
+ DCHECK(!empty());
+ return impl_->first;
+ }
+
+ Impl &get_public() {
+ return *impl_;
+ }
+
+ const Impl &get_public() const {
+ return *impl_;
+ }
+
+ MapNode() {
+ }
+ MapNode(KeyT key, ValueT value) : impl_(td::make_unique<Impl>(std::move(key), std::move(value))) {
+ }
+
+ void copy_from(const MapNode &other) {
+ DCHECK(empty());
+ DCHECK(!other.empty());
+ impl_ = td::make_unique<Impl>(other.impl_->first, other.impl_->second);
+ }
+
+ bool empty() const {
+ return impl_ == nullptr;
+ }
+
+ void clear() {
+ DCHECK(!empty());
+ impl_ = nullptr;
+ }
+
+ template <class... ArgsT>
+ void emplace(KeyT key, ArgsT &&...args) {
+ DCHECK(empty());
+ impl_ = td::make_unique<Impl>(std::move(key), std::forward<ArgsT>(args)...);
+ }
+};
+
} // namespace td