From 69d1b269371b884e11ec5f3f22f7972e823af18f Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Tue, 30 Jan 2018 10:56:21 +0100 Subject: [PATCH 01/13] Pull container_hash git submodule Needed after move from functional. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 57af71888d..c65dc67128 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,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 From 647775934109ec819e8848cd6721d5f3e2e528f8 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Tue, 30 Jan 2018 11:16:27 +0100 Subject: [PATCH 02/13] Try to tweak void_cast to work around ICE on MinGW --- include/boost/serialization/void_cast.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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(); From 89dc4a26b19d8cbe6312153924890abe297e3c78 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Tue, 30 Jan 2018 13:43:42 +0100 Subject: [PATCH 03/13] Add MSVC to Appveyor build matrix --- appveyor.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c65dc67128..c8b01d0f25 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,6 +12,11 @@ branches: - develop # - master +environment: + matrix: + - BUILD_TOOLSET: gcc + - BUILD_TOOLSET: msvc-14.0 + install: - cd .. - git clone -b %APPVEYOR_REPO_BRANCH% https://github.com/boostorg/boost.git boost-root @@ -66,4 +71,4 @@ build: off test_script: - cd libs/serialization/test - - b2 toolset=gcc link=static,shared + - b2 toolset=%BUILD_TOOLSET% link=static,shared From d3bb8d0e503b2fd9745ea21ffe278c5be90a811c Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 31 Jan 2018 08:19:18 +0100 Subject: [PATCH 04/13] Appveyor VMs provide two cores, use them --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c8b01d0f25..26302b48eb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -71,4 +71,4 @@ build: off test_script: - cd libs/serialization/test - - b2 toolset=%BUILD_TOOLSET% link=static,shared + - b2 -j2 toolset=%BUILD_TOOLSET% link=static,shared From 2b61be1285659792bb9a3e18102a30bf0a1d8855 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 31 Jan 2018 09:25:40 +0100 Subject: [PATCH 05/13] Produce distinct jobs for static, shared tests --- appveyor.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 26302b48eb..b98be23226 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,7 +15,13 @@ branches: 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 .. @@ -71,4 +77,4 @@ build: off test_script: - cd libs/serialization/test - - b2 -j2 toolset=%BUILD_TOOLSET% link=static,shared + - b2 -j2 toolset=%BUILD_TOOLSET% link=%BUILD_LINK% From b4b8cbab008917293e33b3fa46177b6ca95b3dd8 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 7 Feb 2018 11:44:22 +0100 Subject: [PATCH 06/13] Travis: Add at least some tests with static linking --- .travis.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) 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: From 7116e61bc2ef21015845483a2b6801a26778823a Mon Sep 17 00:00:00 2001 From: Daniel Arndt Date: Wed, 29 Nov 2017 16:05:03 +0100 Subject: [PATCH 07/13] Fix a potential thread-safety problem --- include/boost/serialization/singleton.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 0bde1f9551..6ac07107c4 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -125,7 +125,7 @@ class singleton : public singleton_module // 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; + static singleton_wrapper* t = new singleton_wrapper; // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -137,9 +137,6 @@ class singleton : public singleton_module // our usage/implementation of "locking" and introduce uncertainty into // the sequence of object initializaition. use(& m_instance); - - if (!t) - t = new singleton_wrapper; return static_cast(*t); } static bool & get_is_destroyed(){ From 715e93a987df1d97ae1d0b68ed06c34d223de8dc Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Tue, 30 Jan 2018 15:25:35 +0100 Subject: [PATCH 08/13] Make singleton_wrapper non-local --- include/boost/serialization/singleton.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 6ac07107c4..5adeb97546 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -112,14 +112,14 @@ template class singleton : public singleton_module { private: + // use a wrapper so that types T with protected constructors + // can be used + class singleton_wrapper : public T {}; + static T & m_instance; // 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. From a9fc9ded1006c9f251c3b2f57481adaa0814b971 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Tue, 30 Jan 2018 13:53:04 +0100 Subject: [PATCH 09/13] Store singleton instance in scoped_ptr<> --- include/boost/serialization/singleton.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 5adeb97546..ddf56afb0b 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -125,7 +126,7 @@ class singleton : public singleton_module // 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 = new singleton_wrapper; + static boost::scoped_ptr t (new singleton_wrapper); // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -159,9 +160,6 @@ class singleton : public singleton_module get_is_destroyed() = false; } BOOST_DLLEXPORT ~singleton() { - if (!get_is_destroyed()) { - delete &(get_instance()); - } get_is_destroyed() = true; } }; From 75af47cac9aefb06da1523916026de30151d5d81 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 7 Feb 2018 09:29:30 +0100 Subject: [PATCH 10/13] Revert "Store singleton instance in scoped_ptr<>" This reverts commit 9f6bc5057a57f902e439ebd815cf6d91379f73f8. --- include/boost/serialization/singleton.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index ddf56afb0b..5adeb97546 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -126,7 +125,7 @@ class singleton : public singleton_module // instance may be destructed before the singleton<> instance. // Using a 'dumb' static variable lets us precisely choose the // time destructor is invoked. - static boost::scoped_ptr t (new singleton_wrapper); + static singleton_wrapper* t = new singleton_wrapper; // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -160,6 +159,9 @@ class singleton : public singleton_module get_is_destroyed() = false; } BOOST_DLLEXPORT ~singleton() { + if (!get_is_destroyed()) { + delete &(get_instance()); + } get_is_destroyed() = true; } }; From 73489e0fb26baccafa251cc6e04669ed9c55e4a3 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 7 Feb 2018 09:48:54 +0100 Subject: [PATCH 11/13] Use a module-scope static variable to handle singleton cleanup --- include/boost/serialization/singleton.hpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 5adeb97546..29ac324750 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -116,6 +116,19 @@ class singleton : public singleton_module // can be used class singleton_wrapper : public T {}; + /* 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_cleanup + { + T* p; + + instance_cleanup() : p(0) { } + ~instance_cleanup() { + if (p) delete static_cast (p); + } + }; + static instance_cleanup m_instance_cleanup; static T & m_instance; // include this to provoke instantiation at pre-execution time static void use(T const *) {} @@ -124,8 +137,10 @@ class singleton : public singleton_module // 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. + // time destructor is invoked. The destruction itself is handled + // by m_instance_cleanup. static singleton_wrapper* t = new singleton_wrapper; + m_instance_cleanup.p = t; // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -159,13 +174,12 @@ class singleton : public singleton_module get_is_destroyed() = false; } BOOST_DLLEXPORT ~singleton() { - if (!get_is_destroyed()) { - delete &(get_instance()); - } get_is_destroyed() = true; } }; +template +typename singleton< T >::instance_cleanup singleton< T >::m_instance_cleanup; template T & singleton< T >::m_instance = singleton< T >::get_instance(); From ee335d1c19c2a91c3daa2bff956649ce17adbf10 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 7 Feb 2018 10:03:11 +0100 Subject: [PATCH 12/13] Merge m_instance and cleanup static vars --- include/boost/serialization/singleton.hpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 29ac324750..50cf4d1142 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -119,17 +119,16 @@ class singleton : public singleton_module /* 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_cleanup + struct instance_and_cleanup { - T* p; + T& x; - instance_cleanup() : p(0) { } - ~instance_cleanup() { - if (p) delete static_cast (p); + instance_and_cleanup(T& x) : x(x) { } + ~instance_and_cleanup() { + delete static_cast (&x); } }; - static instance_cleanup m_instance_cleanup; - static T & m_instance; + 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() { @@ -140,7 +139,6 @@ class singleton : public singleton_module // time destructor is invoked. The destruction itself is handled // by m_instance_cleanup. static singleton_wrapper* t = new singleton_wrapper; - m_instance_cleanup.p = t; // refer to instance, causing it to be instantiated (and // initialized at startup on working compilers) @@ -151,7 +149,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); + use(& m_instance_and_cleanup.x); return static_cast(*t); } static bool & get_is_destroyed(){ @@ -179,9 +177,8 @@ class singleton : public singleton_module }; template -typename singleton< T >::instance_cleanup singleton< T >::m_instance_cleanup; -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 From 4f11789c3998f335461d8c88b1f2712eb20a3f52 Mon Sep 17 00:00:00 2001 From: Frank Richter Date: Wed, 7 Feb 2018 13:49:07 +0100 Subject: [PATCH 13/13] Use atexit() cleanup for static builds --- include/boost/serialization/singleton.hpp | 32 +++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/include/boost/serialization/singleton.hpp b/include/boost/serialization/singleton.hpp index 50cf4d1142..4399424815 100644 --- a/include/boost/serialization/singleton.hpp +++ b/include/boost/serialization/singleton.hpp @@ -112,9 +112,23 @@ template class singleton : public singleton_module { private: + 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 {}; + 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 @@ -123,9 +137,16 @@ class singleton : public singleton_module { T& x; - instance_and_cleanup(T& x) : x(x) { } + instance_and_cleanup(T& x) : x(x) { + } ~instance_and_cleanup() { - delete static_cast (&x); + #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; @@ -136,8 +157,9 @@ class singleton : public singleton_module // 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. The destruction itself is handled - // by m_instance_cleanup. + // time destructor is invoked. + // 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