0
0
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:
Andrew Morrow 2015-01-03 10:55:42 -05:00
parent c1b5595b5f
commit 05d73815c3
28 changed files with 249 additions and 1183 deletions

View File

@ -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()

View File

@ -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 {

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -35,7 +35,7 @@
#include "mongo/util/signal_handlers_synchronous.h"
namespace mongo {
SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create = NULL;
SaslClientSession::SaslClientSessionFactoryFn SaslClientSession::create;
SaslClientSession::SaslClientSession() {}

View File

@ -48,7 +48,7 @@
namespace mongo {
SaslAuthenticationSession::SaslAuthenticationSessionFactoryFn
SaslAuthenticationSession::create = NULL;
SaslAuthenticationSession::create;
// Mechanism name constants.
const char SaslAuthenticationSession::mechanismCRAMMD5[] = "CRAM-MD5";

View File

@ -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); }

View File

@ -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 ) {

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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());

View File

@ -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);

View File

@ -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) {

View File

@ -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();