diff --git a/CGAL_Core/include/CGAL/CORE/MemoryPool.h b/CGAL_Core/include/CGAL/CORE/MemoryPool.h index 64121773f97..596613a727b 100644 --- a/CGAL_Core/include/CGAL/CORE/MemoryPool.h +++ b/CGAL_Core/include/CGAL/CORE/MemoryPool.h @@ -38,6 +38,13 @@ #include #include #include +#if defined(CGAL_HAS_THREADS) && defined(BOOST_GCC) && BOOST_GCC < 90100 +// Force the use of Boost.Thread with g++ and C++11, because of the PR66944 +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66944 +// See also CGAL PR #1888 +// https://github.com/CGAL/cgal/pull/1888#issuecomment-278284232 +# include +#endif #include // for placement new #include @@ -69,7 +76,7 @@ public: t = t->next; } //); - //Cgal_warning_msg(count == nObjects * blocks.size(), + //CGAL_warning_msg(count == nObjects * blocks.size(), // "Cannot delete memory as there are cyclic references"); if(count == nObjects * blocks.size()){ @@ -85,16 +92,38 @@ public: // Access the corresponding static global allocator. static MemoryPool& global_allocator() { - CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Self, memPool); +#if defined(CGAL_HAS_THREADS) && defined(BOOST_GCC) && BOOST_GCC < 90100 + if(memPool_ptr.get() == nullptr) {memPool_ptr.reset(new Self());} + Self& memPool = * memPool_ptr.get(); +#endif return memPool; } private: - Thunk* head; // next available block in the pool + Thunk* head; // next available block in the pool std::vector blocks; +#if defined(CGAL_HAS_THREADS) && defined(BOOST_GCC) && BOOST_GCC < 90100 + static boost::thread_specific_ptr memPool_ptr; +#elif defined(CGAL_HAS_THREADS) // use the C++11 implementation + static thread_local Self memPool; +#else // not CGAL_HAS_THREADS + static Self memPool; +#endif // not CGAL_HAS_THREADS }; +#if defined(CGAL_HAS_THREADS) && defined(BOOST_GCC) && BOOST_GCC < 90100 +template +boost::thread_specific_ptr > +MemoryPool::memPool_ptr; +#else // use C++11 or without CGAL_HAS_THREADS +template +# ifdef CGAL_HAS_THREADS +thread_local +# endif +MemoryPool MemoryPool::memPool; +#endif + template< class T, int nObjects > void* MemoryPool< T, nObjects >::allocate(std::size_t) { if ( head == 0 ) { // if no more memory in the pool diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index e8754dbcdb4..f6a6b8e6ee0 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -390,6 +390,11 @@ installed as binaries. \cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples depend on the binary library `Boost.Program_options`. +As an exception, because of a bug in the \gcc compiler about the \cpp 11 +keyword `thread_local`, the `CGAL_Core` library always requires +the binary library `Boost.Thread` if the \gcc compiler version 9.0 or +earlier is used. + In case the \sc{Boost} libraries are not installed on your system already, you can obtain them from `https://www.boost.org/`. For Visual C++ you can download precompiled libraries from `https://sourceforge.net/projects/boost/files/boost-binaries/`. diff --git a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake index 609f086694b..053c4f6ab67 100644 --- a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake @@ -53,6 +53,13 @@ endif() # keyword, or ``PUBLIC`` otherwise. # +# See the release notes of CGAL-4.10: CGAL_Core now requires +# Boost.Thread, with GNU G++ < 9.1. +if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1) + include(${CMAKE_CURRENT_LIST_DIR}/CGAL_TweakFindBoost.cmake) + find_package( Boost 1.48 REQUIRED COMPONENTS thread system ) +endif() + function(CGAL_setup_CGAL_Core_dependencies target) if(ARGV1 STREQUAL INTERFACE) set(keyword INTERFACE) @@ -63,4 +70,21 @@ function(CGAL_setup_CGAL_Core_dependencies target) use_CGAL_GMP_support(CGAL_Core ${keyword}) target_compile_definitions(${target} ${keyword} CGAL_USE_CORE=1) target_link_libraries( CGAL_Core ${keyword} CGAL::CGAL ) + + # See the release notes of CGAL-4.10: CGAL_Core now requires + # Boost.Thread, with GNU G++. + if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1) + if(TARGET Boost::thread) + target_link_libraries( CGAL_Core ${keyword} Boost::thread) + else() + # Note that `find_package( Boost...)` must be called in the + # function `CGAL_setup_CGAL_Core_dependencies()` because the + # calling `CMakeLists.txt` may also call `find_package(Boost)` + # between the inclusion of this module, and the call to this + # function. That resets `Boost_LIBRARIES`. + find_package( Boost 1.48 REQUIRED thread system ) + target_link_libraries( CGAL_Core ${keyword} ${Boost_LIBRARIES}) + endif() + endif() + endfunction() diff --git a/Installation/include/CGAL/tss.h b/Installation/include/CGAL/tss.h index 7096b1612e8..22f47a46632 100644 --- a/Installation/include/CGAL/tss.h +++ b/Installation/include/CGAL/tss.h @@ -22,64 +22,22 @@ #include #if defined( CGAL_HAS_THREADS ) -# ifdef CGAL_CAN_USE_CXX11_THREAD_LOCAL -//# pragma message ( "Use keyword thread_local" ) -# else -//# pragma message ("Use thread_local from boost") -# define CGAL_USE_BOOST_THREAD -# include -# endif +# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(TYPE, VAR) \ + static thread_local TYPE VAR -# ifdef CGAL_USE_BOOST_THREAD -# define CGAL_STATIC_THREAD_LOCAL_USE_BOOST 1 +# define CGAL_STATIC_THREAD_LOCAL_VARIABLE(TYPE, VAR, ARG1) \ + static thread_local TYPE VAR(ARG1) -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(TYPE, VAR) \ - static boost::thread_specific_ptr VAR##_ptr; \ - if(VAR##_ptr.get() == nullptr) {VAR##_ptr.reset(new TYPE());} \ - TYPE& VAR = * VAR##_ptr.get() - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE(TYPE, VAR, ARG1) \ - static boost::thread_specific_ptr VAR##_ptr; \ - if(VAR##_ptr.get() == nullptr) {VAR##_ptr.reset(new TYPE(ARG1));} \ - TYPE& VAR = * VAR##_ptr.get() - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_2(TYPE, VAR, ARG1, ARG2) \ - static boost::thread_specific_ptr VAR##_ptr; \ - if(VAR##_ptr.get() == nullptr) {VAR##_ptr.reset(new TYPE(ARG1,ARG2));} \ - TYPE& VAR = * VAR##_ptr.get() - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_3(TYPE, VAR, ARG1, ARG2, ARG3) \ - static boost::thread_specific_ptr VAR##_ptr; \ - if(VAR##_ptr.get() == nullptr) {VAR##_ptr.reset(new TYPE(ARG1,ARG2,ARG3));} \ - TYPE& VAR = * VAR##_ptr.get() - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_4(TYPE, VAR, ARG1, ARG2, ARG3, ARG4) \ - static boost::thread_specific_ptr VAR##_ptr; \ - if(VAR##_ptr.get() == nullptr) {VAR##_ptr.reset(new TYPE(ARG1,ARG2,ARG3,ARG4));} \ - TYPE& VAR = * VAR##_ptr.get() - - - -# else // not CGAL_USE_BOOST_THREAD, -> use C++11 thread_local - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(TYPE, VAR) \ - static thread_local TYPE VAR - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE(TYPE, VAR, ARG1) \ - static thread_local TYPE VAR(ARG1) - -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_2(TYPE, VAR, ARG1, ARG2) \ +# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_2(TYPE, VAR, ARG1, ARG2) \ static thread_local TYPE VAR(ARG1,ARG2) -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_3(TYPE, VAR, ARG1, ARG2, ARG3) \ +# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_3(TYPE, VAR, ARG1, ARG2, ARG3) \ static thread_local TYPE VAR(ARG1,ARG2,ARG3) -# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_4(TYPE, VAR, ARG1, ARG2, ARG3, ARG4) \ +# define CGAL_STATIC_THREAD_LOCAL_VARIABLE_4(TYPE, VAR, ARG1, ARG2, ARG3, ARG4) \ static thread_local TYPE VAR(ARG1,ARG2,ARG3,ARG4) -# endif // not CGAL_USE_BOOST_THREAD - #else // not CGAL_HAS_THREADS # define CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(TYPE, VAR) static TYPE VAR