From fde7b3c5939b92f73e7620d2d478d52637ab5e1c Mon Sep 17 00:00:00 2001 From: Francois Ferrand Date: Mon, 11 Dec 2017 18:18:51 +0100 Subject: [PATCH] THRIFT-4441: Support compiling Thrift without Boost. Boost is still required for tests, though; and for older (non C++11) platforms. This involves the following changes: - Replace boost::noncopyable with a custom implementation - Replace boost::scoped_array with std::unique_ptr - Replace boost::shared_array, since only scoped_array was needed. - Remove unused boost header inclusion - Replace boost::atomic with std::atomic - Replace boost::unique_ptr with std::unique_ptr - Replace boost::tokenizer with std::getline - Replace BOOST_STATIC_ASSERT with static_assert - Use fpclassify and signbit from std lib - Use std::codecvt_utf8_utf16 for utf16 to utf8 conversion - Replace boost::numeric_cast with std::numeric_limits - Use ostringstream instead of boost::format - Replace BOOST_SCOPE_EXIT with unique_ptr and custom deleter - Remove use of boost::istarts_with and boost::iends_with - Do not use boost/config.h for feature detection This required fixing appveyor env, since VS2015 image does not contain Boost 1.64: revert to testing with Boost 1.63, using a newer version would require either downloading it or upgrading to VS2017 image. --- appveyor.yml | 2 +- build/cmake/DefineOptions.cmake | 21 +++++- configure.ac | 3 + lib/c_glib/test/testthrifttestclient.cpp | 1 + lib/cpp/CMakeLists.txt | 4 +- lib/cpp/Makefile.am | 1 + lib/cpp/src/thrift/Thrift.h | 3 - lib/cpp/src/thrift/concurrency/BoostMutex.cpp | 1 - .../src/thrift/concurrency/FunctionRunner.h | 5 ++ lib/cpp/src/thrift/concurrency/Monitor.h | 5 +- lib/cpp/src/thrift/concurrency/Mutex.cpp | 7 +- lib/cpp/src/thrift/concurrency/Mutex.h | 6 +- .../thrift/concurrency/PosixThreadFactory.cpp | 1 + lib/cpp/src/thrift/noncopyable.h | 49 +++++++++++++ .../thrift/processor/TMultiplexedProcessor.h | 10 +-- lib/cpp/src/thrift/protocol/TBase64Utils.cpp | 2 - .../src/thrift/protocol/TBinaryProtocol.tcc | 8 +-- .../src/thrift/protocol/TCompactProtocol.tcc | 8 +-- .../src/thrift/protocol/TDebugProtocol.cpp | 1 - .../src/thrift/protocol/THeaderProtocol.cpp | 1 - lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 40 ++++++++--- lib/cpp/src/thrift/protocol/TProtocol.h | 3 +- lib/cpp/src/thrift/server/TThreadPoolServer.h | 6 +- lib/cpp/src/thrift/stdcxx.h | 70 ++++++++++++++++--- .../src/thrift/transport/TBufferTransports.h | 11 +-- .../src/thrift/transport/TFileTransport.cpp | 13 +--- lib/cpp/src/thrift/transport/TFileTransport.h | 5 +- .../src/thrift/transport/THeaderTransport.h | 7 +- lib/cpp/src/thrift/transport/THttpClient.cpp | 22 ++++-- lib/cpp/src/thrift/transport/TPipe.cpp | 3 +- lib/cpp/src/thrift/transport/TPipe.h | 1 - lib/cpp/src/thrift/transport/TPipeServer.cpp | 4 +- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 11 +-- .../thrift/transport/TTransportException.h | 12 ++++ .../windows/OverlappedSubmissionThread.cpp | 11 +-- .../windows/OverlappedSubmissionThread.h | 6 +- lib/cpp/src/thrift/windows/Sync.h | 12 ++-- .../src/thrift/windows/TWinsockSingleton.h | 6 +- lib/cpp/test/TransportTest.cpp | 2 +- lib/cpp/test/TypedefTest.cpp | 8 +-- 40 files changed, 281 insertions(+), 111 deletions(-) create mode 100644 lib/cpp/src/thrift/noncopyable.h diff --git a/appveyor.yml b/appveyor.yml index 4c2e36496ca..05312f7e2cd 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,7 +45,7 @@ environment: - PROFILE: MSVC2015 PLATFORM: x64 CONFIGURATION: Release - BOOST_VERSION: 1.64.0 + BOOST_VERSION: 1.63.0 LIBEVENT_VERSION: 2.0.22 PYTHON_VERSION: 3.6 QT_VERSION: 5.8 diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index f1ea7bbc379..8ea785a9310 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -91,11 +91,26 @@ if(WITH_CPP) option(WITH_STDTHREADS "Build with C++ std::thread support" OFF) CMAKE_DEPENDENT_OPTION(WITH_BOOSTTHREADS "Build with Boost threads support" OFF "NOT WITH_STDTHREADS;Boost_FOUND" OFF) + + set(WITH_CPP_SUPPORT OFF) + if (Boost_FOUND) + set(WITH_CPP_SUPPORT ON) + elseif (CMAKE_COMPILER_IS_GNUCC) + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.0) + set(WITH_CPP_SUPPORT ON) + endif() + elseif (MSVC) + if (NOT (MSVC_VERSION LESS 1900)) + set(WITH_CPP_SUPPORT ON) + endif() + elseif (NOT (CMAKE_CXX_STANDARD LESS 11)) + set(WITH_CPP_SUPPORT ON) + endif() endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON - "BUILD_LIBRARIES;WITH_CPP;Boost_FOUND" OFF) + "BUILD_LIBRARIES;WITH_CPP;WITH_CPP_SUPPORT" OFF) CMAKE_DEPENDENT_OPTION(WITH_PLUGIN "Build compiler plugin support" OFF - "BUILD_COMPILER;BUILD_CPP" OFF) + "BUILD_COMPILER;BUILD_CPP;Boost_FOUND" OFF) # C GLib option(WITH_C_GLIB "Build C (GLib) Thrift library" ON) @@ -107,7 +122,7 @@ CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON if(BUILD_CPP) set(boost_components) - if(WITH_BOOSTTHREADS OR BUILD_TESTING) + if(WITH_BOOSTTHREADS OR BUILD_TESTING OR BUILD_TUTORIALS) list(APPEND boost_components system thread) endif() if(BUILD_TESTING) diff --git a/configure.ac b/configure.ac index 073ad8dc59f..20f6aa3fe7e 100755 --- a/configure.ac +++ b/configure.ac @@ -151,6 +151,9 @@ if test "$with_cpp" = "yes"; then AC_SUBST([BOOST_TEST_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_unit_test_framework.a")]) AC_SUBST([BOOST_THREAD_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_thread.a")]) have_cpp="yes" + elif test "$HAVE_CXX11" ; then + # may actually not be enough: e.g. GCC needs >=5 and VC++ needs >=2013 + have_cpp="yes" fi AX_LIB_EVENT([1.0]) diff --git a/lib/c_glib/test/testthrifttestclient.cpp b/lib/c_glib/test/testthrifttestclient.cpp index 5b06883ebcf..dd05ec0bd7d 100755 --- a/lib/c_glib/test/testthrifttestclient.cpp +++ b/lib/c_glib/test/testthrifttestclient.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "ThriftTest.h" #include "ThriftTest_types.h" diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 734af72d53b..49eb05702dd 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -17,7 +17,9 @@ # under the License. # -include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +if(Boost_FOUND) + include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +endif() include_directories(src) # SYSLIBS contains libraries that need to be linked to all lib targets diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index cd1d9234685..242ca5a1060 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -157,6 +157,7 @@ libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS) include_thriftdir = $(includedir)/thrift include_thrift_HEADERS = \ $(top_builddir)/config.h \ + src/thrift/noncopyable.h \ src/thrift/thrift-config.h \ src/thrift/TDispatchProcessor.h \ src/thrift/Thrift.h \ diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index e8e70eba044..844e1822203 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -42,9 +42,6 @@ #include #include -#include -#include - #include #include diff --git a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp b/lib/cpp/src/thrift/concurrency/BoostMutex.cpp index 4e556df1702..951b3d2078b 100644 --- a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp +++ b/lib/cpp/src/thrift/concurrency/BoostMutex.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include diff --git a/lib/cpp/src/thrift/concurrency/FunctionRunner.h b/lib/cpp/src/thrift/concurrency/FunctionRunner.h index eabf019b759..b8e0ab4c74e 100644 --- a/lib/cpp/src/thrift/concurrency/FunctionRunner.h +++ b/lib/cpp/src/thrift/concurrency/FunctionRunner.h @@ -23,6 +23,11 @@ #include #include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + namespace apache { namespace thrift { namespace concurrency { diff --git a/lib/cpp/src/thrift/concurrency/Monitor.h b/lib/cpp/src/thrift/concurrency/Monitor.h index 2399a987986..92e956f3ae7 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.h +++ b/lib/cpp/src/thrift/concurrency/Monitor.h @@ -26,8 +26,7 @@ #include #include - -#include +#include namespace apache { namespace thrift { @@ -51,7 +50,7 @@ namespace concurrency { * * @version $Id:$ */ -class Monitor : boost::noncopyable { +class Monitor : TNonCopyable { public: /** Creates a new mutex, and takes ownership of it. */ Monitor(); diff --git a/lib/cpp/src/thrift/concurrency/Mutex.cpp b/lib/cpp/src/thrift/concurrency/Mutex.cpp index a5264617d5a..43ac57f9a33 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.cpp +++ b/lib/cpp/src/thrift/concurrency/Mutex.cpp @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -32,8 +33,7 @@ #include #include #include - -#include +#include namespace apache { namespace thrift { @@ -116,7 +116,8 @@ static inline int64_t maybeGetProfilingStartTime() { #define EINTR_LOOP(_CALL) int ret; do { ret = _CALL; } while (ret == EINTR) #define ABORT_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { abort(); } } -#define THROW_SRE(_CALLSTR, RET) { throw SystemResourceException(boost::str(boost::format("%1% returned %2% (%3%)") % _CALLSTR % RET % ::strerror(RET))); } + +#define THROW_SRE(_CALLSTR, RET) { throw SystemResourceException(static_cast(std::ostringstream() << _CALLSTR " returned " << RET << "(" << ::strerror(RET) << ")").str()); } #define THROW_SRE_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { THROW_SRE(#_CALL, ret); } } #define THROW_SRE_TRYFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret == 0) { return true; } else if (ret == EBUSY) { return false; } THROW_SRE(#_CALL, ret); } diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h index 09b938e5b1b..8f8a6eeb7fe 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.h +++ b/lib/cpp/src/thrift/concurrency/Mutex.h @@ -20,8 +20,8 @@ #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ #define _THRIFT_CONCURRENCY_MUTEX_H_ 1 +#include #include -#include #include namespace apache { @@ -129,7 +129,7 @@ class NoStarveReadWriteMutex : public ReadWriteMutex { mutable volatile bool writerWaiting_; }; -class Guard : boost::noncopyable { +class Guard : TNonCopyable { public: Guard(const Mutex& value, int64_t timeout = 0) : mutex_(&value) { if (timeout == 0) { @@ -160,7 +160,7 @@ class Guard : boost::noncopyable { // as to whether we're doing acquireRead() or acquireWrite(). enum RWGuardType { RW_READ = 0, RW_WRITE = 1 }; -class RWGuard : boost::noncopyable { +class RWGuard : TNonCopyable { public: RWGuard(const ReadWriteMutex& value, bool write = false) : rw_mutex_(value) { if (write) { diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp index 2e35446b5c8..c0e1848011c 100644 --- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp +++ b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp @@ -29,6 +29,7 @@ #include #include +#include #include diff --git a/lib/cpp/src/thrift/noncopyable.h b/lib/cpp/src/thrift/noncopyable.h new file mode 100644 index 00000000000..7896f5e26c0 --- /dev/null +++ b/lib/cpp/src/thrift/noncopyable.h @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +#ifndef _THRIFT_NONCOPYABLE_H_ +#define _THRIFT_NONCOPYABLE_H_ 1 + +namespace apache { namespace thrift { + +class TNonCopyable +{ +protected: + // Keep default constructor +#if __cplusplus >= 201103L + TNonCopyable() = default; +#else + TNonCopyable() {} +#endif + + // Remove copy constructor and assignment operator +#if __cplusplus >= 201103L +public: + TNonCopyable(const TNonCopyable&) = delete; + TNonCopyable& operator=(const TNonCopyable&) = delete; +#else +private: + TNonCopyable(const TNonCopyable&); + TNonCopyable& operator=(const TNonCopyable&); +#endif +}; + +}} // apache::thrift + +#endif // _THRIFT_NONCOPYABLE_H_ diff --git a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h index aa3d49f8111..4787601415e 100644 --- a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h +++ b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h @@ -20,10 +20,11 @@ #ifndef THRIFT_TMULTIPLEXEDPROCESSOR_H_ #define THRIFT_TMULTIPLEXEDPROCESSOR_H_ 1 +#include +#include #include #include #include -#include namespace apache { namespace thrift { @@ -165,10 +166,11 @@ class TMultiplexedProcessor : public TProcessor { } // Extract the service name - boost::tokenizer > tok(name, boost::char_separator(":")); - std::vector tokens; - std::copy(tok.begin(), tok.end(), std::back_inserter(tokens)); + std::istringstream tokenStream(name); + for (std::string token; std::getline(tokenStream, token, ':');) { + tokens.push_back(token); + } // A valid message should consist of two tokens: the service // name and the name of the method to call. diff --git a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp index beb76ebdff5..7474f5af8ce 100644 --- a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp +++ b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp @@ -19,8 +19,6 @@ #include -#include - using std::string; namespace apache { diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc index d6f6dbb3d88..b93ea6c8308 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc @@ -165,8 +165,8 @@ uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { template uint32_t TBinaryProtocolT::writeDouble(const double dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + THRIFT_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + THRIFT_STATIC_ASSERT(std::numeric_limits::is_iec559); uint64_t bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); @@ -388,8 +388,8 @@ uint32_t TBinaryProtocolT::readI64(int64_t& i64) { template uint32_t TBinaryProtocolT::readDouble(double& dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + THRIFT_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + THRIFT_STATIC_ASSERT(std::numeric_limits::is_iec559); union bytes { uint8_t b[8]; diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc index d40c3313431..f7cfdc9d98e 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc @@ -253,8 +253,8 @@ uint32_t TCompactProtocolT::writeI64(const int64_t i64) { */ template uint32_t TCompactProtocolT::writeDouble(const double dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + THRIFT_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + THRIFT_STATIC_ASSERT(std::numeric_limits::is_iec559); uint64_t bits = bitwise_cast(dub); bits = THRIFT_htolell(bits); @@ -653,8 +653,8 @@ uint32_t TCompactProtocolT::readI64(int64_t& i64) { */ template uint32_t TCompactProtocolT::readDouble(double& dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + THRIFT_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + THRIFT_STATIC_ASSERT(std::numeric_limits::is_iec559); union { uint64_t bits; diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp index d3c6bebf3a1..0e6d4a2aac3 100644 --- a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp @@ -24,7 +24,6 @@ #include #include #include -#include using std::string; diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp index 26676172f35..cce48fd7af8 100644 --- a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp @@ -26,7 +26,6 @@ #include -#include #include namespace apache { diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index a49a14867e8..aee78fb3d63 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -19,10 +19,6 @@ #include -#include -#include -#include - #include #include #include @@ -33,6 +29,34 @@ #include #include +// Codecvt is supported with C++11, but GCC added support only in version 5. +#if __cplusplus < 201103L || (defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5) +#include +#include +#include +#else +#include +#endif + +namespace apache { namespace thrift { namespace stdcxx { +#if __cplusplus < 201103L || (defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5) + using ::boost::math::fpclassify; + using ::boost::math::signbit; + typedef uint16_t char16; + std::string utf16_to_utf8(char16 * data) { + return ::boost::locale::conv::utf_to_utf(data); + } +#else + using ::std::fpclassify; + using ::std::signbit; + typedef char16_t char16; + std::string utf16_to_utf8(char16 * data) { + return ::std::wstring_convert<::std::codecvt_utf8_utf16, char16_t>() + .to_bytes(data); + } +#endif +}}} // namespace apache::thrift::stdcxx + using namespace apache::thrift::transport; namespace apache { @@ -539,9 +563,9 @@ uint32_t TJSONProtocol::writeJSONDouble(double num) { std::string val; bool special = false; - switch (boost::math::fpclassify(num)) { + switch (stdcxx::fpclassify(num)) { case FP_INFINITE: - if (boost::math::signbit(num)) { + if (stdcxx::signbit(num)) { val = kThriftNegativeInfinity; } else { val = kThriftInfinity; @@ -742,7 +766,7 @@ uint32_t TJSONProtocol::readJSONEscapeChar(uint16_t* out) { uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) { uint32_t result = (skipContext ? 0 : context_->read(reader_)); result += readJSONSyntaxChar(kJSONStringDelimiter); - std::vector codeunits; + std::vector codeunits; uint8_t ch; str.clear(); while (true) { @@ -767,7 +791,7 @@ uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) { } codeunits.push_back(cp); codeunits.push_back(0); - str += boost::locale::conv::utf_to_utf(codeunits.data()); + str += stdcxx::utf16_to_utf8(codeunits.data()); codeunits.clear(); } continue; diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index aa5beea92e9..9731c77a7a3 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -29,7 +29,6 @@ #include #include -#include #ifdef HAVE_NETINET_IN_H #include @@ -48,7 +47,7 @@ // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html template static inline To bitwise_cast(From from) { - BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To)); + THRIFT_STATIC_ASSERT(sizeof(From) == sizeof(To)); // BAD!!! These are all broken with -O2. //return *reinterpret_cast(&from); // BAD!!! diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h index 94088d5d04a..36e0cebe787 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.h +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ #define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 -#include +#include #include #include @@ -90,8 +90,8 @@ class TThreadPoolServer : public TServerFramework { virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; stdcxx::shared_ptr threadManager_; - boost::atomic timeout_; - boost::atomic taskExpiration_; + stdcxx::atomic timeout_; + stdcxx::atomic taskExpiration_; }; } diff --git a/lib/cpp/src/thrift/stdcxx.h b/lib/cpp/src/thrift/stdcxx.h index 5113940a595..c7475f50be4 100644 --- a/lib/cpp/src/thrift/stdcxx.h +++ b/lib/cpp/src/thrift/stdcxx.h @@ -20,15 +20,13 @@ #ifndef _THRIFT_STDCXX_H_ #define _THRIFT_STDCXX_H_ 1 -#include - /////////////////////////////////////////////////////////////////// // // functional (function, bind) // /////////////////////////////////////////////////////////////////// -#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL) +#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL) #include #define _THRIFT_FUNCTIONAL_TR1_ 1 #endif @@ -83,29 +81,43 @@ /////////////////////////////////////////////////////////////////// // We can use std for memory functions only if the compiler supports template aliasing -// The macro BOOST_NO_CXX11_SMART_PTR is defined as 1 under Visual Studio 2010 and 2012 -// which do not support the feature, so we must continue to use C++98 and boost on them. -// We cannot use __cplusplus to detect this either, since Microsoft advertises an older one. +// Visual Studio 2010 and 2012 do not support the feature, so we must continue to use C++98 +// and boost on them. We cannot use __cplusplus to detect this either, since Microsoft +// advertises an older one. -#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR) +#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR) #include +#include +#if (BOOST_VERSION >= 105700) +#include +#else +#include +#endif +#define _THRIFT_USE_BOOST_SMARTPTR_ 1 #else #include #endif namespace apache { namespace thrift { namespace stdcxx { -#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR) +#if _THRIFT_USE_BOOST_SMARTPTR_ using ::boost::const_pointer_cast; using ::boost::dynamic_pointer_cast; using ::boost::enable_shared_from_this; using ::boost::make_shared; using ::boost::scoped_ptr; + using ::boost::scoped_array; using ::boost::shared_ptr; using ::boost::static_pointer_cast; using ::boost::weak_ptr; +#if (BOOST_VERSION >= 105700) + using ::boost::movelib::unique_ptr; +#else + using ::boost::interprocess::unique_ptr; +#endif + #else using ::std::const_pointer_cast; @@ -113,12 +125,54 @@ namespace apache { namespace thrift { namespace stdcxx { using ::std::enable_shared_from_this; using ::std::make_shared; template using scoped_ptr = std::unique_ptr; // compiler must support template aliasing + template using scoped_array = std::unique_ptr; // compiler must support template aliasing using ::std::shared_ptr; using ::std::static_pointer_cast; using ::std::weak_ptr; + using ::std::unique_ptr; #endif }}} // apache::thrift::stdcxx +/////////////////////////////////////////////////////////////////// +// +// Atomic +// +/////////////////////////////////////////////////////////////////// + +#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1700) +#include +#define _THRIFT_USE_BOOST_ATOMIC_ 1 +#else +#include +#endif + +namespace apache { namespace thrift { namespace stdcxx { + +#if _THRIFT_USE_BOOST_ATOMIC_ + + using ::boost::atomic; + +#else + + using ::std::atomic; + +#endif + +}}} // apache::thrift::stdcxx + +/////////////////////////////////////////////////////////////////// +// +// Static Assert +// +/////////////////////////////////////////////////////////////////// + +#if (!defined(_MSC_VER) && __cplusplus < 201103L) || (defined(_MSC_VER) && _MSC_VER < 1600) +#include +#define THRIFT_STATIC_ASSERT(_x) BOOST_STATIC_ASSERT(_x) +#else +#define THRIFT_STATIC_ASSERT(_x) static_assert((_x), #_x) +#endif + #endif // #ifndef _THRIFT_STDCXX_H_ diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h index 0a4cc6d73ec..21299f5cf9e 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.h +++ b/lib/cpp/src/thrift/transport/TBufferTransports.h @@ -20,11 +20,12 @@ #ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ #define _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1 +#include #include #include #include -#include +#include #include #include @@ -274,8 +275,8 @@ class TBufferedTransport : public TVirtualTransport rBuf_; - boost::scoped_array wBuf_; + stdcxx::scoped_array rBuf_; + stdcxx::scoped_array wBuf_; }; /** @@ -411,8 +412,8 @@ class TFramedTransport : public TVirtualTransport uint32_t rBufSize_; uint32_t wBufSize_; - boost::scoped_array rBuf_; - boost::scoped_array wBuf_; + stdcxx::scoped_array rBuf_; + stdcxx::scoped_array wBuf_; uint32_t bufReclaimThresh_; uint32_t maxFrameSize_; }; diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index 4683f9531e8..9cc9076331a 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -19,20 +19,12 @@ #include +#include #include #include #include #include -#include -#if (BOOST_VERSION >= 105700) -#include -using boost::movelib::unique_ptr; -#else -#include -using boost::interprocess::unique_ptr; -#endif - #ifdef HAVE_SYS_TIME_H #include #else @@ -62,6 +54,7 @@ namespace thrift { namespace transport { using stdcxx::shared_ptr; +using stdcxx::unique_ptr; using std::cerr; using std::cout; using std::endl; @@ -436,7 +429,7 @@ void TFileTransport::writerThread() { uint8_t* zeros = new uint8_t[padding]; memset(zeros, '\0', padding); - boost::scoped_array array(zeros); + stdcxx::scoped_array array(zeros); if (-1 == ::write(fd_, zeros, padding)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() error while padding zeros ", diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index d6da4363e1b..40841fc4bc1 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -348,11 +347,11 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // conditions used to block when the buffer is full or empty Monitor notFull_, notEmpty_; - boost::atomic closing_; + stdcxx::atomic closing_; // To keep track of whether the buffer has been flushed Monitor flushed_; - boost::atomic forceFlush_; + stdcxx::atomic forceFlush_; // Mutex that is grabbed when enqueueing and swapping the read/write buffers Mutex mutex_; diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.h b/lib/cpp/src/thrift/transport/THeaderTransport.h index 1a2c8e04900..e04b55b6e55 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.h +++ b/lib/cpp/src/thrift/transport/THeaderTransport.h @@ -33,7 +33,6 @@ #include #endif -#include #include #include @@ -83,7 +82,7 @@ class THeaderTransport : public TVirtualTransport tBuf_; + stdcxx::scoped_array tBuf_; void readString(uint8_t*& ptr, /* out */ std::string& str, uint8_t const* headerBoundary); diff --git a/lib/cpp/src/thrift/transport/THttpClient.cpp b/lib/cpp/src/thrift/transport/THttpClient.cpp index afd02a83dc0..f2adb310e7f 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.cpp +++ b/lib/cpp/src/thrift/transport/THttpClient.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -47,6 +47,20 @@ THttpClient::THttpClient(string host, int port, string path) THttpClient::~THttpClient() { } +namespace { +bool iStartWith(char const* str, char const* prefix){ + for(; *prefix; str++, prefix++) { + if (!*str || ::tolower(*str) != ::tolower(*prefix)) + return false; + } + return true; +} +bool iEndsWith(char const* str, char const* suffix){ + size_t suffixLen = ::strlen(suffix); + return ::strlen(str) >= suffixLen && iStartWith(str - suffixLen, suffix); +} +} + void THttpClient::parseHeader(char* header) { char* colon = strchr(header, ':'); if (colon == NULL) { @@ -54,11 +68,11 @@ void THttpClient::parseHeader(char* header) { } char* value = colon + 1; - if (boost::istarts_with(header, "Transfer-Encoding")) { - if (boost::iends_with(value, "chunked")) { + if (iStartWith(header, "Transfer-Encoding")) { + if (iEndsWith(value, "chunked")) { chunked_ = true; } - } else if (boost::istarts_with(header, "Content-Length")) { + } else if (iStartWith(header, "Content-Length")) { chunked_ = false; contentLength_ = atoi(value); } diff --git a/lib/cpp/src/thrift/transport/TPipe.cpp b/lib/cpp/src/thrift/transport/TPipe.cpp index 8a84457db0a..2b3ea77426f 100644 --- a/lib/cpp/src/thrift/transport/TPipe.cpp +++ b/lib/cpp/src/thrift/transport/TPipe.cpp @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include #ifdef _WIN32 @@ -40,7 +41,7 @@ void pipe_write(HANDLE pipe, const uint8_t* buf, uint32_t len); uint32_t pseudo_sync_read(HANDLE pipe, HANDLE event, uint8_t* buf, uint32_t len); void pseudo_sync_write(HANDLE pipe, HANDLE event, const uint8_t* buf, uint32_t len); -class TPipeImpl : boost::noncopyable { +class TPipeImpl : TNonCopyable { public: TPipeImpl() {} virtual ~TPipeImpl() {} diff --git a/lib/cpp/src/thrift/transport/TPipe.h b/lib/cpp/src/thrift/transport/TPipe.h index dfc5f2c2fab..002a4b3c1ac 100644 --- a/lib/cpp/src/thrift/transport/TPipe.h +++ b/lib/cpp/src/thrift/transport/TPipe.h @@ -28,7 +28,6 @@ #ifdef _WIN32 #include #endif -#include #ifdef _WIN32 #include #endif diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp index 5923a6236a8..168138e0f46 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.cpp +++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp @@ -20,10 +20,10 @@ #include #include +#include #include #include #include -#include #ifdef _WIN32 #include @@ -39,7 +39,7 @@ namespace transport { using stdcxx::shared_ptr; -class TPipeServerImpl : boost::noncopyable { +class TPipeServerImpl : TNonCopyable { public: TPipeServerImpl() {} virtual ~TPipeServerImpl() {} diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 3f0e28ed8c9..8a1582a9dc6 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -35,11 +35,13 @@ #ifdef HAVE_FCNTL_H #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif #define OPENSSL_VERSION_NO_THREAD_ID_BEFORE 0x10000000L #define OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE 0x10100000L -#include #include #if (OPENSSL_VERSION_NUMBER < OPENSSL_ENGINE_CLEANUP_REQUIRED_BEFORE) #include @@ -49,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +70,7 @@ namespace transport { // OpenSSL initialization/cleanup static bool openSSLInitialized = false; -static boost::shared_array mutexes; +static stdcxx::scoped_array mutexes; static void callbackLocking(int mode, int n, const char*, int) { if (mode & CRYPTO_LOCK) { @@ -120,9 +123,9 @@ void initializeOpenSSL() { // static locking // newer versions of OpenSSL changed CRYPTO_num_locks - see THRIFT-3878 #ifdef CRYPTO_num_locks - mutexes = boost::shared_array(new Mutex[CRYPTO_num_locks()]); + mutexes.reset(new Mutex[CRYPTO_num_locks()]); #else - mutexes = boost::shared_array(new Mutex[ ::CRYPTO_num_locks()]); + mutexes.reset(new Mutex[ ::CRYPTO_num_locks()]); #endif #if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID_BEFORE) diff --git a/lib/cpp/src/thrift/transport/TTransportException.h b/lib/cpp/src/thrift/transport/TTransportException.h index dbbb9711c5c..0a8a0db361f 100644 --- a/lib/cpp/src/thrift/transport/TTransportException.h +++ b/lib/cpp/src/thrift/transport/TTransportException.h @@ -20,7 +20,11 @@ #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ #define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 +#if __cplusplus < 201103L #include +#else +#include +#endif #include #include @@ -90,6 +94,7 @@ class TTransportException : public apache::thrift::TException { * that need to be enforced. */ template To safe_numeric_cast(From i) { +#if __cplusplus < 201103L try { return boost::numeric_cast(i); } @@ -97,6 +102,13 @@ template To safe_numeric_cast(From i) { throw TTransportException(TTransportException::CORRUPTED_DATA, bc.what()); } +#else + if ((std::numeric_limits::is_signed + && i < static_cast(std::numeric_limits::lowest())) + || (i > static_cast(std::numeric_limits::max()))) + throw TTransportException(TTransportException::CORRUPTED_DATA, "out of range"); + return static_cast(i); +#endif } } diff --git a/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.cpp b/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.cpp index 5ac6fe00b02..5bd2e57e1c3 100644 --- a/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.cpp +++ b/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.cpp @@ -19,8 +19,7 @@ #include #include -#include -#include +#include #include namespace apache { @@ -58,9 +57,13 @@ uint32_t TOverlappedWorkItem::overlappedResults(bool signal_failure) { return bytes; } +struct setEventDeleter +{ + void operator()(TAutoResetEvent* ptr) const { SetEvent(ptr->h); } +}; + bool TOverlappedWorkItem::process() { - BOOST_SCOPE_EXIT((&doneSubmittingEvent)) { SetEvent(doneSubmittingEvent.h); } - BOOST_SCOPE_EXIT_END + stdcxx::unique_ptr setEventOnReturn(&doneSubmittingEvent); switch (action) { case (CONNECT): diff --git a/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.h b/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.h index dd0c5c95795..64de07a23a5 100644 --- a/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.h +++ b/lib/cpp/src/thrift/windows/OverlappedSubmissionThread.h @@ -24,8 +24,8 @@ #error "OverlappedSubmissionThread.h is only usable on Windows" #endif +#include #include -#include #include /* @@ -89,7 +89,7 @@ struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) TOverlappedWorkItem : public bool process(); }; -class TOverlappedSubmissionThread : boost::noncopyable { +class TOverlappedSubmissionThread : TNonCopyable { public: void addWorkItem(TOverlappedWorkItem* item); @@ -117,7 +117,7 @@ class TOverlappedSubmissionThread : boost::noncopyable { HANDLE thread_; }; -class TAutoOverlapThread : boost::noncopyable { +class TAutoOverlapThread : TNonCopyable { private: TOverlappedSubmissionThread* p; diff --git a/lib/cpp/src/thrift/windows/Sync.h b/lib/cpp/src/thrift/windows/Sync.h index 5d321996b3d..ca4716c52c3 100644 --- a/lib/cpp/src/thrift/windows/Sync.h +++ b/lib/cpp/src/thrift/windows/Sync.h @@ -24,8 +24,8 @@ #error "windows/Sync.h is only usable on Windows" #endif +#include #include -#include #include /* @@ -36,13 +36,13 @@ namespace apache { namespace thrift { -struct TCriticalSection : boost::noncopyable { +struct TCriticalSection : TNonCopyable { CRITICAL_SECTION cs; TCriticalSection() { InitializeCriticalSection(&cs); } ~TCriticalSection() { DeleteCriticalSection(&cs); } }; -class TAutoCrit : boost::noncopyable { +class TAutoCrit : TNonCopyable { private: CRITICAL_SECTION* cs_; @@ -51,7 +51,7 @@ class TAutoCrit : boost::noncopyable { ~TAutoCrit() { LeaveCriticalSection(cs_); } }; -struct TAutoResetEvent : boost::noncopyable { +struct TAutoResetEvent : TNonCopyable { HANDLE h; TAutoResetEvent() { @@ -64,7 +64,7 @@ struct TAutoResetEvent : boost::noncopyable { ~TAutoResetEvent() { CloseHandle(h); } }; -struct TManualResetEvent : boost::noncopyable { +struct TManualResetEvent : TNonCopyable { HANDLE h; TManualResetEvent() { @@ -77,7 +77,7 @@ struct TManualResetEvent : boost::noncopyable { ~TManualResetEvent() { CloseHandle(h); } }; -struct TAutoHandle : boost::noncopyable { +struct TAutoHandle : TNonCopyable { HANDLE h; explicit TAutoHandle(HANDLE h_ = INVALID_HANDLE_VALUE) : h(h_) {} ~TAutoHandle() { diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.h b/lib/cpp/src/thrift/windows/TWinsockSingleton.h index 0eab6d4ec8a..618a304efa8 100644 --- a/lib/cpp/src/thrift/windows/TWinsockSingleton.h +++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.h @@ -30,9 +30,6 @@ #include -// boost -#include - #if USE_BOOST_THREAD #include #elif USE_STD_THREAD @@ -41,6 +38,7 @@ #error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD #endif +#include #include namespace apache { @@ -51,7 +49,7 @@ namespace transport { * Winsock2 must be intialised once only in order to create sockets. This class * performs a one time initialisation when create is called. */ -class TWinsockSingleton : private boost::noncopyable { +class TWinsockSingleton : private TNonCopyable { public: typedef stdcxx::shared_ptr instance_ptr; diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index d6ab457e2f7..e8a5ee10514 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -380,7 +380,7 @@ void alarm_handler() { // Write some data to the transport to hopefully unblock it. uint8_t* buf = new uint8_t[info->writeLength]; memset(buf, 'b', info->writeLength); - boost::scoped_array array(buf); + stdcxx::scoped_array array(buf); info->transport->write(buf, info->writeLength); info->transport->flush(); diff --git a/lib/cpp/test/TypedefTest.cpp b/lib/cpp/test/TypedefTest.cpp index 24e9265e686..0d492713973 100644 --- a/lib/cpp/test/TypedefTest.cpp +++ b/lib/cpp/test/TypedefTest.cpp @@ -18,11 +18,11 @@ */ #include -#include +#include #include "gen-cpp/TypedefTest_types.h" -BOOST_STATIC_ASSERT((boost::is_same::value)); -BOOST_STATIC_ASSERT((boost::is_same::value)); -BOOST_STATIC_ASSERT( +THRIFT_STATIC_ASSERT((boost::is_same::value)); +THRIFT_STATIC_ASSERT((boost::is_same::value)); +THRIFT_STATIC_ASSERT( (boost::is_same::value));