diff --git a/.travis.yml b/.travis.yml index 03c227b915..514d92cd83 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,14 +56,32 @@ matrix: sources: - ubuntu-toolchain-r-test + - os: linux + compiler: g++-7 + env: TOOLSET=gcc-7 LINK=static + addons: + apt: + packages: + - g++-7 + sources: + - ubuntu-toolchain-r-test + - os: linux compiler: clang++ env: TOOLSET=clang + - os: linux + compiler: clang++ + env: TOOLSET=clang LINK=static + - os: osx compiler: clang++ env: TOOLSET=clang + - os: osx + compiler: clang++ + env: TOOLSET=clang LINK=static + install: - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true - cd .. @@ -78,7 +96,7 @@ install: - ./b2 headers script: - - ./b2 -j 3 libs/serialization/test toolset=$TOOLSET + - ./b2 -j 3 libs/serialization/test toolset=$TOOLSET link=${LINK:-shared} notifications: email: diff --git a/appveyor.yml b/appveyor.yml index 57af71888d..b98be23226 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,17 @@ branches: - develop # - master +environment: + matrix: + - BUILD_TOOLSET: gcc + BUILD_LINK: static + - BUILD_TOOLSET: gcc + BUILD_LINK: shared + - BUILD_TOOLSET: msvc-14.0 + BUILD_LINK: static + - BUILD_TOOLSET: msvc-14.0 + BUILD_LINK: shared + install: - cd .. - git clone -b %APPVEYOR_REPO_BRANCH% https://github.com/boostorg/boost.git boost-root @@ -24,6 +35,7 @@ install: - git submodule init libs/concept_check - git submodule init libs/config - git submodule init libs/container + - git submodule init libs/container_hash - git submodule init libs/core - git submodule init libs/detail - git submodule init libs/filesystem @@ -65,4 +77,4 @@ build: off test_script: - cd libs/serialization/test - - b2 toolset=gcc link=static,shared + - b2 -j2 toolset=%BUILD_TOOLSET% link=%BUILD_LINK% diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 0bde1f9551..4399424815 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -112,20 +112,55 @@ template class singleton : public singleton_module { private: - static T & m_instance; + static void cleanup_func() { + delete static_cast (&get_instance()); + } + + // use a wrapper so that types T with protected constructors + // can be used + class singleton_wrapper : public T { + public: + singleton_wrapper () { + #if !defined(BOOST_ALL_DYN_LINK) && !defined(BOOST_SERIALIZATION_DYN_LINK) + /* Static builds: We're in a single module, use atexit() to + * ensure destruction in reverse of construction. + * (In static builds the compiler-generated order may be wrong...) */ + atexit(&cleanup_func); + #endif + } + }; + + /* This wrapper ensures the instance is cleaned up when the + * module is wound down. (The cleanup of the static variable + * in get_instance() may happen at the wrong time.) */ + struct instance_and_cleanup + { + T& x; + + instance_and_cleanup(T& x) : x(x) { + } + ~instance_and_cleanup() { + #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK) + /* Shared builds: The ordering through global variables is + * sufficient. + * However, avoid atexit() as it may cause destruction order + * issues here. */ + singleton::cleanup_func(); + #endif + } + }; + static instance_and_cleanup m_instance_and_cleanup; // include this to provoke instantiation at pre-execution time static void use(T const *) {} static T & get_instance() { - // use a wrapper so that types T with protected constructors - // can be used - class singleton_wrapper : public T {}; - // Use a heap-allocated instance to work around static variable // destruction order issues: this inner singleton_wrapper<> // instance may be destructed before the singleton<> instance. // Using a 'dumb' static variable lets us precisely choose the // time destructor is invoked. - static singleton_wrapper *t = 0; + // The destruction itself is handled by m_instance_cleanup (for + // shared builds) or in an atexit() function (static builds). + static singleton_wrapper* t = new singleton_wrapper; // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -136,10 +171,7 @@ class singleton : public singleton_module // construct the instance at pre-execution time. This would prevent // our usage/implementation of "locking" and introduce uncertainty into // the sequence of object initializaition. - use(& m_instance); - - if (!t) - t = new singleton_wrapper; + use(& m_instance_and_cleanup.x); return static_cast(*t); } static bool & get_is_destroyed(){ @@ -162,15 +194,13 @@ class singleton : public singleton_module get_is_destroyed() = false; } BOOST_DLLEXPORT ~singleton() { - if (!get_is_destroyed()) { - delete &(get_instance()); - } get_is_destroyed() = true; } }; template -T & singleton< T >::m_instance = singleton< T >::get_instance(); +typename singleton< T >::instance_and_cleanup singleton< T >::m_instance_and_cleanup ( + singleton< T >::get_instance()); } // namespace serialization } // namespace boost diff --git a/include/boost/serialization/void_cast.hpp b/include/boost/serialization/void_cast.hpp index f1b3828611..97c5fe61ba 100644 --- a/include/boost/serialization/void_cast.hpp +++ b/include/boost/serialization/void_cast.hpp @@ -181,13 +181,14 @@ void_caster_primitive::void_caster_primitive() : void_caster( & type_info_implementation::type::get_const_instance(), & type_info_implementation::type::get_const_instance(), - // note:I wanted to displace from 0 here, but at least one compiler - // treated 0 by not shifting it at all. + /* note about displacement: + * displace 0: at least one compiler treated 0 by not shifting it at all + * displace by small value (8): caused ICE on certain mingw gcc versions */ reinterpret_cast( static_cast( - reinterpret_cast(8) + reinterpret_cast(1 << 20) ) - ) - 8 + ) - (1 << 20) ) { recursive_register();