mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 17:10:48 +01:00
SERVER-16559 Require C++11 and remove conditional compilation
This commit is contained in:
parent
c1b5595b5f
commit
05d73815c3
266
SConstruct
266
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 <vector>
|
||||
#if !defined(_GLIBCXX_BEGIN_NAMESPACE_VERSION)
|
||||
#error libstdcxx older than 4.6.0
|
||||
#define _GLIBCXX_PROFILE
|
||||
#include <unordered_map>
|
||||
#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 <atomic>
|
||||
int main(int argc, char **argv) {
|
||||
std::atomic<int> a(0);
|
||||
return a.fetch_add(1);
|
||||
}
|
||||
"""
|
||||
context.Message('Checking for C++11 <atomic> 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> > __atomic > __sync
|
||||
# Windows: <atomic> > Interlocked functions / intrinsics.
|
||||
#
|
||||
# If we are in C++11 mode, try to use <atomic>. 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 <atomic> 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()
|
||||
|
@ -28,13 +28,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "mongo/platform/endian.h"
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace mongo {
|
||||
|
||||
class ConstDataView {
|
||||
|
@ -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);
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "mongo/util/signal_handlers_synchronous.h"
|
||||
|
||||
namespace mongo {
|
||||
SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create = NULL;
|
||||
SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create;
|
||||
|
||||
SaslClientSession::SaslClientSession() {}
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
|
||||
namespace mongo {
|
||||
SaslAuthenticationSession::SaslAuthenticationSessionFactoryFn
|
||||
SaslAuthenticationSession::create = NULL;
|
||||
SaslAuthenticationSession::create;
|
||||
|
||||
// Mechanism name constants.
|
||||
const char SaslAuthenticationSession::mechanismCRAMMD5[] = "CRAM-MD5";
|
||||
|
@ -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); }
|
||||
|
@ -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 ) {
|
||||
|
@ -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 {
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
|
||||
#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 <mutex>
|
||||
#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<std::timed_mutex> 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;
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <typename T> 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 <atomic> 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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<T>::* 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 <typename T, typename IsTLarge=void>
|
||||
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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<T>::* operations for IA-32 and AMD64 systems using a
|
||||
* GCC-compatible compiler toolchain.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* Instantiation of AtomicIntrinsics<> for all word types T where sizeof<T> <= 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 <typename T, typename IsTLarge=void>
|
||||
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<T> where sizeof<T> 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 <typename T>
|
||||
class AtomicIntrinsics<T, typename boost::disable_if_c<sizeof(T) <= sizeof(void*)>::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<volatile T*>(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
|
@ -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<T>::* operations for systems on any
|
||||
* architecture using a GCC 4.1+ compatible compiler toolchain.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* Instantiation of AtomicIntrinsics<> for all word types T.
|
||||
*/
|
||||
template <typename T, typename IsTLarge=void>
|
||||
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 <typename T>
|
||||
class AtomicIntrinsics<T, typename boost::disable_if_c<sizeof(T) <= sizeof(void*)>::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<volatile T*>(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
|
@ -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 <atomic>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* Implementation of the AtomicWord interface in terms of the C++11 Atomics.
|
||||
*/
|
||||
template <typename _WordType>
|
||||
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<WordType> _value;
|
||||
};
|
||||
|
||||
#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \
|
||||
typedef class AtomicWord<WTYPE> NAME; \
|
||||
namespace { \
|
||||
BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \
|
||||
BOOST_STATIC_ASSERT(std::is_standard_layout<WTYPE>::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
|
||||
|
||||
|
@ -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 <atomic> 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 <atomic> when available, even if full C++11 conformance is not advertised. As a
|
||||
// result, we unconditionally include <atomic>, 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 <atomic>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include "mongo/base/disallow_copying.h"
|
||||
|
||||
namespace mongo {
|
||||
|
||||
/**
|
||||
* Implementation of the AtomicWord interface in terms of the C++11 Atomics.
|
||||
*/
|
||||
template <typename _WordType>
|
||||
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<WordType> _value;
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \
|
||||
typedef class AtomicWord<WTYPE> NAME; \
|
||||
namespace { \
|
||||
BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \
|
||||
BOOST_STATIC_ASSERT(std::is_standard_layout<WTYPE>::value); \
|
||||
} // namespace
|
||||
#else
|
||||
#define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \
|
||||
typedef class AtomicWord<WTYPE> 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
|
||||
|
@ -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 <boost/static_assert.hpp>
|
||||
|
||||
#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 <typename _WordType>
|
||||
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<WordType>::load(&_value); }
|
||||
|
||||
/**
|
||||
* Gets the current value of this AtomicWord.
|
||||
*
|
||||
* Has relaxed semantics.
|
||||
*/
|
||||
WordType loadRelaxed() const { return AtomicIntrinsics<WordType>::loadRelaxed(&_value); }
|
||||
|
||||
/**
|
||||
* Sets the value of this AtomicWord to "newValue".
|
||||
*
|
||||
* Has acquire and release semantics.
|
||||
*/
|
||||
void store(WordType newValue) { AtomicIntrinsics<WordType>::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<WordType>::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<WordType>::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<WordType>::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<WTYPE> 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
|
||||
|
@ -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 <new> header is pretty lightweight, mostly unavoidable,
|
||||
// and almost certain to bring in the standard library configuration macros.
|
||||
#include <new>
|
||||
|
||||
// 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 <functional>
|
||||
|
||||
#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 <functional>
|
||||
|
||||
#define MONGO_HASH_NAMESPACE_START namespace std {
|
||||
#define MONGO_HASH_NAMESPACE_END }
|
||||
#define MONGO_HASH_NAMESPACE std
|
||||
|
||||
#else /* Older Visual Studio */
|
||||
|
||||
#include <tr1/functional>
|
||||
|
||||
#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 <tr1/functional>
|
||||
|
||||
#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
|
||||
|
@ -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 <new> header is pretty lightweight, mostly unavoidable,
|
||||
// and almost certain to bring in the standard library configuration macros.
|
||||
#include <new>
|
||||
|
||||
// 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 <unordered_map>
|
||||
|
||||
namespace mongo {
|
||||
@ -44,31 +34,3 @@ namespace mongo {
|
||||
using std::unordered_map;
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
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 <tr1/unordered_map>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
using std::tr1::unordered_map;
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
#else
|
||||
#error "Compiler's standard library does not provide a C++ unordered_map implementation."
|
||||
#endif
|
||||
|
@ -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 <new> header is pretty lightweight, mostly unavoidable,
|
||||
// and almost certain to bring in the standard library configuration macros.
|
||||
#include <new>
|
||||
|
||||
// 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 <unordered_set>
|
||||
|
||||
namespace mongo {
|
||||
@ -44,31 +34,3 @@ namespace mongo {
|
||||
using std::unordered_set;
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
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 <tr1/unordered_set>
|
||||
|
||||
namespace mongo {
|
||||
|
||||
using std::tr1::unordered_set;
|
||||
|
||||
} // namespace mongo
|
||||
|
||||
#else
|
||||
#error "Compiler's standard library does not provide a C++ unordered_set implementation."
|
||||
#endif
|
||||
|
@ -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 <functional>
|
||||
|
||||
|
@ -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());
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user