diff options
Diffstat (limited to 'absl')
-rw-r--r-- | absl/base/BUILD.bazel | 2 | ||||
-rw-r--r-- | absl/base/CMakeLists.txt | 1 | ||||
-rw-r--r-- | absl/base/dynamic_annotations.cc | 72 | ||||
-rw-r--r-- | absl/base/dynamic_annotations.h | 64 | ||||
-rw-r--r-- | absl/base/internal/sysinfo.cc | 14 | ||||
-rw-r--r-- | absl/base/internal/sysinfo.h | 8 | ||||
-rw-r--r-- | absl/container/btree_test.cc | 7 | ||||
-rw-r--r-- | absl/container/internal/btree.h | 252 | ||||
-rw-r--r-- | absl/container/internal/container_memory.h | 7 |
9 files changed, 170 insertions, 257 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 23f2763a..ad29bb0d 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -116,7 +116,6 @@ cc_library( cc_library( name = "dynamic_annotations", srcs = [ - "dynamic_annotations.cc", "internal/dynamic_annotations.h", ], hdrs = [ @@ -126,6 +125,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":config", + ":core_headers", ], ) diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 62486f9d..f5cfc792 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -105,7 +105,6 @@ absl_cc_library( HDRS "dynamic_annotations.h" SRCS - "dynamic_annotations.cc" "internal/dynamic_annotations.h" COPTS ${ABSL_DEFAULT_COPTS} diff --git a/absl/base/dynamic_annotations.cc b/absl/base/dynamic_annotations.cc deleted file mode 100644 index f26e673e..00000000 --- a/absl/base/dynamic_annotations.cc +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2017 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include <stdlib.h> -#include <string.h> - -#include "absl/base/dynamic_annotations.h" - -// Compiler-based ThreadSanitizer defines -// DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1 -// and provides its own definitions of the functions. - -#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL -# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0 -#endif - -#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__) - -extern "C" { - -static int GetRunningOnValgrind(void) { -#ifdef RUNNING_ON_VALGRIND - if (RUNNING_ON_VALGRIND) return 1; -#endif - char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND"); - if (running_on_valgrind_str) { - return strcmp(running_on_valgrind_str, "0") != 0; - } - return 0; -} - -// See the comments in dynamic_annotations.h -int RunningOnValgrind(void) { - static volatile int running_on_valgrind = -1; - int local_running_on_valgrind = running_on_valgrind; - // C doesn't have thread-safe initialization of statics, and we - // don't want to depend on pthread_once here, so hack it. - ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack"); - if (local_running_on_valgrind == -1) - running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind(); - return local_running_on_valgrind; -} - -// See the comments in dynamic_annotations.h -double ValgrindSlowdown(void) { - // Same initialization hack as in RunningOnValgrind(). - static volatile double slowdown = 0.0; - double local_slowdown = slowdown; - ANNOTATE_BENIGN_RACE(&slowdown, "safe hack"); - if (RunningOnValgrind() == 0) { - return 1.0; - } - if (local_slowdown == 0.0) { - char *env = getenv("VALGRIND_SLOWDOWN"); - slowdown = local_slowdown = env ? atof(env) : 50.0; - } - return local_slowdown; -} - -} // extern "C" -#endif // DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h index 5ea697b7..c470c747 100644 --- a/absl/base/dynamic_annotations.h +++ b/absl/base/dynamic_annotations.h @@ -47,7 +47,11 @@ #include <stddef.h> +#include "absl/base/attributes.h" #include "absl/base/config.h" +#ifdef __cplusplus +#include "absl/base/macros.h" +#endif // TODO(rogeeff): Remove after the backward compatibility period. #include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export @@ -90,7 +94,8 @@ // Read/write annotations are enabled in Annotalysis mode; disabled otherwise. #define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \ ABSL_INTERNAL_ANNOTALYSIS_ENABLED -#endif + +#endif // ABSL_HAVE_THREAD_SANITIZER #ifdef __cplusplus #define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" { @@ -152,7 +157,7 @@ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock) // Report that a linker initialized lock has been created at address `lock`. -#ifdef THREAD_SANITIZER +#ifdef ABSL_HAVE_THREAD_SANITIZER #define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \ (__FILE__, __LINE__, lock) @@ -417,41 +422,30 @@ ABSL_NAMESPACE_END #endif +#ifdef __cplusplus +#ifdef ABSL_HAVE_THREAD_SANITIZER ABSL_INTERNAL_BEGIN_EXTERN_C - -// ------------------------------------------------------------------------- -// Return non-zero value if running under valgrind. -// -// If "valgrind.h" is included into dynamic_annotations.cc, -// the regular valgrind mechanism will be used. -// See http://valgrind.org/docs/manual/manual-core-adv.html about -// RUNNING_ON_VALGRIND and other valgrind "client requests". -// The file "valgrind.h" may be obtained by doing -// svn co svn://svn.valgrind.org/valgrind/trunk/include -// -// If for some reason you can't use "valgrind.h" or want to fake valgrind, -// there are two ways to make this function return non-zero: -// - Use environment variable: export RUNNING_ON_VALGRIND=1 -// - Make your tool intercept the function RunningOnValgrind() and -// change its return value. -// -int RunningOnValgrind(void); - -// ValgrindSlowdown returns: -// * 1.0, if (RunningOnValgrind() == 0) -// * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == -// NULL) -// * atof(getenv("VALGRIND_SLOWDOWN")) otherwise -// This function can be used to scale timeout values: -// EXAMPLE: -// for (;;) { -// DoExpensiveBackgroundTask(); -// SleepForSeconds(5 * ValgrindSlowdown()); -// } -// -double ValgrindSlowdown(void); - +int RunningOnValgrind(); +double ValgrindSlowdown(); ABSL_INTERNAL_END_EXTERN_C +#else +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace base_internal { +ABSL_DEPRECATED( + "Don't use this interface. It is misleading and is being deleted.") +ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; } +ABSL_DEPRECATED( + "Don't use this interface. It is misleading and is being deleted.") +ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; } +} // namespace base_internal +ABSL_NAMESPACE_END +} // namespace absl + +using absl::base_internal::RunningOnValgrind; +using absl::base_internal::ValgrindSlowdown; +#endif +#endif // ------------------------------------------------------------------------- // Address sanitizer annotations diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc index 6c69683f..349d9268 100644 --- a/absl/base/internal/sysinfo.cc +++ b/absl/base/internal/sysinfo.cc @@ -39,6 +39,7 @@ #endif #include <string.h> + #include <cassert> #include <cstdint> #include <cstdio> @@ -50,6 +51,7 @@ #include <vector> #include "absl/base/call_once.h" +#include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/spinlock.h" #include "absl/base/internal/unscaledcycleclock.h" @@ -420,6 +422,18 @@ pid_t GetTID() { #endif +// GetCachedTID() caches the thread ID in thread-local storage (which is a +// userspace construct) to avoid unnecessary system calls. Without this caching, +// it can take roughly 98ns, while it takes roughly 1ns with this caching. +pid_t GetCachedTID() { +#if ABSL_HAVE_THREAD_LOCAL + static thread_local pid_t thread_id = GetTID(); + return thread_id; +#else + return GetTID(); +#endif // ABSL_HAVE_THREAD_LOCAL +} + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h index 7246d5dd..119cf1f0 100644 --- a/absl/base/internal/sysinfo.h +++ b/absl/base/internal/sysinfo.h @@ -30,6 +30,7 @@ #include <cstdint> +#include "absl/base/config.h" #include "absl/base/port.h" namespace absl { @@ -59,6 +60,13 @@ using pid_t = uint32_t; #endif pid_t GetTID(); +// Like GetTID(), but caches the result in thread-local storage in order +// to avoid unnecessary system calls. Note that there are some cases where +// one must call through to GetTID directly, which is why this exists as a +// separate function. For example, GetCachedTID() is not safe to call in +// an asynchronous signal-handling context nor right after a call to fork(). +pid_t GetCachedTID(); + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc index 67ee7521..0c5f9368 100644 --- a/absl/container/btree_test.cc +++ b/absl/container/btree_test.cc @@ -15,6 +15,7 @@ #include "absl/container/btree_test.h" #include <cstdint> +#include <limits> #include <map> #include <memory> #include <stdexcept> @@ -1344,6 +1345,12 @@ class BtreeNodePeer { constexpr static size_t GetNumValuesPerNode() { return btree_node<typename Set::params_type>::kNodeValues; } + + template <typename Set> + constexpr static size_t GetMaxFieldType() { + return std::numeric_limits< + typename btree_node<typename Set::params_type>::field_type>::max(); + } }; namespace { diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index 996afa61..ab85f7da 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -255,10 +255,6 @@ struct common_params { static void move(Alloc *alloc, slot_type *src, slot_type *dest) { slot_policy::move(alloc, src, dest); } - static void move(Alloc *alloc, slot_type *first, slot_type *last, - slot_type *result) { - slot_policy::move(alloc, first, last, result); - } }; // A parameters structure for holding the type parameters for a btree_map. @@ -336,13 +332,6 @@ struct set_slot_policy { static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) { *dest = std::move(*src); } - - template <typename Alloc> - static void move(Alloc *alloc, slot_type *first, slot_type *last, - slot_type *result) { - for (slot_type *src = first, *dest = result; src != last; ++src, ++dest) - move(alloc, src, dest); - } }; // A parameters structure for holding the type parameters for a btree_set. @@ -759,14 +748,10 @@ class btree_node { template <typename... Args> void emplace_value(size_type i, allocator_type *alloc, Args &&... args); - // Removes the value at position i, shifting all existing values and children - // at positions > i to the left by 1. - void remove_value(int i, allocator_type *alloc); - - // Removes the values at positions [i, i + to_erase), shifting all values - // after that range to the left by to_erase. Does not change children at all. - void remove_values_ignore_children(int i, int to_erase, - allocator_type *alloc); + // Removes the values at positions [i, i + to_erase), shifting all existing + // values and children after that range to the left by to_erase. Clears all + // children between [i, i + to_erase). + void remove_values(field_type i, field_type to_erase, allocator_type *alloc); // Rebalances a node with its right sibling. void rebalance_right_to_left(int to_move, btree_node *right, @@ -778,7 +763,7 @@ class btree_node { void split(int insert_position, btree_node *dest, allocator_type *alloc); // Merges a node with its right sibling, moving all of the values and the - // delimiting key in the parent node onto itself. + // delimiting key in the parent node onto itself, and deleting the src node. void merge(btree_node *src, allocator_type *alloc); // Node allocation/deletion routines. @@ -799,12 +784,15 @@ class btree_node { absl::container_internal::SanitizerPoisonMemoryRegion( &mutable_child(start()), (kNodeValues + 1) * sizeof(btree_node *)); } - void destroy(allocator_type *alloc) { - for (int i = start(); i < finish(); ++i) { - value_destroy(i, alloc); - } + + static void deallocate(const size_type size, btree_node *node, + allocator_type *alloc) { + absl::container_internal::Deallocate<Alignment()>(alloc, node, size); } + // Deletes a node and all of its children. + static void clear_and_delete(btree_node *node, allocator_type *alloc); + public: // Exposed only for tests. static bool testonly_uses_linear_node_search() { @@ -813,14 +801,21 @@ class btree_node { private: template <typename... Args> - void value_init(const size_type i, allocator_type *alloc, Args &&... args) { + void value_init(const field_type i, allocator_type *alloc, Args &&... args) { absl::container_internal::SanitizerUnpoisonObject(slot(i)); params_type::construct(alloc, slot(i), std::forward<Args>(args)...); } - void value_destroy(const size_type i, allocator_type *alloc) { + void value_destroy(const field_type i, allocator_type *alloc) { params_type::destroy(alloc, slot(i)); absl::container_internal::SanitizerPoisonObject(slot(i)); } + void value_destroy_n(const field_type i, const field_type n, + allocator_type *alloc) { + for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) { + params_type::destroy(alloc, s); + absl::container_internal::SanitizerPoisonObject(s); + } + } // Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`. void transfer(const size_type dest_i, const size_type src_i, @@ -1423,25 +1418,8 @@ class btree { } // Deletion helper routines. - void erase_same_node(iterator begin, iterator end); - iterator erase_from_leaf_node(iterator begin, size_type to_erase); iterator rebalance_after_delete(iterator iter); - // Deallocates a node of a certain size in bytes using the allocator. - void deallocate(const size_type size, node_type *node) { - absl::container_internal::Deallocate<node_type::Alignment()>( - mutable_allocator(), node, size); - } - - void delete_internal_node(node_type *node) { - node->destroy(mutable_allocator()); - deallocate(node_type::InternalSize(), node); - } - void delete_leaf_node(node_type *node) { - node->destroy(mutable_allocator()); - deallocate(node_type::LeafSize(node->max_count()), node); - } - // Rebalances or splits the node iter points to. void rebalance_or_split(iterator *iter); @@ -1510,9 +1488,6 @@ class btree { template <typename K> iterator internal_find(const K &key) const; - // Deletes a node and all of its children. - void internal_clear(node_type *node); - // Verifies the tree structure of node. int internal_verify(const node_type *node, const key_type *lo, const key_type *hi) const; @@ -1580,26 +1555,27 @@ inline void btree_node<P>::emplace_value(const size_type i, } template <typename P> -inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) { - if (!leaf() && finish() > i + 1) { - assert(child(i + 1)->count() == 0); - for (size_type j = i + 1; j < finish(); ++j) { - set_child(j, child(j + 1)); - } - clear_child(finish()); - } - - remove_values_ignore_children(i, /*to_erase=*/1, alloc); -} +inline void btree_node<P>::remove_values(const field_type i, + const field_type to_erase, + allocator_type *alloc) { + // Transfer values after the removed range into their new places. + value_destroy_n(i, to_erase, alloc); + const field_type orig_finish = finish(); + const field_type src_i = i + to_erase; + transfer_n(orig_finish - src_i, i, src_i, this, alloc); -template <typename P> -inline void btree_node<P>::remove_values_ignore_children( - const int i, const int to_erase, allocator_type *alloc) { - params_type::move(alloc, slot(i + to_erase), finish_slot(), slot(i)); - for (int j = finish() - to_erase; j < finish(); ++j) { - value_destroy(j, alloc); + if (!leaf()) { + // Delete all children between begin and end. + for (int j = 0; j < to_erase; ++j) { + clear_and_delete(child(i + j + 1), alloc); + } + // Rotate children after end into new positions. + for (int j = i + to_erase + 1; j <= orig_finish; ++j) { + set_child(j - to_erase, child(j)); + clear_child(j); + } } - set_finish(finish() - to_erase); + set_finish(orig_finish - to_erase); } template <typename P> @@ -1751,8 +1727,59 @@ void btree_node<P>::merge(btree_node *src, allocator_type *alloc) { set_finish(start() + 1 + count() + src->count()); src->set_finish(src->start()); - // Remove the value on the parent node. - parent()->remove_value(position(), alloc); + // Remove the value on the parent node and delete the src node. + parent()->remove_values(position(), /*to_erase=*/1, alloc); +} + +template <typename P> +void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) { + if (node->leaf()) { + node->value_destroy_n(node->start(), node->count(), alloc); + deallocate(LeafSize(node->max_count()), node, alloc); + return; + } + if (node->count() == 0) { + deallocate(InternalSize(), node, alloc); + return; + } + + // The parent of the root of the subtree we are deleting. + btree_node *delete_root_parent = node->parent(); + + // Navigate to the leftmost leaf under node, and then delete upwards. + while (!node->leaf()) node = node->start_child(); + // Use `int` because `pos` needs to be able to hold `kNodeValues+1`, which + // isn't guaranteed to be a valid `field_type`. + int pos = node->position(); + btree_node *parent = node->parent(); + for (;;) { + // In each iteration of the next loop, we delete one leaf node and go right. + assert(pos <= parent->finish()); + do { + node = parent->child(pos); + if (!node->leaf()) { + // Navigate to the leftmost leaf under node. + while (!node->leaf()) node = node->start_child(); + pos = node->position(); + parent = node->parent(); + } + node->value_destroy_n(node->start(), node->count(), alloc); + deallocate(LeafSize(node->max_count()), node, alloc); + ++pos; + } while (pos <= parent->finish()); + + // Once we've deleted all children of parent, delete parent and go up/right. + assert(pos > parent->finish()); + do { + node = parent; + pos = node->position(); + parent = node->parent(); + node->value_destroy_n(node->start(), node->count(), alloc); + deallocate(InternalSize(), node, alloc); + if (parent == delete_root_parent) return; + ++pos; + } while (pos > parent->finish()); + } } //// @@ -2034,7 +2061,7 @@ auto btree<P>::erase(iterator iter) -> iterator { bool internal_delete = false; if (!iter.node->leaf()) { // Deletion of a value on an internal node. First, move the largest value - // from our left child here, then delete that position (in remove_value() + // from our left child here, then delete that position (in remove_values() // below). We can get to the largest value from our left child by // decrementing iter. iterator internal_iter(iter); @@ -2046,7 +2073,7 @@ auto btree<P>::erase(iterator iter) -> iterator { } // Delete the key from the leaf. - iter.node->remove_value(iter.position, mutable_allocator()); + iter.node->remove_values(iter.position, /*to_erase=*/1, mutable_allocator()); --size_; // We want to return the next value after the one we just erased. If we @@ -2121,7 +2148,9 @@ auto btree<P>::erase_range(iterator begin, iterator end) } if (begin.node == end.node) { - erase_same_node(begin, end); + assert(end.position > begin.position); + begin.node->remove_values(begin.position, end.position - begin.position, + mutable_allocator()); size_ -= count; return {count, rebalance_after_delete(begin)}; } @@ -2131,8 +2160,11 @@ auto btree<P>::erase_range(iterator begin, iterator end) if (begin.node->leaf()) { const size_type remaining_to_erase = size_ - target_size; const size_type remaining_in_node = begin.node->finish() - begin.position; - begin = erase_from_leaf_node( - begin, (std::min)(remaining_to_erase, remaining_in_node)); + const size_type to_erase = + (std::min)(remaining_to_erase, remaining_in_node); + begin.node->remove_values(begin.position, to_erase, mutable_allocator()); + size_ -= to_erase; + begin = rebalance_after_delete(begin); } else { begin = erase(begin); } @@ -2141,51 +2173,6 @@ auto btree<P>::erase_range(iterator begin, iterator end) } template <typename P> -void btree<P>::erase_same_node(iterator begin, iterator end) { - assert(begin.node == end.node); - assert(end.position > begin.position); - - node_type *node = begin.node; - size_type to_erase = end.position - begin.position; - if (!node->leaf()) { - // Delete all children between begin and end. - for (size_type i = 0; i < to_erase; ++i) { - internal_clear(node->child(begin.position + i + 1)); - } - // Rotate children after end into new positions. - for (size_type i = begin.position + to_erase + 1; i <= node->finish(); - ++i) { - node->set_child(i - to_erase, node->child(i)); - node->clear_child(i); - } - } - node->remove_values_ignore_children(begin.position, to_erase, - mutable_allocator()); - - // Do not need to update rightmost_, because - // * either end == this->end(), and therefore node == rightmost_, and still - // exists - // * or end != this->end(), and therefore rightmost_ hasn't been erased, since - // it wasn't covered in [begin, end) -} - -template <typename P> -auto btree<P>::erase_from_leaf_node(iterator begin, size_type to_erase) - -> iterator { - node_type *node = begin.node; - assert(node->leaf()); - assert(node->finish() > begin.position); - assert(begin.position + to_erase <= node->finish()); - - node->remove_values_ignore_children(begin.position, to_erase, - mutable_allocator()); - - size_ -= to_erase; - - return rebalance_after_delete(begin); -} - -template <typename P> template <typename K> auto btree<P>::erase_unique(const K &key) -> size_type { const iterator iter = internal_find(key); @@ -2213,7 +2200,7 @@ auto btree<P>::erase_multi(const K &key) -> size_type { template <typename P> void btree<P>::clear() { if (!empty()) { - internal_clear(root()); + node_type::clear_and_delete(root(), mutable_allocator()); } mutable_root() = EmptyNode(); rightmost_ = EmptyNode(); @@ -2354,12 +2341,7 @@ void btree<P>::rebalance_or_split(iterator *iter) { template <typename P> void btree<P>::merge_nodes(node_type *left, node_type *right) { left->merge(right, mutable_allocator()); - if (right->leaf()) { - if (rightmost_ == right) rightmost_ = left; - delete_leaf_node(right); - } else { - delete_internal_node(right); - } + if (rightmost_ == right) rightmost_ = left; } template <typename P> @@ -2416,20 +2398,20 @@ bool btree<P>::try_merge_or_rebalance(iterator *iter) { template <typename P> void btree<P>::try_shrink() { - if (root()->count() > 0) { + node_type *orig_root = root(); + if (orig_root->count() > 0) { return; } // Deleted the last item on the root node, shrink the height of the tree. - if (root()->leaf()) { + if (orig_root->leaf()) { assert(size() == 0); - delete_leaf_node(root()); mutable_root() = rightmost_ = EmptyNode(); } else { - node_type *child = root()->start_child(); + node_type *child = orig_root->start_child(); child->make_root(); - delete_internal_node(root()); mutable_root() = child; } + node_type::clear_and_delete(orig_root, mutable_allocator()); } template <typename P> @@ -2474,7 +2456,7 @@ inline auto btree<P>::internal_emplace(iterator iter, Args &&... args) old_root->start(), old_root, alloc); new_root->set_finish(old_root->finish()); old_root->set_finish(old_root->start()); - delete_leaf_node(old_root); + node_type::clear_and_delete(old_root, alloc); mutable_root() = rightmost_ = new_root; } else { rebalance_or_split(&iter); @@ -2578,18 +2560,6 @@ auto btree<P>::internal_find(const K &key) const -> iterator { } template <typename P> -void btree<P>::internal_clear(node_type *node) { - if (!node->leaf()) { - for (int i = node->start(); i <= node->finish(); ++i) { - internal_clear(node->child(i)); - } - delete_internal_node(node); - } else { - delete_leaf_node(node); - } -} - -template <typename P> int btree<P>::internal_verify(const node_type *node, const key_type *lo, const key_type *hi) const { assert(node->count() > 0); diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index 536ea398..92a61cc0 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -429,13 +429,6 @@ struct map_slot_policy { std::move(src->value)); } } - - template <class Allocator> - static void move(Allocator* alloc, slot_type* first, slot_type* last, - slot_type* result) { - for (slot_type *src = first, *dest = result; src != last; ++src, ++dest) - move(alloc, src, dest); - } }; } // namespace container_internal |