diff --git a/src/3rdparty/cpp-btree/README b/src/3rdparty/cpp-btree/README index de596b58c0..f3183bd4f2 100644 --- a/src/3rdparty/cpp-btree/README +++ b/src/3rdparty/cpp-btree/README @@ -40,6 +40,9 @@ Changes include: - Adding key_comp - Adding move constructors/assignment. - No longer #define NDEBUG if unset, this can clash with other headers, test for BTREE_DEBUG being defined instead +- Add noexcept to swap-based move constructors and copy/move assignment operator +- Remove use of deprecated std::allocator::rebind type +- Adding support for uncopyable/move-only map/multimap values (not keys). CMakeLists-pthreads-fix.txt is a modified copy of CMakeLists.txt which includes -lpthreads when building the tests/benchmarks. Using this instead fixes compilation on some platforms. diff --git a/src/3rdparty/cpp-btree/btree.h b/src/3rdparty/cpp-btree/btree.h index 15b0ee0621..191497b4d2 100644 --- a/src/3rdparty/cpp-btree/btree.h +++ b/src/3rdparty/cpp-btree/btree.h @@ -649,9 +649,14 @@ class btree_node { return s; } +private: + void insert_value_common(int i); + +public: // Inserts the value x at position i, shifting all existing values and // children at positions >= i to the right by 1. - void insert_value(int i, const value_type &x); + template + void insert_value(int i, Args&&... args); // Removes the value at position i, shifting all existing values and children // at positions > i to the left by 1. @@ -709,8 +714,9 @@ class btree_node { void value_init(int i) { new (&fields_.values[i]) mutable_value_type; } - void value_init(int i, const value_type &x) { - new (&fields_.values[i]) mutable_value_type(x); + template + void value_init_args(int i, Args&&... args) { + new (&fields_.values[i]) mutable_value_type(std::forward(args)...); } void value_destroy(int i) { fields_.values[i].~mutable_value_type(); @@ -1002,45 +1008,65 @@ class btree : public Params::key_compare { // Inserts a value into the btree only if it does not already exist. The // boolean return value indicates whether insertion succeeded or failed. The - // ValuePointer type is used to avoid instatiating the value unless the key - // is being inserted. Value is not dereferenced if the key already exists in - // the btree. See btree_map::operator[]. - template - std::pair insert_unique(const key_type &key, ValuePointer value); + // Args&&... type is used to avoid instatiating the value unless the key + // is being inserted. See btree_map::operator[]. + template + std::pair insert_unique_args(const key_type &key, Args&&... args); // Inserts a value into the btree only if it does not already exist. The // boolean return value indicates whether insertion succeeded or failed. std::pair insert_unique(const value_type &v) { - return insert_unique(params_type::key(v), &v); + return insert_unique_args(params_type::key(v), v); } + std::pair insert_unique(value_type &&v) { + return insert_unique_args(params_type::key(v), std::move(v)); + } + + template + iterator insert_unique_hint_args(iterator position, const key_type &key, Args&&... args); // Insert with hint. Check to see if the value should be placed immediately // before position in the tree. If it does, then the insertion will take // amortized constant time. If not, the insertion will take amortized // logarithmic time as if a call to insert_unique(v) were made. - iterator insert_unique(iterator position, const value_type &v); + iterator insert_unique(iterator position, const value_type &v) { + return insert_unique_hint_args(position, params_type::key(v), v); + } + iterator insert_unique(iterator position, value_type &&v) { + return insert_unique_hint_args(position, params_type::key(v), std::move(v)); + } // Insert a range of values into the btree. template void insert_unique(InputIterator b, InputIterator e); - // Inserts a value into the btree. The ValuePointer type is used to avoid - // instatiating the value unless the key is being inserted. Value is not - // dereferenced if the key already exists in the btree. See + // Inserts a value into the btree. The Args&&... type is used to avoid + // instatiating the value unless the key is being inserted. See // btree_map::operator[]. - template - iterator insert_multi(const key_type &key, ValuePointer value); + template + iterator insert_multi_args(const key_type &key, Args&&... args); // Inserts a value into the btree. iterator insert_multi(const value_type &v) { - return insert_multi(params_type::key(v), &v); + return insert_multi_args(params_type::key(v), v); } + iterator insert_multi(value_type &&v) { + return insert_multi_args(params_type::key(v), std::move(v)); + } + + template + iterator insert_multi_hint_args(iterator position, const key_type &key, Args&&... args); // Insert with hint. Check to see if the value should be placed immediately // before position in the tree. If it does, then the insertion will take // amortized constant time. If not, the insertion will take amortized // logarithmic time as if a call to insert_multi(v) were made. - iterator insert_multi(iterator position, const value_type &v); + iterator insert_multi(iterator position, const value_type &v) { + return insert_multi_hint_args(position, params_type::key(v), v); + } + iterator insert_multi(iterator position, value_type &&v) { + return insert_multi_hint_args(position, params_type::key(v), std::move(v)); + } // Insert a range of values into the btree. template @@ -1305,9 +1331,12 @@ class btree : public Params::key_compare { return iter.node ? iter : end(); } + iterator internal_insert_common(iterator iter); + // Inserts a value into the btree immediately before iter. Requires that // key(v) <= iter.key() and (--iter).key() <= key(v). - iterator internal_insert(iterator iter, const value_type &v); + template + iterator internal_insert(iterator iter, Args&&... args); // Returns an iterator pointing to the first value >= the value "iter" is // pointing at. Note that "iter" might be pointing to an invalid location as @@ -1420,10 +1449,15 @@ class btree : public Params::key_compare { //// // btree_node methods -template -inline void btree_node

::insert_value(int i, const value_type &x) { +template template +inline void btree_node

::insert_value(int i, Args&&... args) { dbg_assert(i <= count()); - value_init(count(), x); + value_init_args(count(), std::forward(args)...); + insert_value_common(i); +} + +template +inline void btree_node

::insert_value_common(int i) { for (int j = count(); j > i; --j) { value_swap(j, this, j - 1); } @@ -1576,7 +1610,7 @@ void btree_node

::split(btree_node *dest, int insert_position) { // The split key is the largest value in the left sibling. set_count(count() - 1); - parent()->insert_value(position(), value_type()); + parent()->insert_value(position()); value_swap(count(), parent(), position()); value_destroy(count()); parent()->set_child(position() + 1, dest); @@ -1741,9 +1775,9 @@ btree

::btree(const self_type &x) assign(x); } -template template +template template std::pair::iterator, bool> -btree

::insert_unique(const key_type &key, ValuePointer value) { +btree

::insert_unique_args(const key_type &key, Args&&... args) { if (empty()) { *mutable_root() = new_leaf_root_node(1); } @@ -1761,34 +1795,33 @@ btree

::insert_unique(const key_type &key, ValuePointer value) { } } - return std::make_pair(internal_insert(iter, *value), true); + return std::make_pair(internal_insert(iter, std::forward(args)...), true); } -template +template template inline typename btree

::iterator -btree

::insert_unique(iterator position, const value_type &v) { +btree

::insert_unique_hint_args(iterator position, const key_type &key, Args&&... args) { if (!empty()) { - const key_type &key = params_type::key(v); const iterator end = this->end(); if (position == end || compare_keys(key, position.key())) { iterator prev = position; if (position == begin() || compare_keys((--prev).key(), key)) { // prev.key() < key < position.key() - return internal_insert(position, v); + return internal_insert(position, std::forward(args)...); } } else if (compare_keys(position.key(), key)) { iterator next = position; ++next; if (next == end || compare_keys(key, next.key())) { // position.key() < key < next.key() - return internal_insert(next, v); + return internal_insert(next, std::forward(args)...); } } else { // position.key() == key return position; } } - return insert_unique(v).first; + return insert_unique_args(key, std::forward(args)...).first; } template template @@ -1798,9 +1831,9 @@ void btree

::insert_unique(InputIterator b, InputIterator e) { } } -template template +template template typename btree

::iterator -btree

::insert_multi(const key_type &key, ValuePointer value) { +btree

::insert_multi_args(const key_type &key, Args&&... args) { if (empty()) { *mutable_root() = new_leaf_root_node(1); } @@ -1809,31 +1842,31 @@ btree

::insert_multi(const key_type &key, ValuePointer value) { if (!iter.node) { iter = end(); } - return internal_insert(iter, *value); + return internal_insert(iter, std::forward(args)...); } -template + +template template typename btree

::iterator -btree

::insert_multi(iterator position, const value_type &v) { +btree

::insert_multi_hint_args(iterator position, const key_type &key, Args&&... args) { if (!empty()) { - const key_type &key = params_type::key(v); const iterator end = this->end(); if (position == end || !compare_keys(position.key(), key)) { iterator prev = position; if (position == begin() || !compare_keys(key, (--prev).key())) { // prev.key() <= key <= position.key() - return internal_insert(position, v); + return internal_insert(position, std::forward(args)...); } } else { iterator next = position; ++next; if (next == end || !compare_keys(next.key(), key)) { // position.key() < key <= next.key() - return internal_insert(next, v); + return internal_insert(next, std::forward(args)...); } } } - return insert_multi(v); + return insert_multi_args(key, std::forward(args)...); } template template @@ -2202,7 +2235,7 @@ inline IterType btree

::internal_last(IterType iter) { template inline typename btree

::iterator -btree

::internal_insert(iterator iter, const value_type &v) { +btree

::internal_insert_common(iterator iter) { if (!iter.node->leaf()) { // We can't insert on an internal node. Instead, we'll insert after the // previous value which is guaranteed to be on a leaf node. @@ -2227,7 +2260,14 @@ btree

::internal_insert(iterator iter, const value_type &v) { } else if (!root()->leaf()) { ++*mutable_size(); } - iter.node->insert_value(iter.position, v); + return iter; +} + +template template +inline typename btree

::iterator +btree

::internal_insert(iterator iter, Args&&... args) { + iter = internal_insert_common(iter); + iter.node->insert_value(iter.position, std::forward(args)...); return iter; } diff --git a/src/3rdparty/cpp-btree/btree_container.h b/src/3rdparty/cpp-btree/btree_container.h index c62c1af8aa..5a429b5823 100644 --- a/src/3rdparty/cpp-btree/btree_container.h +++ b/src/3rdparty/cpp-btree/btree_container.h @@ -201,9 +201,15 @@ class btree_unique_container : public btree_container { std::pair insert(const value_type &x) { return this->tree_.insert_unique(x); } + std::pair insert(value_type &&x) { + return this->tree_.insert_unique(std::move(x)); + } iterator insert(iterator position, const value_type &x) { return this->tree_.insert_unique(position, x); } + iterator insert(iterator position, value_type &&x) { + return this->tree_.insert_unique(position, std::move(x)); + } template void insert(InputIterator b, InputIterator e) { this->tree_.insert_unique(b, e); @@ -238,21 +244,6 @@ class btree_map_container : public btree_unique_container { typedef typename Tree::key_compare key_compare; typedef typename Tree::allocator_type allocator_type; - private: - // A pointer-like object which only generates its value when - // dereferenced. Used by operator[] to avoid constructing an empty data_type - // if the key already exists in the map. - struct generate_value { - generate_value(const key_type &k) - : key(k) { - } - value_type operator*() const { - return std::make_pair(key, data_type()); - } - const key_type &key; - }; - - public: // Default constructor. btree_map_container(const key_compare &comp = key_compare(), const allocator_type &alloc = allocator_type()) @@ -274,7 +265,7 @@ class btree_map_container : public btree_unique_container { // Insertion routines. data_type& operator[](const key_type &key) { - return this->tree_.insert_unique(key, generate_value(key)).first->second; + return this->tree_.insert_unique_args(key, std::piecewise_construct, std::forward_as_tuple(key), std::make_tuple()).first->second; } }; @@ -329,9 +320,15 @@ class btree_multi_container : public btree_container { iterator insert(const value_type &x) { return this->tree_.insert_multi(x); } + iterator insert(value_type &&x) { + return this->tree_.insert_multi(std::move(x)); + } iterator insert(iterator position, const value_type &x) { return this->tree_.insert_multi(position, x); } + iterator insert(iterator position, value_type &&x) { + return this->tree_.insert_multi(position, std::move(x)); + } template void insert(InputIterator b, InputIterator e) { this->tree_.insert_multi(b, e); diff --git a/src/3rdparty/cpp-btree/safe_btree.h b/src/3rdparty/cpp-btree/safe_btree.h index f4e0297917..d979c81653 100644 --- a/src/3rdparty/cpp-btree/safe_btree.h +++ b/src/3rdparty/cpp-btree/safe_btree.h @@ -274,36 +274,64 @@ class safe_btree { } // Insertion routines. - template - std::pair insert_unique(const key_type &key, ValuePointer value) { - std::pair p = tree_.insert_unique(key, value); + template + std::pair insert_unique_args(const key_type &key, Args&&... args) { + std::pair p = tree_.insert_unique_args(key, std::forward(args)...); generation_ += p.second; return std::make_pair(iterator(this, p.first), p.second); } - std::pair insert_unique(const value_type &v) { - std::pair p = tree_.insert_unique(v); - generation_ += p.second; - return std::make_pair(iterator(this, p.first), p.second); + std::pair insert_unique(const value_type &v) { + return insert_unique_args(params_type::key(v), v); } - iterator insert_unique(iterator position, const value_type &v) { + std::pair insert_unique(value_type &&v) { + return insert_unique_args(params_type::key(v), std::move(v)); + } + + template + iterator insert_unique_hint_args(iterator position, const key_type &key, Args&&... args) { tree_iterator tree_pos = position.iter(); ++generation_; - return iterator(this, tree_.insert_unique(tree_pos, v)); + return iterator(this, tree_.insert_unique_hint_args(tree_pos, key, std::forward(args)...)); } + iterator insert_unique(iterator position, const value_type &v) { + return insert_unique_hint_args(position, params_type::key(v), v); + } + iterator insert_unique(iterator position, value_type &&v) { + return insert_unique_hint_args(position, params_type::key(v), std::move(v)); + } + template void insert_unique(InputIterator b, InputIterator e) { for (; b != e; ++b) { insert_unique(*b); } } - iterator insert_multi(const value_type &v) { + + template + iterator insert_multi_args(const key_type &key, Args&&... args) { ++generation_; - return iterator(this, tree_.insert_multi(v)); + return iterator(this, tree_.insert_multi_args(key, std::forward(args)...)); } - iterator insert_multi(iterator position, const value_type &v) { + + iterator insert_multi(const value_type &v) { + return insert_multi_args(params_type::key(v), v); + } + iterator insert_multi(value_type &&v) { + return insert_multi_args(params_type::key(v), std::move(v)); + } + + template + iterator insert_multi_hint_args(iterator position, const key_type &key, Args&&... args) { tree_iterator tree_pos = position.iter(); ++generation_; - return iterator(this, tree_.insert_multi(tree_pos, v)); + return iterator(this, tree_.insert_multi_hint_args(tree_pos, key, std::forward(args)...)); + } + + iterator insert_multi(iterator position, const value_type &v) { + return insert_multi_hint_args(position, params_type::key(v), v); + } + iterator insert_multi(iterator position, value_type &&v) { + return insert_multi_hint_args(position, params_type::key(v), std::move(v)); } template void insert_multi(InputIterator b, InputIterator e) {