diff options
| author | levlam <levlam@telegram.org> | 2022-04-19 02:33:12 +0300 |
|---|---|---|
| committer | levlam <levlam@telegram.org> | 2022-04-19 02:33:12 +0300 |
| commit | 43ea7be0fbca64995eca3c902a4c77e6d44c2de2 (patch) | |
| tree | 455221a968c2bde20ae5e359d4ea60c1708fbaff /tdutils/td/utils/MapNode.h | |
| parent | e8c3792776f9c63590aa51bc9bbc472af0bd3fca (diff) | |
Add fast-moved implementation for big HashSet nodes.
Diffstat (limited to 'tdutils/td/utils/MapNode.h')
| -rw-r--r-- | tdutils/td/utils/MapNode.h | 75 |
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 |
