diff options
author | Billy Donahue <billy.donahue@mongodb.com> | 2023-05-09 16:33:30 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-05-09 21:51:49 +0000 |
commit | f439c82251932419f9eae69fd48358132cce58e7 (patch) | |
tree | 9acdd4029bee4c7baca43a90c3d8ba292e417e0b | |
parent | b6eab7e7d83b10cef5c57f781c1751b465aade9f (diff) | |
download | mongo-f439c82251932419f9eae69fd48358132cce58e7.tar.gz |
SERVER-39506 destroying delete for RCString
-rw-r--r-- | src/mongo/db/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/exec/document_value/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/exec/document_value/value_internal.h | 69 | ||||
-rw-r--r-- | src/mongo/util/SConscript | 10 | ||||
-rw-r--r-- | src/mongo/util/intrusive_counter.cpp | 60 | ||||
-rw-r--r-- | src/mongo/util/intrusive_counter.h | 46 |
6 files changed, 72 insertions, 115 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index d0debcf9e1f..2d5d9447d8e 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1657,7 +1657,6 @@ env.Library( '$BUILD_DIR/mongo/crypto/fle_crypto', '$BUILD_DIR/mongo/scripting/scripting', '$BUILD_DIR/mongo/scripting/scripting_common', - '$BUILD_DIR/mongo/util/intrusive_counter', '$BUILD_DIR/mongo/util/pcre_util', '$BUILD_DIR/mongo/util/pcre_wrapper', '$BUILD_DIR/mongo/util/summation', diff --git a/src/mongo/db/exec/document_value/SConscript b/src/mongo/db/exec/document_value/SConscript index 9d0947da749..5899cb089fc 100644 --- a/src/mongo/db/exec/document_value/SConscript +++ b/src/mongo/db/exec/document_value/SConscript @@ -15,7 +15,6 @@ env.Library( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/pipeline/field_path', '$BUILD_DIR/mongo/db/query/datetime/date_time_support', - '$BUILD_DIR/mongo/util/intrusive_counter', ], ) diff --git a/src/mongo/db/exec/document_value/value_internal.h b/src/mongo/db/exec/document_value/value_internal.h index b19af0e728f..8f36c8f800e 100644 --- a/src/mongo/db/exec/document_value/value_internal.h +++ b/src/mongo/db/exec/document_value/value_internal.h @@ -30,14 +30,20 @@ #pragma once #include <algorithm> +#include <cstdlib> +#include <new> + #include <boost/intrusive_ptr.hpp> #include "mongo/base/static_assert.h" +#include "mongo/base/string_data.h" #include "mongo/bson/bsonmisc.h" #include "mongo/bson/bsonobj.h" #include "mongo/bson/bsontypes.h" #include "mongo/bson/oid.h" #include "mongo/bson/timestamp.h" +#include "mongo/bson/util/builder.h" +#include "mongo/util/assert_util.h" #include "mongo/util/debug_util.h" #include "mongo/util/intrusive_counter.h" @@ -47,6 +53,67 @@ class Document; class DocumentStorage; class Value; + +/** An immutable reference-counted string of inline data. */ +class RCString final : public RefCountable { +public: + static boost::intrusive_ptr<const RCString> create(StringData s) { + using namespace fmt::literals; + static constexpr size_t sizeLimit = BSONObjMaxUserSize; + uassert(16493, + "RCString too large. Requires size={} < limit={}"_format(s.size(), sizeLimit), + s.size() < sizeLimit); + return boost::intrusive_ptr{new (s) RCString{s}}; + } + + explicit operator StringData() const noexcept { + return StringData{_data(), _size}; + } + + void* operator new(size_t, StringData s) { + return ::operator new(_allocSize(s.size())); + } + + /** Used if constructor fails after placement `new (StringData)`. */ + void operator delete(void* ptr, StringData s) { + ::operator delete(ptr, _allocSize(s.size())); + } + +#if __cpp_lib_destroying_delete >= 201806L + void operator delete(RCString* ptr, std::destroying_delete_t) { + size_t sz = _allocSize(ptr->_size); + ptr->~RCString(); + ::operator delete(ptr, sz); + } +#else // !__cpp_lib_destroying_delete + /** Invoked by virtual destructor. */ + void operator delete(void* ptr) { + ::operator delete(ptr); + } +#endif // __cpp_lib_destroying_delete + +private: + static size_t _allocSize(size_t stringSize) { + return sizeof(RCString) + stringSize + 1; // Incl. '\0'-terminator + } + + /** Use static `create()` instead. */ + explicit RCString(StringData s) : _size{s.size()} { + if (_size) + memcpy(_data(), s.rawData(), _size); + _data()[_size] = '\0'; + } + + const char* _data() const noexcept { + return reinterpret_cast<const char*>(this + 1); + } + char* _data() noexcept { + return const_cast<char*>(std::as_const(*this)._data()); + } + + size_t _size; /** Excluding '\0' terminator. */ +}; + // TODO: a MutableVector, similar to MutableDocument /// A heap-allocated reference-counted std::vector class RCVector : public RefCountable { @@ -268,7 +335,7 @@ public: } else { dassert(typeid(*genericRCPtr) == typeid(const RCString)); const RCString* stringPtr = static_cast<const RCString*>(genericRCPtr); - return StringData(stringPtr->c_str(), stringPtr->size()); + return StringData{*stringPtr}; } } diff --git a/src/mongo/util/SConscript b/src/mongo/util/SConscript index 4f92d284478..aff0ed44fef 100644 --- a/src/mongo/util/SConscript +++ b/src/mongo/util/SConscript @@ -115,16 +115,6 @@ env.Library( ) env.Library( - target='intrusive_counter', - source=[ - 'intrusive_counter.cpp', - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/base', - ], -) - -env.Library( target='log_and_backoff', source=[ 'log_and_backoff.cpp', diff --git a/src/mongo/util/intrusive_counter.cpp b/src/mongo/util/intrusive_counter.cpp deleted file mode 100644 index e33cbc87da5..00000000000 --- a/src/mongo/util/intrusive_counter.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (C) 2018-present MongoDB, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the Server Side Public License, version 1, - * as published by MongoDB, Inc. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Server Side Public License for more details. - * - * You should have received a copy of the Server Side Public License - * along with this program. If not, see - * <http://www.mongodb.com/licensing/server-side-public-license>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the Server Side Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/util/intrusive_counter.h" - -#include "mongo/util/str.h" - -namespace mongo { -using boost::intrusive_ptr; - -intrusive_ptr<const RCString> RCString::create(StringData s) { - uassert(16493, - str::stream() << "Tried to create string longer than " - << (BSONObjMaxUserSize / 1024 / 1024) << "MB", - s.size() < static_cast<size_t>(BSONObjMaxUserSize)); - - const size_t sizeWithNUL = s.size() + 1; - const size_t bytesNeeded = sizeof(RCString) + sizeWithNUL; - -#pragma warning(push) -#pragma warning(disable : 4291) - intrusive_ptr<RCString> ptr = new (bytesNeeded) RCString(); // uses custom operator new -#pragma warning(pop) - - ptr->_size = s.size(); - char* stringStart = reinterpret_cast<char*>(ptr.get()) + sizeof(RCString); - s.copyTo(stringStart, true); - - return ptr; -} - -} // namespace mongo diff --git a/src/mongo/util/intrusive_counter.h b/src/mongo/util/intrusive_counter.h index 38d024ddea6..9041f50d937 100644 --- a/src/mongo/util/intrusive_counter.h +++ b/src/mongo/util/intrusive_counter.h @@ -29,12 +29,11 @@ #pragma once +#include <atomic> // NOLINT #include <boost/intrusive_ptr.hpp> #include <cstdlib> -#include "mongo/base/string_data.h" -#include "mongo/platform/atomic_word.h" -#include "mongo/util/allocator.h" +#include "mongo/util/assert_util_core.h" namespace mongo { @@ -67,13 +66,13 @@ public: // See this for a description of why relaxed is OK here. It is also used in libc++. // http://www.boost.org/doc/libs/1_66_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_reference_counters.discussion ptr->_count.fetch_add(1, std::memory_order_relaxed); - }; + } friend void intrusive_ptr_release(const RefCountable* ptr) { if (ptr->_count.fetch_sub(1, std::memory_order_acq_rel) == 1) { delete ptr; } - }; + } protected: /** @@ -101,41 +100,4 @@ boost::intrusive_ptr<T> make_intrusive(Args&&... args) { ptr->threadUnsafeIncRefCountTo(1); return boost::intrusive_ptr<T>(ptr, /*add ref*/ false); } - -/// This is an immutable reference-counted string -class RCString : public RefCountable { -public: - const char* c_str() const { - return reinterpret_cast<const char*>(this) + sizeof(RCString); - } - int size() const { - return _size; - } - StringData stringData() const { - return StringData(c_str(), _size); - } - - static boost::intrusive_ptr<const RCString> create(StringData s); - -// MSVC: C4291: 'declaration' : no matching operator delete found; memory will not be freed if -// initialization throws an exception -// We simply rely on the default global placement delete since a local placement delete would be -// ambiguous for some compilers -#pragma warning(push) -#pragma warning(disable : 4291) - void operator delete(void* ptr) { - free(ptr); - } -#pragma warning(pop) - -private: - // these can only be created by calling create() - RCString(){}; - void* operator new(size_t objSize, size_t realSize) { - return mongoMalloc(realSize); - } - - int _size; // does NOT include trailing NUL byte. - // char[_size+1] array allocated past end of class -}; } // namespace mongo |