diff --git a/SConstruct b/SConstruct index 7cae5fdb90f..b4f00c895e2 100644 --- a/SConstruct +++ b/SConstruct @@ -214,8 +214,8 @@ add_option( "cc", "compiler to use for c" , 1 , True ) add_option( "cc-use-shell-environment", "use $CC from shell for C compiler" , 0 , False ) add_option( "cxx-use-shell-environment", "use $CXX from shell for C++ compiler" , 0 , False ) add_option( "ld", "linker to use" , 1 , True ) -add_option( "c++11", "enable c++11 support (experimental)", "?", True, - type="choice", choices=["on", "off", "auto"], const="on", default="auto" ) +add_option( "c++11", "enable c++11 support", "?", True, + type="choice", choices=["on", "off", "auto"], const="on", default="on" ) add_option( "disable-minimum-compiler-version-enforcement", "allow use of unsupported older compilers (NEVER for production builds)", 0, False ) @@ -440,6 +440,10 @@ if GetOption('help'): # --- environment setup --- +if get_option("c++11") != "on": + print("MongoDB requires C++11 to build") + Exit(1) + # If the user isn't using the # to indicate top-of-tree or $ to expand a variable, forbid # relative paths. Relative paths don't really work as expected, because they end up relative to # the top level SConstruct, not the invokers CWD. We could in theory fix this with @@ -1572,26 +1576,65 @@ def doConfigure(myenv): usingLibStdCxx = conf.CheckLibStdCxx() conf.Finish() - # Check to see if we are trying to use an elderly libstdc++, which we arbitrarily define as - # 4.6.0. This is primarly to help people using clang in C++11 mode on OS X but forgetting - # to use --libc++. We also use it to decide if we trust the libstdc++ debug mode. We would, - # ideally, check the __GLIBCXX__ version, but for various reasons this is not - # workable. Instead, we switch on the fact that _GLIBCXX_BEGIN_NAMESPACE_VERSION wasn't - # introduced until libstdc++ 4.6.0. + if not using_msvc(): + if not AddToCXXFLAGSIfSupported(myenv, '-std=c++11'): + print( 'Compiler does not honor -std=c++11' ) + Exit(1) + if not AddToCFLAGSIfSupported(myenv, '-std=c99'): + print( "C++11 mode selected for C++ files, but can't enable C99 for C files" ) + Exit(1) - haveGoodLibStdCxx = False + if using_system_version_of_cxx_libraries(): + print( 'WARNING: System versions of C++ libraries must be compiled with C++11 support' ) + + # We appear to have C++11, or at least a flag to enable it. Check that the declared C++ + # language level is not less than C++11, and that we can at least compile an 'auto' + # expression. We don't check the __cplusplus macro when using MSVC because as of our + # current required MS compiler version (MSVS 2013 Update 2), they don't set it. If + # MSFT ever decides (in MSVS 2015?) to define __cplusplus >= 201103L, remove the exception + # here for _MSC_VER + def CheckCxx11(context): + test_body = """ + #ifndef _MSC_VER + #if __cplusplus < 201103L + #error + #endif + #endif + auto not_an_empty_file = 0; + """ + + context.Message('Checking for C++11... ') + ret = context.TryCompile(textwrap.dedent(test_body), ".cpp") + context.Result(ret) + return ret + + conf = Configure(myenv, help=False, custom_tests = { + 'CheckCxx11' : CheckCxx11, + }) + + if not conf.CheckCxx11(): + print( 'C++11 support is required to build MongoDB') + Exit(1) + + conf.Finish() + + # If we are using libstdc++, check to see if we are using a libstdc++ that is older than + # our GCC minimum of 4.8.2. This is primarly to help people using clang on OS X but + # forgetting to use --libc++ (or set the target OS X version high enough to get it as the + # default). We would, ideally, check the __GLIBCXX__ version, but for various reasons this + # is not workable. Instead, we switch on the fact that _GLIBCXX_PROFILE_UNORDERED wasn't + # introduced until libstdc++ 4.8.2. Yes, this is a terrible hack. if usingLibStdCxx: - def CheckModernLibStdCxx(context): - test_body = """ - #include - #if !defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION) - #error libstdcxx older than 4.6.0 + #define _GLIBCXX_PROFILE + #include + #if !defined(_GLIBCXX_PROFILE_UNORDERED) + #error libstdc++ older than 4.8.2 #endif """ - context.Message('Checking for libstdc++ 4.6.0 or better... ') + context.Message('Checking for libstdc++ 4.8.2 or better... ') ret = context.TryCompile(textwrap.dedent(test_body), ".cpp") context.Result(ret) return ret @@ -1599,111 +1642,23 @@ def doConfigure(myenv): conf = Configure(myenv, help=False, custom_tests = { 'CheckModernLibStdCxx' : CheckModernLibStdCxx, }) - haveGoodLibStdCxx = conf.CheckModernLibStdCxx() + + if not conf.CheckModernLibStdCxx(): + print("When using libstdc++, MongoDB requires libstdc++ 4.8.2 or newer") + Exit(1) + conf.Finish() - # Sort out whether we can and should use C++11: - cxx11_mode = get_option("c++11") - - if using_msvc(): - if cxx11_mode == "off": - print( 'WARNING: Cannot disable C++11 features when using MSVC' ) - else: - - # In C++11 'auto' mode, don't use C++11 if we are linking against any system C++ libs. - if cxx11_mode == "auto" and using_system_version_of_cxx_libraries(): - cxx11_mode = "off" - - # If we are using libstdc++, only allow C++11 mode with our line-in-the-sand good - # libstdc++. As always, if in auto mode fall back to disabling if we don't have a good - # libstdc++, otherwise fail the build because we can't honor the explicit request. - if cxx11_mode != "off" and usingLibStdCxx: - if not haveGoodLibStdCxx: - if cxx11_mode == "auto": - cxx11_mode = "off" - else: - print( 'Detected libstdc++ is too old to support C++11 mode' ) - if darwin: - print( 'Try building with --libc++ and --osx-version-min=10.7 or higher' ) - Exit(1) - - # We are going to be adding flags to the environment, but we don't want to persist - # those changes unless we pass all the below checks. Make a copy of the environment - # that we will modify, we will only "commit" the changes to the env if we pass all the - # checks. - cxx11Env = myenv.Clone() - - # For our other compilers (gcc and clang) we need to pass -std=c++0x or -std=c++11, - # but we prefer the latter. Try that first, and fall back to c++0x if we don't - # detect that --std=c++11 works. If we can't find a flag and C++11 was explicitly - # requested, error out, otherwise turn off C++11 support in auto mode. - if cxx11_mode != "off": - if not AddToCXXFLAGSIfSupported(cxx11Env, '-std=c++11'): - if not AddToCXXFLAGSIfSupported(cxx11Env, '-std=c++0x'): - if cxx11_mode == "auto": - cxx11_mode = "off" - else: - print( 'C++11 mode requested, but cannot find a flag to enable it' ) - Exit(1) - - # We appear to have C++11, or at least a flag to enable it, which is now set in the - # environment. If we are in auto mode, check if the compiler claims that it strictly - # supports C++11, and disable C++11 if not. If the user has explicitly requested C++11, - # we don't care about what the compiler claims to support, trust the user. - if cxx11_mode == "auto": - def CheckCxx11Official(context): - test_body = """ - #if __cplusplus < 201103L - #error - #endif - const int not_an_empty_file = 0; - """ - - context.Message('Checking if __cplusplus >= 201103L to auto-enable C++11... ') - ret = context.TryCompile(textwrap.dedent(test_body), ".cpp") - context.Result(ret) - return ret - - conf = Configure(cxx11Env, help=False, custom_tests = { - 'CheckCxx11Official' : CheckCxx11Official, - }) - - if cxx11_mode == "auto" and not conf.CheckCxx11Official(): - cxx11_mode = "off" - - conf.Finish() - - # We require c99 mode for C files when C++11 is enabled, so perform the same dance - # as above: if C++11 mode is not off, try the flag, if we are in auto mode and we fail - # then turn off C++11, otherwise C++11 was explicitly requested and we should error out. - if cxx11_mode != "off": - if not AddToCFLAGSIfSupported(cxx11Env, '-std=c99'): - if cxx11_mode == "auto": - cxx11_mode = "off" - else: - print( "C++11 mode selected for C++ files, but can't enable C99 for C files" ) - Exit(1) - - # If we got here and cxx11_mode hasn't become false, then its true, so swap in the - # modified environment. - if cxx11_mode != "off": - cxx11_mode = "on" - myenv = cxx11Env - - # rocksdb requires C++11 mode - if has_option("rocksdb") and cxx11_mode == "off": - print("--rocksdb requires C++11 mode to be enabled"); - Exit(1) - if has_option("use-glibcxx-debug"): # If we are using a modern libstdc++ and this is a debug build and we control all C++ # dependencies, then turn on the debugging features in libstdc++. + # TODO: Need a new check here. if not debugBuild: print("--use-glibcxx-debug requires --dbg=on") Exit(1) - if not usingLibStdCxx or not haveGoodLibStdCxx: + if not usingLibStdCxx: print("--use-glibcxx-debug is only compatible with the GNU implementation of the " - "C++ standard libary, and requires minimum version 4.6") + "C++ standard libary") Exit(1) if using_system_version_of_cxx_libraries(): print("--use-glibcxx-debug not compatible with system versions of C++ libraries.") @@ -1944,61 +1899,6 @@ def doConfigure(myenv): if haveUUThread: myenv.Append(CPPDEFINES=['MONGO_HAVE___THREAD']) - def CheckCXX11Atomics(context): - test_body = """ - #include - int main(int argc, char **argv) { - std::atomic a(0); - return a.fetch_add(1); - } - """ - context.Message('Checking for C++11 support... ') - ret = context.TryLink(textwrap.dedent(test_body), '.cpp') - context.Result(ret) - return ret; - - def CheckGCCAtomicBuiltins(context): - test_body = """ - int main(int argc, char **argv) { - int a = 0; - int b = 0; - int c = 0; - - __atomic_compare_exchange(&a, &b, &c, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); - return 0; - } - """ - context.Message('Checking for gcc __atomic builtins... ') - ret = context.TryLink(textwrap.dedent(test_body), '.cpp') - context.Result(ret) - return ret - - def CheckGCCSyncBuiltins(context): - test_body = """ - int main(int argc, char **argv) { - int a = 0; - return __sync_fetch_and_add(&a, 1); - } - - // - // Figure out if we are using gcc older than 4.2 to target 32-bit x86. If so, error out - // even if we were able to compile the __sync statement, due to - // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40693 - // - #if defined(__i386__) - #if !defined(__clang__) - #if defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 2) - #error "Refusing to use __sync in 32-bit mode with gcc older than 4.2" - #endif - #endif - #endif - """ - - context.Message('Checking for useable __sync builtins... ') - ret = context.TryLink(textwrap.dedent(test_body), '.cpp') - context.Result(ret) - return ret - # not all C++11-enabled gcc versions have type properties def CheckCXX11IsTriviallyCopyable(context): test_body = """ @@ -2030,42 +1930,12 @@ def doConfigure(myenv): context.Result(ret) return ret + # Some GCC's don't have std::is_trivially_copyable conf = Configure(myenv, help=False, custom_tests = { - 'CheckCXX11Atomics': CheckCXX11Atomics, - 'CheckGCCAtomicBuiltins': CheckGCCAtomicBuiltins, - 'CheckGCCSyncBuiltins': CheckGCCSyncBuiltins, 'CheckCXX11IsTriviallyCopyable': CheckCXX11IsTriviallyCopyable, }) - # Figure out what atomics mode to use by way of the tests defined above. - # - # Non_windows: > __atomic > __sync - # Windows: > Interlocked functions / intrinsics. - # - # If we are in C++11 mode, try to use . This is unusual for us, as typically we - # only use __cplusplus >= 201103L to decide if we want to enable a feature. We make a - # special case for the atomics and use them on platforms that offer them even if they don't - # advertise full conformance. For MSVC systems, if we don't have then no more - # checks are required. Otherwise, we are on a GCC/clang system, where we may have __atomic - # or __sync, so try those in that order next. - # - # If we don't end up defining a MONGO_HAVE for the atomics, we will end up falling back to - # the Microsoft Interlocked functions/intrinsics when using MSVC, or the gcc_intel - # implementation of hand-rolled assembly if using gcc/clang. - - if (using_msvc() or (cxx11_mode == "on")) and conf.CheckCXX11Atomics(): - conf.env.Append(CPPDEFINES=['MONGO_HAVE_CXX11_ATOMICS']) - elif using_gcc() or using_clang(): - # Prefer the __atomic builtins. If we don't have those, try for __sync. Otherwise - # atomic_intrinsics.h will try to fall back to the hand-rolled assembly implementations - # in atomic_intrinsics_gcc_intel for x86 platforms. - if conf.CheckGCCAtomicBuiltins(): - conf.env.Append(CPPDEFINES=["MONGO_HAVE_GCC_ATOMIC_BUILTINS"]) - else: - if conf.CheckGCCSyncBuiltins(): - conf.env.Append(CPPDEFINES=["MONGO_HAVE_GCC_SYNC_BUILTINS"]) - - if (cxx11_mode == "on") and conf.CheckCXX11IsTriviallyCopyable(): + if conf.CheckCXX11IsTriviallyCopyable(): conf.env.Append(CPPDEFINES=['MONGO_HAVE_STD_IS_TRIVIALLY_COPYABLE']) myenv = conf.Finish() diff --git a/src/mongo/base/data_view.h b/src/mongo/base/data_view.h index 9b3bf3aa727..abc6b57f4c6 100644 --- a/src/mongo/base/data_view.h +++ b/src/mongo/base/data_view.h @@ -28,13 +28,10 @@ #pragma once #include +#include #include "mongo/platform/endian.h" -#if __cplusplus >= 201103L -#include -#endif - namespace mongo { class ConstDataView { diff --git a/src/mongo/base/status-inl.h b/src/mongo/base/status-inl.h index 221ba20e53d..880f548a87b 100644 --- a/src/mongo/base/status-inl.h +++ b/src/mongo/base/status-inl.h @@ -45,19 +45,17 @@ namespace mongo { return *this; } -#if __cplusplus >= 201103L - inline Status::Status(Status&& other) noexcept + inline Status::Status(Status&& other) BOOST_NOEXCEPT : _error(other._error) { other._error = nullptr; } - inline Status& Status::operator=(Status&& other) noexcept { + inline Status& Status::operator=(Status&& other) BOOST_NOEXCEPT { unref(_error); _error = other._error; other._error = nullptr; return *this; } -#endif // __cplusplus >= 201103L inline Status::~Status() { unref(_error); diff --git a/src/mongo/base/status.h b/src/mongo/base/status.h index 2b32ecc1a89..e8b82023179 100644 --- a/src/mongo/base/status.h +++ b/src/mongo/base/status.h @@ -27,6 +27,7 @@ #pragma once +#include #include #include @@ -75,10 +76,8 @@ namespace mongo { inline Status(const Status& other); inline Status& operator=(const Status& other); -#if __cplusplus >= 201103L - inline Status(Status&& other) noexcept; - inline Status& operator=(Status&& other) noexcept; -#endif // __cplusplus >= 201103L + inline Status(Status&& other) BOOST_NOEXCEPT; + inline Status& operator=(Status&& other) BOOST_NOEXCEPT; inline ~Status(); diff --git a/src/mongo/base/status_test.cpp b/src/mongo/base/status_test.cpp index 28d48c26b28..89184140ab7 100644 --- a/src/mongo/base/status_test.cpp +++ b/src/mongo/base/status_test.cpp @@ -67,7 +67,6 @@ namespace { ASSERT_EQUALS(orig.refCount(), 2U); } -#if __cplusplus >= 201103L TEST(Cloning, MoveCopyOK) { Status orig = Status::OK(); ASSERT_TRUE(orig.isOK()); @@ -184,8 +183,6 @@ namespace { ASSERT_EQUALS(dest.refCount(), 0U); } -#endif // __cplusplus >= 201103L - TEST(Cloning, OKIsNotRefCounted) { ASSERT_EQUALS(Status::OK().refCount(), 0U); diff --git a/src/mongo/bson/bsonobj.h b/src/mongo/bson/bsonobj.h index bcfa2b0c5d4..4eb4f46f86a 100644 --- a/src/mongo/bson/bsonobj.h +++ b/src/mongo/bson/bsonobj.h @@ -107,11 +107,10 @@ namespace mongo { } explicit BSONObj(SharedBuffer ownedBuffer) - : _objdata(ownedBuffer.get() ? ownedBuffer.get() : BSONObj().objdata()) - , _ownedBuffer(ownedBuffer.moveFrom()) { + : _objdata(ownedBuffer.get() ? ownedBuffer.get() : BSONObj().objdata()) + , _ownedBuffer(std::move(ownedBuffer)) { } -#if __cplusplus >= 201103L /** Move construct a BSONObj */ BSONObj(BSONObj&& other) : _objdata(std::move(other._objdata)) @@ -125,7 +124,6 @@ namespace mongo { /** Copy construct a BSONObj. */ BSONObj(const BSONObj&) = default; -#endif /** Provide assignment semantics. We use the value taking form so that we can use copy * and swap, and consume both lvalue and rvalue references. diff --git a/src/mongo/bson/util/builder.h b/src/mongo/bson/util/builder.h index 7f9e5056195..f88d3e18ad5 100644 --- a/src/mongo/bson/util/builder.h +++ b/src/mongo/bson/util/builder.h @@ -184,13 +184,7 @@ namespace mongo { } // Bool does not have a well defined encoding. -#if __cplusplus >= 201103L void appendNum(bool j) = delete; -#else - void appendNum(bool j) { - invariant(false); - } -#endif void appendNum(double j) { BOOST_STATIC_ASSERT(sizeof(double) == 8); diff --git a/src/mongo/client/sasl_client_session.cpp b/src/mongo/client/sasl_client_session.cpp index 17a072a28eb..3e088b9cdbb 100644 --- a/src/mongo/client/sasl_client_session.cpp +++ b/src/mongo/client/sasl_client_session.cpp @@ -35,7 +35,7 @@ #include "mongo/util/signal_handlers_synchronous.h" namespace mongo { - SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create = NULL; + SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create; SaslClientSession::SaslClientSession() {} diff --git a/src/mongo/db/auth/sasl_authentication_session.cpp b/src/mongo/db/auth/sasl_authentication_session.cpp index b02f01d18bc..d3c428e39c5 100644 --- a/src/mongo/db/auth/sasl_authentication_session.cpp +++ b/src/mongo/db/auth/sasl_authentication_session.cpp @@ -48,7 +48,7 @@ namespace mongo { SaslAuthenticationSession::SaslAuthenticationSessionFactoryFn - SaslAuthenticationSession::create = NULL; + SaslAuthenticationSession::create; // Mechanism name constants. const char SaslAuthenticationSession::mechanismCRAMMD5[] = "CRAM-MD5"; diff --git a/src/mongo/db/storage/record_data.h b/src/mongo/db/storage/record_data.h index a819422f0ab..57593ab09e8 100644 --- a/src/mongo/db/storage/record_data.h +++ b/src/mongo/db/storage/record_data.h @@ -35,6 +35,7 @@ namespace mongo { + // TODO: Does this need to have move support? /** * A replacement for the Record class. This class represents data in a record store. * The _dataPtr attribute is used to manage memory ownership. If _dataPtr is NULL, then @@ -47,7 +48,7 @@ namespace mongo { RecordData(const char* data, int size): _data(data), _size(size) { } RecordData(SharedBuffer ownedData, int size) - : _data(ownedData.get()), _size(size), _ownedData(ownedData.moveFrom()) { + : _data(ownedData.get()), _size(size), _ownedData(std::move(ownedData)) { } const char* data() const { return _data; } @@ -60,7 +61,7 @@ namespace mongo { bool isOwned() const { return _ownedData.get(); } SharedBuffer releaseBuffer() { - return _ownedData.moveFrom(); + return std::move(_ownedData); } BSONObj toBson() const { return isOwned() ? BSONObj(_ownedData) : BSONObj(_data); } diff --git a/src/mongo/db/storage/rocks/rocks_record_store.cpp b/src/mongo/db/storage/rocks/rocks_record_store.cpp index b711f4f29cb..145c9547b8b 100644 --- a/src/mongo/db/storage/rocks/rocks_record_store.cpp +++ b/src/mongo/db/storage/rocks/rocks_record_store.cpp @@ -659,7 +659,7 @@ namespace mongo { SharedBuffer data = SharedBuffer::allocate(valueStorage.size()); memcpy(data.get(), valueStorage.data(), valueStorage.size()); - return RecordData(data.moveFrom(), valueStorage.size()); + return RecordData(data, valueStorage.size()); } void RocksRecordStore::_changeNumRecords( OperationContext* txn, bool insert ) { diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp index a9f12e639fd..aa756c8bcc7 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_record_store.cpp @@ -317,7 +317,7 @@ namespace { SharedBuffer data = SharedBuffer::allocate(value.size); memcpy( data.get(), value.data, value.size ); - return RecordData(data.moveFrom(), value.size); + return RecordData(data, value.size); } RecordData WiredTigerRecordStore::dataFor(OperationContext* txn, const RecordId& loc) const { diff --git a/src/mongo/dbtests/perftests.cpp b/src/mongo/dbtests/perftests.cpp index 548dc016e5f..0b71f1d9cf5 100644 --- a/src/mongo/dbtests/perftests.cpp +++ b/src/mongo/dbtests/perftests.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "mongo/db/db.h" #include "mongo/db/dbdirectclient.h" @@ -68,10 +69,6 @@ #include "mongo/util/version_reporting.h" #include "mongo/db/concurrency/lock_state.h" -#if (__cplusplus >= 201103L) -#include -#endif - namespace PerfTests { using boost::shared_ptr; @@ -543,10 +540,8 @@ namespace PerfTests { mongo::mutex mtest("mtest"); boost::mutex mboost; boost::timed_mutex mboost_timed; -#if (__cplusplus >= 201103L) std::mutex mstd; std::timed_mutex mstd_timed; -#endif SpinLock s; boost::condition c; @@ -595,7 +590,7 @@ namespace PerfTests { SimpleMutex::scoped_lock lk(m); } }; -#if (__cplusplus >= 201103L) + class stdmutexspeed : public B { public: string name() { return "std::mutex"; } @@ -614,7 +609,7 @@ namespace PerfTests { std::lock_guard lk(mstd_timed); } }; -#endif + class spinlockspeed : public B { public: string name() { return "spinlock"; } @@ -1383,7 +1378,6 @@ namespace PerfTests { const Status _status; }; -#if __cplusplus >= 201103L class StatusMoveTestBase : public StatusTestBase { public: StatusMoveTestBase(bool ok) @@ -1416,7 +1410,6 @@ namespace PerfTests { : StatusMoveTestBase(false) {} string name() { return "move-not-ok-status"; } }; -#endif class All : public Suite { public: @@ -1485,10 +1478,8 @@ namespace PerfTests { add< simplemutexspeed >(); add< boostmutexspeed >(); add< boosttimed_mutexspeed >(); -#if (__cplusplus >= 201103L) add< stdmutexspeed >(); add< stdtimed_mutexspeed >(); -#endif add< spinlockspeed >(); #ifdef RUNCOMPARESWAP add< casspeed >(); @@ -1517,10 +1508,8 @@ namespace PerfTests { add< ReturnNotOKStatus >(); add< CopyOKStatus >(); add< CopyNotOKStatus >(); -#if __cplusplus >= 201103L add< MoveOKStatus >(); add< MoveNotOKStatus >(); -#endif } } } myall; diff --git a/src/mongo/platform/atomic_intrinsics.h b/src/mongo/platform/atomic_intrinsics.h deleted file mode 100644 index ffadd9af6f5..00000000000 --- a/src/mongo/platform/atomic_intrinsics.h +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * 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 GNU Affero General 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. - */ - -/** - * NOTE: Not for direct use by any code other than AtomicWord. - * - * The atomic_intrinsics module provides low-level atomic operations for manipulating memory. - * Implementations are platform specific, so this file describes the interface and includes - * the appropriate os/compiler-specific headers. - * - * For supported word types, the atomic_intrinsics headers provide implementations of template - * classes of the following form: - * - * template class AtomicIntrinsics { - * static T load(volatile const T* value); - * static T store(volatile T* dest, T newValue); - * static T compareAndSwap(volatile T* dest, T expected, T newValue); - * static T swap(volatile T* dest, T newValue); - * static T fetchAndAdd(volatile T* dest, T increment); - * }; - * - * All of the functions assume that the volatile T pointers are naturally aligned, and may not - * operate as expected, if they are not so aligned. - * - * The behavior of the functions is analogous to the same-named member functions of the AtomicWord - * template type in atomic_word.h. - */ - -#pragma once - -#if defined(MONGO_HAVE_CXX11_ATOMICS) -#error "Use of atomic_intrinsics.h is not supported when C++11 is available" -#endif - -#if defined(_WIN32) -#error "Windows builds must use a compiler supporting std::atomic" -#elif defined(MONGO_HAVE_GCC_ATOMIC_BUILTINS) -#include "mongo/platform/atomic_intrinsics_gcc_atomic.h" -#elif defined(MONGO_HAVE_GCC_SYNC_BUILTINS) -#include "mongo/platform/atomic_intrinsics_gcc_sync.h" -#elif defined(__i386__) || defined(__x86_64__) -#include "mongo/platform/atomic_intrinsics_gcc_intel.h" -#else -#error "Unsupported os/compiler family" -#endif diff --git a/src/mongo/platform/atomic_intrinsics_gcc_atomic.h b/src/mongo/platform/atomic_intrinsics_gcc_atomic.h deleted file mode 100644 index 5e2e7d24a14..00000000000 --- a/src/mongo/platform/atomic_intrinsics_gcc_atomic.h +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * 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 GNU Affero General 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. - */ - -/** - * Implementation of the AtomicIntrinsics::* operations for systems on any - * architecture using a new enough GCC-compatible compiler toolchain. - */ - -#pragma once - -namespace mongo { - - /** - * Instantiation of AtomicIntrinsics<> for all word types T. - */ - template - class AtomicIntrinsics { - public: - - static T compareAndSwap(volatile T* dest, T expected, T newValue) { - __atomic_compare_exchange(dest, &expected, &newValue, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); - return expected; - } - - static T swap(volatile T* dest, T newValue) { - T result; - __atomic_exchange(dest, &newValue, &result, __ATOMIC_SEQ_CST); - return result; - } - - static T load(volatile const T* value) { - T result; - __atomic_load(value, &result, __ATOMIC_SEQ_CST); - return result; - } - - static T loadRelaxed(volatile const T* value) { - T result; - __atomic_load(value, &result, __ATOMIC_RELAXED); - return result; - } - - static void store(volatile T* dest, T newValue) { - __atomic_store(dest, &newValue, __ATOMIC_SEQ_CST); - } - - static T fetchAndAdd(volatile T* dest, T increment) { - return __atomic_fetch_add(dest, increment, __ATOMIC_SEQ_CST); - } - - private: - AtomicIntrinsics(); - ~AtomicIntrinsics(); - }; - -} // namespace mongo diff --git a/src/mongo/platform/atomic_intrinsics_gcc_intel.h b/src/mongo/platform/atomic_intrinsics_gcc_intel.h deleted file mode 100644 index 489c0c4b5bd..00000000000 --- a/src/mongo/platform/atomic_intrinsics_gcc_intel.h +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License, version 3, - * as published by the Free Software Foundation. - * - * 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 - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - * 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 GNU Affero General 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. - */ - -/** - * Implementation of the AtomicIntrinsics::* operations for IA-32 and AMD64 systems using a - * GCC-compatible compiler toolchain. - */ - -#pragma once - -#include - -namespace mongo { - - /** - * Instantiation of AtomicIntrinsics<> for all word types T where sizeof <= sizeof(void *). - * - * On 32-bit systems, this handles 8-, 16- and 32-bit word types. On 64-bit systems, - * it handles 8-, 16, 32- and 64-bit types. - */ - template - class AtomicIntrinsics { - public: - - static T compareAndSwap(volatile T* dest, T expected, T newValue) { - - T result; - asm volatile ("lock cmpxchg %[src], %[dest]" - : [dest] "+m" (*dest), - "=a" (result) - : [src] "r" (newValue), - "a" (expected) - : "memory", "cc"); - return result; - } - - static T swap(volatile T* dest, T newValue) { - - T result = newValue; - // No need for "lock" prefix on "xchg". - asm volatile ("xchg %[r], %[dest]" - : [dest] "+m" (*dest), - [r] "+r" (result) - : - : "memory"); - return result; - } - - static T load(volatile const T* value) { - asm volatile ("mfence" ::: "memory"); - T result = *value; - asm volatile ("mfence" ::: "memory"); - return result; - } - - static T loadRelaxed(volatile const T* value) { - return *value; - } - - static void store(volatile T* dest, T newValue) { - asm volatile ("mfence" ::: "memory"); - *dest = newValue; - asm volatile ("mfence" ::: "memory"); - } - - static T fetchAndAdd(volatile T* dest, T increment) { - - T result = increment; - asm volatile ("lock xadd %[src], %[dest]" - : [dest] "+m" (*dest), - [src] "+r" (result) - : - : "memory", "cc"); - return result; - } - - private: - AtomicIntrinsics(); - ~AtomicIntrinsics(); - }; - - /** - * Instantiation of AtomicIntrinsics where sizeof exceeds sizeof(void*). - * - * On 32-bit systems, this handles the 64-bit word type. Not used on 64-bit systems. - * - * Note that the implementations of swap, store and fetchAndAdd spin until they succeed. This - * implementation is thread-safe, but may have poor performance in high-contention environments. - * However, no superior solution exists for IA-32 (32-bit x86) systems. - */ - template - class AtomicIntrinsics::type> { - public: - static T compareAndSwap(volatile T* dest, T expected, T newValue) { - T result = expected; - asm volatile ("push %%eax\n" - "push %%ebx\n" - "push %%ecx\n" - "push %%edx\n" - "mov (%%edx), %%ebx\n" - "mov 4(%%edx), %%ecx\n" - "mov (%%edi), %%eax\n" - "mov 4(%%edi), %%edx\n" - "lock cmpxchg8b (%%esi)\n" - "mov %%eax, (%%edi)\n" - "mov %%edx, 4(%%edi)\n" - "pop %%edx\n" - "pop %%ecx\n" - "pop %%ebx\n" - "pop %%eax\n" - : - : "S" (dest), - "D" (&result), - "d" (&newValue) - : "memory", "cc"); - return result; - } - - static T swap(volatile T* dest, T newValue) { - - T expected; - T actual; - do { - expected = *dest; - actual = compareAndSwap(dest, expected, newValue); - } while (actual != expected); - return actual; - } - - static T load(volatile const T* value) { - return compareAndSwap(const_cast(value), T(0), T(0)); - } - - static void store(volatile T* dest, T newValue) { - swap(dest, newValue); - } - - static T fetchAndAdd(volatile T* dest, T increment) { - - T expected; - T actual; - do { - expected = load(dest); - actual = compareAndSwap(dest, expected, expected + increment); - } while (actual != expected); - return actual; - } - - private: - AtomicIntrinsics(); - ~AtomicIntrinsics(); - }; - -} // namespace mongo diff --git a/src/mongo/platform/atomic_intrinsics_gcc_sync.h b/src/mongo/platform/atomic_intrinsics_gcc_sync.h deleted file mode 100644 index 2ff7b33f4be..00000000000 --- a/src/mongo/platform/atomic_intrinsics_gcc_sync.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright 2014 10gen Inc. - * - * 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 - * - * http://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. - */ - -/** - * Implementation of the AtomicIntrinsics::* operations for systems on any - * architecture using a GCC 4.1+ compatible compiler toolchain. - */ - -#pragma once - -#include - -namespace mongo { - - /** - * Instantiation of AtomicIntrinsics<> for all word types T. - */ - template - class AtomicIntrinsics { - public: - - static T compareAndSwap(volatile T* dest, T expected, T newValue) { - return __sync_val_compare_and_swap(dest, expected, newValue); - } - - static T swap(volatile T* dest, T newValue) { - T currentValue = *dest; - while (true) { - const T result = compareAndSwap(dest, currentValue, newValue); - if (result == currentValue) - return result; - currentValue = result; - } - } - - static T load(volatile const T* value) { - __sync_synchronize(); - T result = *value; - __sync_synchronize(); - return result; - } - - static T loadRelaxed(volatile const T* value) { - asm volatile("" ::: "memory"); - return *value; - } - - static void store(volatile T* dest, T newValue) { - __sync_synchronize(); - *dest = newValue; - __sync_synchronize(); - } - - static T fetchAndAdd(volatile T* dest, T increment) { - return __sync_fetch_and_add(dest, increment); - } - - private: - AtomicIntrinsics(); - ~AtomicIntrinsics(); - }; - - template - class AtomicIntrinsics::type> { - public: - - static T compareAndSwap(volatile T* dest, T expected, T newValue) { - return __sync_val_compare_and_swap(dest, expected, newValue); - } - - static T swap(volatile T* dest, T newValue) { - T currentValue = *dest; - while (true) { - const T result = compareAndSwap(dest, currentValue, newValue); - if (result == currentValue) - return result; - currentValue = result; - } - } - - static T load(volatile const T* value) { - return compareAndSwap(const_cast(value), T(0), T(0)); - } - - static void store(volatile T* dest, T newValue) { - swap(dest, newValue); - } - - static T fetchAndAdd(volatile T* dest, T increment) { - return __sync_fetch_and_add(dest, increment); - } - - private: - AtomicIntrinsics(); - ~AtomicIntrinsics(); - }; - -} // namespace mongo diff --git a/src/mongo/platform/atomic_word.h b/src/mongo/platform/atomic_word.h index 7601d9bed06..ac39a24c0ed 100644 --- a/src/mongo/platform/atomic_word.h +++ b/src/mongo/platform/atomic_word.h @@ -1,4 +1,4 @@ -/* Copyright 2012 10gen Inc. +/* Copyright 2014 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, @@ -27,8 +27,142 @@ #pragma once -#if defined(MONGO_HAVE_CXX11_ATOMICS) -#include "mongo/platform/atomic_word_cxx11.h" -#else -#include "mongo/platform/atomic_word_intrinsics.h" -#endif +#include +#include + +#include + +namespace mongo { + + /** + * Implementation of the AtomicWord interface in terms of the C++11 Atomics. + */ + template + class AtomicWord { + + public: + /** + * Underlying value type. + */ + typedef _WordType WordType; + + /** + * Construct a new word with the given initial value. + */ + explicit AtomicWord(WordType value=WordType(0)) : _value(value) {} + + /** + * Gets the current value of this AtomicWord. + * + * Has acquire and release semantics. + */ + WordType load() const { + return _value.load(); + } + + /** + * Gets the current value of this AtomicWord. + * + * Has relaxed semantics. + */ + WordType loadRelaxed() const { + return _value.load(std::memory_order_relaxed); + } + + /** + * Sets the value of this AtomicWord to "newValue". + * + * Has acquire and release semantics. + */ + void store(WordType newValue) { + return _value.store(newValue); + } + + /** + * Atomically swaps the current value of this with "newValue". + * + * Returns the old value. + * + * Has acquire and release semantics. + */ + WordType swap(WordType newValue) { + return _value.exchange(newValue); + } + + /** + * Atomic compare and swap. + * + * If this value equals "expected", sets this to "newValue". + * Always returns the original of this. + * + * Has acquire and release semantics. + */ + WordType compareAndSwap(WordType expected, WordType newValue) { + // NOTE: Subtle: compare_exchange mutates its first argument. + _value.compare_exchange_strong(expected, newValue); + return expected; + } + + /** + * Get the current value of this, add "increment" and store it, atomically. + * + * Returns the value of this before incrementing. + * + * Has acquire and release semantics. + */ + WordType fetchAndAdd(WordType increment) { + return _value.fetch_add(increment); + } + + /** + * Get the current value of this, subtract "decrement" and store it, atomically. + * + * Returns the value of this before decrementing. + * + * Has acquire and release semantics. + */ + WordType fetchAndSubtract(WordType decrement) { + return _value.fetch_sub(decrement); + } + + /** + * Get the current value of this, add "increment" and store it, atomically. + * + * Returns the value of this after incrementing. + * + * Has acquire and release semantics. + */ + WordType addAndFetch(WordType increment) { + return fetchAndAdd(increment) + increment; + } + + /** + * Get the current value of this, subtract "decrement" and store it, atomically. + * + * Returns the value of this after decrementing. + * + * Has acquire and release semantics. + */ + WordType subtractAndFetch(WordType decrement) { + return fetchAndSubtract(decrement) - decrement; + } + + private: + std::atomic _value; + }; + +#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \ + typedef class AtomicWord NAME; \ + namespace { \ + BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \ + BOOST_STATIC_ASSERT(std::is_standard_layout::value); \ + } // namespace + + _ATOMIC_WORD_DECLARE(AtomicUInt32, unsigned); + _ATOMIC_WORD_DECLARE(AtomicUInt64, unsigned long long); + _ATOMIC_WORD_DECLARE(AtomicInt32, int); + _ATOMIC_WORD_DECLARE(AtomicInt64, long long); +#undef _ATOMIC_WORD_DECLARE + +} // namespace mongo + diff --git a/src/mongo/platform/atomic_word_cxx11.h b/src/mongo/platform/atomic_word_cxx11.h deleted file mode 100644 index ddf981bb9b9..00000000000 --- a/src/mongo/platform/atomic_word_cxx11.h +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright 2014 10gen Inc. - * - * 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 - * - * http://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. - */ - -#pragma once - -#if !defined(MONGO_HAVE_CXX11_ATOMICS) -#error "Cannot use atomic_word_cxx11.h without C++11 support" -#endif - -// This file is a bit unusual. Most other source files in this codebase assume that C++11 -// things are only usable if __cplusplus >= 201103L. However, we have made an explicit decision -// to use when available, even if full C++11 conformance is not advertised. As a -// result, we unconditionally include , but guard all other C++11 features under -// __cplusplus >= 201103L so that we can work on platforms that don't yet offer those features, but -// do offer - -#include - -#if __cplusplus >= 201103L -#include -#endif - -#include - -#include "mongo/base/disallow_copying.h" - -namespace mongo { - - /** - * Implementation of the AtomicWord interface in terms of the C++11 Atomics. - */ - template - class AtomicWord { - -#if __cplusplus < 201103L - // AtomicWords are not copyable in C++03. - MONGO_DISALLOW_COPYING(AtomicWord); -#endif - - public: - /** - * Underlying value type. - */ - typedef _WordType WordType; - - /** - * Construct a new word with the given initial value. - */ - explicit AtomicWord(WordType value=WordType(0)) : _value(value) {} - -#if __cplusplus >= 201103L - // In C++11, AtomicWords are not copyable or movable. - AtomicWord(const AtomicWord&) = delete; - AtomicWord& operator=(const AtomicWord&) = delete; - AtomicWord(AtomicWord&&) = delete; - AtomicWord& operator=(AtomicWord&&) = delete; -#endif - - /** - * Gets the current value of this AtomicWord. - * - * Has acquire and release semantics. - */ - WordType load() const { - return _value.load(); - } - - /** - * Gets the current value of this AtomicWord. - * - * Has relaxed semantics. - */ - WordType loadRelaxed() const { - return _value.load(std::memory_order_relaxed); - } - - /** - * Sets the value of this AtomicWord to "newValue". - * - * Has acquire and release semantics. - */ - void store(WordType newValue) { - return _value.store(newValue); - } - - /** - * Atomically swaps the current value of this with "newValue". - * - * Returns the old value. - * - * Has acquire and release semantics. - */ - WordType swap(WordType newValue) { - return _value.exchange(newValue); - } - - /** - * Atomic compare and swap. - * - * If this value equals "expected", sets this to "newValue". - * Always returns the original of this. - * - * Has acquire and release semantics. - */ - WordType compareAndSwap(WordType expected, WordType newValue) { - // NOTE: Subtle: compare_exchange mutates its first argument. - _value.compare_exchange_strong(expected, newValue); - return expected; - } - - /** - * Get the current value of this, add "increment" and store it, atomically. - * - * Returns the value of this before incrementing. - * - * Has acquire and release semantics. - */ - WordType fetchAndAdd(WordType increment) { - return _value.fetch_add(increment); - } - - /** - * Get the current value of this, subtract "decrement" and store it, atomically. - * - * Returns the value of this before decrementing. - * - * Has acquire and release semantics. - */ - WordType fetchAndSubtract(WordType decrement) { - return _value.fetch_sub(decrement); - } - - /** - * Get the current value of this, add "increment" and store it, atomically. - * - * Returns the value of this after incrementing. - * - * Has acquire and release semantics. - */ - WordType addAndFetch(WordType increment) { - return fetchAndAdd(increment) + increment; - } - - /** - * Get the current value of this, subtract "decrement" and store it, atomically. - * - * Returns the value of this after decrementing. - * - * Has acquire and release semantics. - */ - WordType subtractAndFetch(WordType decrement) { - return fetchAndSubtract(decrement) - decrement; - } - - private: - std::atomic _value; - }; - -#if __cplusplus >= 201103L -#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \ - typedef class AtomicWord NAME; \ - namespace { \ - BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \ - BOOST_STATIC_ASSERT(std::is_standard_layout::value); \ - } // namespace -#else -#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \ - typedef class AtomicWord NAME; \ - namespace { \ - BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \ - } // namespace -#endif - - _ATOMIC_WORD_DECLARE(AtomicUInt32, unsigned); - _ATOMIC_WORD_DECLARE(AtomicUInt64, unsigned long long); - _ATOMIC_WORD_DECLARE(AtomicInt32, int); - _ATOMIC_WORD_DECLARE(AtomicInt64, long long); -#undef _ATOMIC_WORD_DECLARE - -} // namespace mongo - diff --git a/src/mongo/platform/atomic_word_intrinsics.h b/src/mongo/platform/atomic_word_intrinsics.h deleted file mode 100644 index 7b1997526e2..00000000000 --- a/src/mongo/platform/atomic_word_intrinsics.h +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2012 10gen Inc. - * - * 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 - * - * http://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. - */ - -#pragma once - -#include - -#include "mongo/base/disallow_copying.h" -#include "mongo/platform/atomic_intrinsics.h" -#include "mongo/platform/compiler.h" - -namespace mongo { - - /** - * Template type for word types supporting indivisible memory operations, implemented - * in terms of the atomic_intrinsics header. - * - * Effects of operations with "acquire" semantics are visible to other threads before effects of - * any subsequent operation by the calling thread. Effects of operations with "release" - * semantics are visible to other processors only after the effects of previous operations on - * the current thread are visible. - * - * NOTE(schwerin): This implementation assumes that instances are naturally aligned. - * Instances that are not naturally aligned may operate incorrectly, or not at all. Natural - * alignment for this purpose means that the byte address of the beginning of the object is an - * integer multiple of the size of the type, in bytes. - * - * NOTE(schwerin): This is a low level concurrency type, it is very hard to use correctly, and - * you should not decide to use it lightly. - * - * NOTE(schwerin): This type is and must be a POD type, or per C++11 rules, a "Standard-layout" - * type. - */ - template - class AtomicWord { - MONGO_DISALLOW_COPYING(AtomicWord); - - public: - /** - * Underlying value type. - */ - typedef _WordType WordType; - - /** - * Construct a new word with the given initial value. - */ - explicit AtomicWord(WordType value=WordType(0)) : _value(value) {} - - /** - * Gets the current value of this AtomicWord. - * - * Has acquire and release semantics. - */ - WordType load() const { return AtomicIntrinsics::load(&_value); } - - /** - * Gets the current value of this AtomicWord. - * - * Has relaxed semantics. - */ - WordType loadRelaxed() const { return AtomicIntrinsics::loadRelaxed(&_value); } - - /** - * Sets the value of this AtomicWord to "newValue". - * - * Has acquire and release semantics. - */ - void store(WordType newValue) { AtomicIntrinsics::store(&_value, newValue); } - - /** - * Atomically swaps the current value of this with "newValue". - * - * Returns the old value. - * - * Has acquire and release semantics. - */ - WordType swap(WordType newValue) { - return AtomicIntrinsics::swap(&_value, newValue); - } - - /** - * Atomic compare and swap. - * - * If this value equals "expected", sets this to "newValue". - * Always returns the original of this. - * - * Has acquire and release semantics. - */ - WordType compareAndSwap(WordType expected, WordType newValue) { - return AtomicIntrinsics::compareAndSwap(&_value, expected, newValue); - } - - /** - * Get the current value of this, add "increment" and store it, atomically. - * - * Returns the value of this before incrementing. - * - * Has acquire and release semantics. - */ - WordType fetchAndAdd(WordType increment) { - return AtomicIntrinsics::fetchAndAdd(&_value, increment); - } - - /** - * Get the current value of this, subtract "decrement" and store it, atomically. - * - * Returns the value of this before decrementing. - * - * Has acquire and release semantics. - */ - WordType fetchAndSubtract(WordType decrement) { - return fetchAndAdd(WordType(0) - decrement); - } - - /** - * Get the current value of this, add "increment" and store it, atomically. - * - * Returns the value of this after incrementing. - * - * Has acquire and release semantics. - */ - WordType addAndFetch(WordType increment) { - return fetchAndAdd(increment) + increment; - } - - /** - * Get the current value of this, subtract "decrement" and store it, atomically. - * - * Returns the value of this after decrementing. - * - * Has acquire and release semantics. - */ - WordType subtractAndFetch(WordType decrement) { - return fetchAndSubtract(decrement) - decrement; - } - - private: - volatile WordType _value; - }; - -#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \ - typedef class AtomicWord NAME; \ - namespace { BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); } - - _ATOMIC_WORD_DECLARE(AtomicUInt32, unsigned); - _ATOMIC_WORD_DECLARE(AtomicUInt64, unsigned long long); - _ATOMIC_WORD_DECLARE(AtomicInt32, int); - _ATOMIC_WORD_DECLARE(AtomicInt64, long long); -#undef _ATOMIC_WORD_DECLARE - -} // namespace mongo - diff --git a/src/mongo/platform/hash_namespace.h b/src/mongo/platform/hash_namespace.h index be1fb95c4d9..6e0b7fcf38a 100644 --- a/src/mongo/platform/hash_namespace.h +++ b/src/mongo/platform/hash_namespace.h @@ -27,50 +27,8 @@ #pragma once -// We need to drag in a C++ header so we can examine __GXX_EXPERIMENTAL_CXX0X__ or -// _LIBCPP_VERSION meaningfully. The header is pretty lightweight, mostly unavoidable, -// and almost certain to bring in the standard library configuration macros. -#include - -// NOTE(acm): Before gcc-4.7, __cplusplus is always defined to be 1, so we can't reliably -// detect C++11 support by exclusively checking the value of __cplusplus. Additionaly, libc++, -// whether in C++11 or C++03 mode, doesn't use TR1 and drops things into std instead. -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_LIBCPP_VERSION) - #include #define MONGO_HASH_NAMESPACE_START namespace std { #define MONGO_HASH_NAMESPACE_END } #define MONGO_HASH_NAMESPACE std - -#elif defined(_MSC_VER) && _MSC_VER >= 1500 - -#if _MSC_VER >= 1600 /* Visual Studio 2010+ */ - -#include - -#define MONGO_HASH_NAMESPACE_START namespace std { -#define MONGO_HASH_NAMESPACE_END } -#define MONGO_HASH_NAMESPACE std - -#else /* Older Visual Studio */ - -#include - -#define MONGO_HASH_NAMESPACE_START namespace std { namespace tr1 { -#define MONGO_HASH_NAMESPACE_END }} -#define MONGO_HASH_NAMESPACE std::tr1 - -#endif - -#elif defined(__GNUC__) - -#include - -#define MONGO_HASH_NAMESPACE_START namespace std { namespace tr1 { -#define MONGO_HASH_NAMESPACE_END }} -#define MONGO_HASH_NAMESPACE std::tr1 - -#else -#error "Cannot determine namespace for 'hash'" -#endif diff --git a/src/mongo/platform/unordered_map.h b/src/mongo/platform/unordered_map.h index c88f05229fb..5bf3e340962 100644 --- a/src/mongo/platform/unordered_map.h +++ b/src/mongo/platform/unordered_map.h @@ -27,16 +27,6 @@ #pragma once -// We need to drag in a C++ header so we can examine __GXX_EXPERIMENTAL_CXX0X__ or -// _LIBCPP_VERSION meaningfully. The header is pretty lightweight, mostly unavoidable, -// and almost certain to bring in the standard library configuration macros. -#include - -// NOTE(acm): Before gcc-4.7, __cplusplus is always defined to be 1, so we can't reliably -// detect C++11 support by exclusively checking the value of __cplusplus. Additionaly, libc++, -// whether in C++11 or C++03 mode, doesn't use TR1 and drops things into std instead. -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_LIBCPP_VERSION) - #include namespace mongo { @@ -44,31 +34,3 @@ namespace mongo { using std::unordered_map; } // namespace mongo - -#elif defined(_MSC_VER) && _MSC_VER >= 1500 - -#include - -namespace mongo { - -#if _MSC_VER >= 1600 /* Visual Studio 2010+ */ - using std::unordered_map; -#else - using std::tr1::unordered_map; -#endif - -} // namespace mongo - -#elif defined(__GNUC__) - -#include - -namespace mongo { - - using std::tr1::unordered_map; - -} // namespace mongo - -#else -#error "Compiler's standard library does not provide a C++ unordered_map implementation." -#endif diff --git a/src/mongo/platform/unordered_set.h b/src/mongo/platform/unordered_set.h index 20b392095eb..4733ab73973 100644 --- a/src/mongo/platform/unordered_set.h +++ b/src/mongo/platform/unordered_set.h @@ -27,16 +27,6 @@ #pragma once -// We need to drag in a C++ header so we can examine __GXX_EXPERIMENTAL_CXX0X__ or -// _LIBCPP_VERSION meaningfully. The header is pretty lightweight, mostly unavoidable, -// and almost certain to bring in the standard library configuration macros. -#include - -// NOTE(acm): Before gcc-4.7, __cplusplus is always defined to be 1, so we can't reliably -// detect C++11 support by exclusively checking the value of __cplusplus. Additionaly, libc++, -// whether in C++11 or C++03 mode, doesn't use TR1 and drops things into std instead. -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(_LIBCPP_VERSION) - #include namespace mongo { @@ -44,31 +34,3 @@ namespace mongo { using std::unordered_set; } // namespace mongo - -#elif defined(_MSC_VER) && _MSC_VER >= 1500 - -#include - -namespace mongo { - -#if _MSC_VER >= 1600 /* Visual Studio 2010+ */ - using std::unordered_set; -#else - using std::tr1::unordered_set; -#endif - -} // namespace mongo - -#elif defined(__GNUC__) - -#include - -namespace mongo { - - using std::tr1::unordered_set; - -} // namespace mongo - -#else -#error "Compiler's standard library does not provide a C++ unordered_set implementation." -#endif diff --git a/src/mongo/stdx/functional.h b/src/mongo/stdx/functional.h index 8ed0a746d73..a0e6079cac4 100644 --- a/src/mongo/stdx/functional.h +++ b/src/mongo/stdx/functional.h @@ -28,7 +28,13 @@ #pragma once -#if __cplusplus >= 201103L +// As of VS2013, the Windows STL still doesn't have an adequate implementation +// of std::function. +// +// See https://connect.microsoft.com/VisualStudio/feedback/details/768899/std-function-not-compiling-in-vs2012 +// +// The bug is fixed in VS2015. +#if !defined(_MSC_VER) || (_MSC_VER > 1800) #include diff --git a/src/mongo/unittest/unittest.cpp b/src/mongo/unittest/unittest.cpp index f484c70f079..477045a27d0 100644 --- a/src/mongo/unittest/unittest.cpp +++ b/src/mongo/unittest/unittest.cpp @@ -400,10 +400,7 @@ namespace { return *this; } - TestAssertionFailure::~TestAssertionFailure() -#if __cplusplus >= 201103 - noexcept(false) -#endif + TestAssertionFailure::~TestAssertionFailure() BOOST_NOEXCEPT_IF(false) { if (!_enabled) { invariant(_stream.str().empty()); diff --git a/src/mongo/unittest/unittest.h b/src/mongo/unittest/unittest.h index bb31bfa30ed..b5f6f3eb850 100644 --- a/src/mongo/unittest/unittest.h +++ b/src/mongo/unittest/unittest.h @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -440,11 +441,7 @@ namespace mongo { TestAssertionFailure( const std::string& file, unsigned line, const std::string& message); TestAssertionFailure(const TestAssertionFailure& other); -#if __cplusplus < 201103 - ~TestAssertionFailure(); -#else - ~TestAssertionFailure() noexcept(false); -#endif + ~TestAssertionFailure() BOOST_NOEXCEPT_IF(false); TestAssertionFailure& operator=(const TestAssertionFailure& other); diff --git a/src/mongo/util/shared_buffer.h b/src/mongo/util/shared_buffer.h index 442f5681482..af21b19d615 100644 --- a/src/mongo/util/shared_buffer.h +++ b/src/mongo/util/shared_buffer.h @@ -36,19 +36,24 @@ namespace mongo { class SharedBuffer { public: - SharedBuffer() {} + SharedBuffer() = default; void swap(SharedBuffer& other) { _holder.swap(other._holder); } - /** - * C++03 compatible way of writing std::move(someSharedBuffer) - */ - SharedBuffer moveFrom() { - SharedBuffer out; - this->swap(out); - return out; + SharedBuffer(const SharedBuffer&) = default; + SharedBuffer& operator=(const SharedBuffer&) = default; + + SharedBuffer(SharedBuffer&& other) + : _holder() { + swap(other); + } + + SharedBuffer& operator=(SharedBuffer&& other) { + swap(other); + other._holder.reset(); + return *this; } static SharedBuffer allocate(size_t bytes) { diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp index 680324ec781..d4bc2f75234 100644 --- a/src/mongo/util/signal_handlers_synchronous.cpp +++ b/src/mongo/util/signal_handlers_synchronous.cpp @@ -131,7 +131,6 @@ namespace { void myTerminate() { boost::mutex::scoped_lock lk(streamMutex); -#if __cplusplus >= 201103L || defined(_MSC_VER) // Available in MSVC++2010 and newer. // In c++11 we can recover the current exception to print it. if (std::exception_ptr eptr = std::current_exception()) { mallocFreeOStream << "terminate() called. An exception is active;" @@ -172,9 +171,6 @@ namespace { else { mallocFreeOStream << "terminate() called. No exception is active"; } -#else - mallocFreeOStream << "terminate() called.\n"; -#endif printStackTrace(mallocFreeOStream); writeMallocFreeStreamToLog();