mirror of
				https://github.com/boostorg/smart_ptr.git
				synced 2025-10-26 13:21:39 +01:00 
			
		
		
		
	Compare commits
	
		
			14 Commits
		
	
	
		
			boost-1.89
			...
			feature/qu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 82e80c7175 | ||
|  | 81318213a6 | ||
|  | 85c2a6ea74 | ||
|  | 9723621128 | ||
|  | 6dffeb8a75 | ||
|  | bee3766c04 | ||
|  | 86a873a58c | ||
|  | c808ca7ac8 | ||
|  | a4e0508ab7 | ||
|  | 1dcc441ca1 | ||
|  | cdf118b15b | ||
|  | ab75e1f892 | ||
|  | dcfb560de3 | ||
|  | 362fb1d677 | 
| @@ -34,7 +34,6 @@ local linux_pipeline(name, image, environment, packages = "", sources = [], arch | ||||
|                 'set -e', | ||||
|                 'uname -a', | ||||
|                 'echo $DRONE_STAGE_MACHINE', | ||||
|                 'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -', | ||||
|             ] + | ||||
|             (if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) + | ||||
|             (if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) + | ||||
| @@ -340,40 +339,40 @@ local windows_pipeline(name, image, environment, arch = "amd64") = | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 17 UBSAN", | ||||
|         "Linux 24.04 Clang 17", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan, | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-17", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 17 ASAN", | ||||
|         "Linux 24.04 Clang 18", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan, | ||||
|         "clang-17", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 18 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + ubsan, | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-18", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 18 ASAN", | ||||
|         "Linux 24.04 Clang 19", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + asan, | ||||
|         "clang-18", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.10 Clang 19", | ||||
|         "cppalliance/droneubuntu2410:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-19', CXXSTD: '11,14,17,20,2b' }, | ||||
|         "clang-19", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 20 UBSAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,23,2c' } + ubsan, | ||||
|         "clang-20", | ||||
|     ), | ||||
|  | ||||
|     linux_pipeline( | ||||
|         "Linux 24.04 Clang 20 ASAN", | ||||
|         "cppalliance/droneubuntu2404:1", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++-20', CXXSTD: '11,14,17,20,23,2c' } + asan, | ||||
|         "clang-20", | ||||
|     ), | ||||
|  | ||||
|     macos_pipeline( | ||||
|         "MacOS 10.15 Xcode 12.2 UBSAN", | ||||
|         { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + ubsan, | ||||
|   | ||||
							
								
								
									
										19
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -276,14 +276,6 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - toolset: msvc-14.0 | ||||
|             cxxstd: 14,latest | ||||
|             addrmd: 32,64 | ||||
|             os: windows-2019 | ||||
|           - toolset: msvc-14.2 | ||||
|             cxxstd: "14,17,20,latest" | ||||
|             addrmd: 32,64 | ||||
|             os: windows-2019 | ||||
|           - toolset: msvc-14.3 | ||||
|             cxxstd: "14,17,20,latest" | ||||
|             addrmd: 32,64 | ||||
| @@ -295,7 +287,7 @@ jobs: | ||||
|           - toolset: gcc | ||||
|             cxxstd: "11,14,17,2a" | ||||
|             addrmd: 64 | ||||
|             os: windows-2019 | ||||
|             os: windows-2022 | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
| @@ -497,8 +489,7 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-2019 | ||||
|           - os: windows-2022 | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
| @@ -546,8 +537,7 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-2019 | ||||
|           - os: windows-2022 | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
| @@ -613,8 +603,7 @@ jobs: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         include: | ||||
|           - os: windows-2019 | ||||
|           - os: windows-2022 | ||||
|           - os: windows-latest | ||||
|  | ||||
|     runs-on: ${{matrix.os}} | ||||
|  | ||||
|   | ||||
							
								
								
									
										28
									
								
								appveyor.yml
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								appveyor.yml
									
									
									
									
									
								
							| @@ -21,6 +21,22 @@ environment: | ||||
|       TOOLSET: msvc-14.1 | ||||
|       CXXSTD: 14,17 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 14 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 17 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: 20 | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: msvc-14.2 | ||||
|       CXXSTD: latest | ||||
|       ADDRMD: 32,64 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 | ||||
|       TOOLSET: clang-win | ||||
|       CXXSTD: 14,17,latest | ||||
| @@ -33,14 +49,14 @@ environment: | ||||
|       ADDPATH: C:\cygwin64\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,1z | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | ||||
|       ADDPATH: C:\mingw\bin; | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 | ||||
|       ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,1z | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 | ||||
|       ADDPATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin; | ||||
|       CXXSTD: 11,14,17 | ||||
|     - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 | ||||
|       ADDPATH: C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin; | ||||
|       TOOLSET: gcc | ||||
|       CXXSTD: 11,14,1z | ||||
|       CXXSTD: 11,14,17 | ||||
|  | ||||
| install: | ||||
|   - set BOOST_BRANCH=develop | ||||
|   | ||||
| @@ -1,270 +0,0 @@ | ||||
| // | ||||
| //  sp_collector.cpp | ||||
| // | ||||
| //  Copyright (c) 2002, 2003 Peter Dimov | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/shared_ptr.hpp> | ||||
| #include <boost/smart_ptr/detail/lightweight_mutex.hpp> | ||||
| #include <cstdlib> | ||||
| #include <map> | ||||
| #include <deque> | ||||
| #include <iostream> | ||||
|  | ||||
| typedef std::map< void const *, std::pair<void *, size_t> > map_type; | ||||
|  | ||||
| static map_type & get_map() | ||||
| { | ||||
|     static map_type m; | ||||
|     return m; | ||||
| } | ||||
|  | ||||
| typedef boost::detail::lightweight_mutex mutex_type; | ||||
|  | ||||
| static mutex_type & get_mutex() | ||||
| { | ||||
|     static mutex_type m; | ||||
|     return m; | ||||
| } | ||||
|  | ||||
| static void * init_mutex_before_main = &get_mutex(); | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     class X; | ||||
|  | ||||
|     struct count_layout | ||||
|     { | ||||
|         boost::detail::sp_counted_base * pi; | ||||
|         int id; | ||||
|     }; | ||||
|  | ||||
|     struct shared_ptr_layout | ||||
|     { | ||||
|         X * px; | ||||
|         count_layout pn; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| // assume 4 byte alignment for pointers when scanning | ||||
| size_t const pointer_align = 4; | ||||
|  | ||||
| typedef std::map<void const *, long> map2_type; | ||||
|  | ||||
| static void scan_and_count(void const * area, size_t size, map_type const & m, map2_type & m2) | ||||
| { | ||||
|     unsigned char const * p = static_cast<unsigned char const *>(area); | ||||
|  | ||||
|     for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) | ||||
|     { | ||||
|         shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p); | ||||
|  | ||||
|         if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m.count(q->pn.pi) != 0) | ||||
|         { | ||||
|             ++m2[q->pn.pi]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| typedef std::deque<void const *> open_type; | ||||
|  | ||||
| static void scan_and_mark(void const * area, size_t size, map2_type & m2, open_type & open) | ||||
| { | ||||
|     unsigned char const * p = static_cast<unsigned char const *>(area); | ||||
|  | ||||
|     for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) | ||||
|     { | ||||
|         shared_ptr_layout const * q = reinterpret_cast<shared_ptr_layout const *>(p); | ||||
|  | ||||
|         if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0) | ||||
|         { | ||||
|             open.push_back(q->pn.pi); | ||||
|             m2.erase(q->pn.pi); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void find_unreachable_objects_impl(map_type const & m, map2_type & m2) | ||||
| { | ||||
|     // scan objects for shared_ptr members, compute internal counts | ||||
|  | ||||
|     { | ||||
|         std::cout << "... " << m.size() << " objects in m.\n"; | ||||
|  | ||||
|         for(map_type::const_iterator i = m.begin(); i != m.end(); ++i) | ||||
|         { | ||||
|             boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first); | ||||
|  | ||||
|             BOOST_ASSERT(p->use_count() != 0); // there should be no inactive counts in the map | ||||
|  | ||||
|             m2[ i->first ]; | ||||
|  | ||||
|             scan_and_count(i->second.first, i->second.second, m, m2); | ||||
|         } | ||||
|  | ||||
|         std::cout << "... " << m2.size() << " objects in m2.\n"; | ||||
|     } | ||||
|  | ||||
|     // mark reachable objects | ||||
|  | ||||
|     { | ||||
|         open_type open; | ||||
|  | ||||
|         for(map2_type::iterator i = m2.begin(); i != m2.end(); ++i) | ||||
|         { | ||||
|             boost::detail::sp_counted_base const * p = static_cast<boost::detail::sp_counted_base const *>(i->first); | ||||
|             if(p->use_count() != i->second) open.push_back(p); | ||||
|         } | ||||
|  | ||||
|         std::cout << "... " << open.size() << " objects in open.\n"; | ||||
|  | ||||
|         for(open_type::iterator j = open.begin(); j != open.end(); ++j) | ||||
|         { | ||||
|             m2.erase(*j); | ||||
|         } | ||||
|  | ||||
|         while(!open.empty()) | ||||
|         { | ||||
|             void const * p = open.front(); | ||||
|             open.pop_front(); | ||||
|  | ||||
|             map_type::const_iterator i = m.find(p); | ||||
|             BOOST_ASSERT(i != m.end()); | ||||
|  | ||||
|             scan_and_mark(i->second.first, i->second.second, m2, open); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // m2 now contains the unreachable objects | ||||
| } | ||||
|  | ||||
| std::size_t find_unreachable_objects(bool report) | ||||
| { | ||||
|     map2_type m2; | ||||
|  | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
|     // This will work without the #ifdef, but some compilers warn | ||||
|     // that lock is not referenced | ||||
|  | ||||
|     mutex_type::scoped_lock lock(get_mutex()); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     map_type const & m = get_map(); | ||||
|  | ||||
|     find_unreachable_objects_impl(m, m2); | ||||
|  | ||||
|     if(report) | ||||
|     { | ||||
|         for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) | ||||
|         { | ||||
|             map_type::const_iterator i = m.find(j->first); | ||||
|             BOOST_ASSERT(i != m.end()); | ||||
|             std::cout << "Unreachable object at " << i->second.first << ", " << i->second.second << " bytes long.\n"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return m2.size(); | ||||
| } | ||||
|  | ||||
| typedef std::deque< boost::shared_ptr<X> > free_list_type; | ||||
|  | ||||
| static void scan_and_free(void * area, size_t size, map2_type const & m2, free_list_type & free) | ||||
| { | ||||
|     unsigned char * p = static_cast<unsigned char *>(area); | ||||
|  | ||||
|     for(size_t n = 0; n + sizeof(shared_ptr_layout) <= size; p += pointer_align, n += pointer_align) | ||||
|     { | ||||
|         shared_ptr_layout * q = reinterpret_cast<shared_ptr_layout *>(p); | ||||
|  | ||||
|         if(q->pn.id == boost::detail::shared_count_id && q->pn.pi != 0 && m2.count(q->pn.pi) != 0 && q->px != 0) | ||||
|         { | ||||
|             boost::shared_ptr<X> * ppx = reinterpret_cast< boost::shared_ptr<X> * >(p); | ||||
|             free.push_back(*ppx); | ||||
|             ppx->reset(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void free_unreachable_objects() | ||||
| { | ||||
|     free_list_type free; | ||||
|  | ||||
|     { | ||||
|         map2_type m2; | ||||
|  | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
|         mutex_type::scoped_lock lock(get_mutex()); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|         map_type const & m = get_map(); | ||||
|  | ||||
|         find_unreachable_objects_impl(m, m2); | ||||
|  | ||||
|         for(map2_type::iterator j = m2.begin(); j != m2.end(); ++j) | ||||
|         { | ||||
|             map_type::const_iterator i = m.find(j->first); | ||||
|             BOOST_ASSERT(i != m.end()); | ||||
|             scan_and_free(i->second.first, i->second.second, m2, free); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     std::cout << "... about to free " << free.size() << " objects.\n"; | ||||
| } | ||||
|  | ||||
| // debug hooks | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| void sp_scalar_constructor_hook(void *) | ||||
| { | ||||
| } | ||||
|  | ||||
| void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn) | ||||
| { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
|     mutex_type::scoped_lock lock(get_mutex()); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     get_map()[pn] = std::make_pair(px, size); | ||||
| } | ||||
|  | ||||
| void sp_scalar_destructor_hook(void *) | ||||
| { | ||||
| } | ||||
|  | ||||
| void sp_scalar_destructor_hook(void *, std::size_t, void * pn) | ||||
| { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
|     mutex_type::scoped_lock lock(get_mutex()); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     get_map().erase(pn); | ||||
| } | ||||
|  | ||||
| void sp_array_constructor_hook(void *) | ||||
| { | ||||
| } | ||||
|  | ||||
| void sp_array_destructor_hook(void *) | ||||
| { | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
| @@ -1,227 +0,0 @@ | ||||
| // | ||||
| //  sp_debug_hooks.cpp | ||||
| // | ||||
| //  Copyright (c) 2002, 2003 Peter Dimov | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
| #include <new> | ||||
| #include <cstdlib> | ||||
|  | ||||
| int const m = 2; // m * sizeof(int) must be aligned appropriately | ||||
|  | ||||
| // magic values to mark heap blocks with | ||||
|  | ||||
| int const allocated_scalar  = 0x1234560C; | ||||
| int const allocated_array   = 0x1234560A; | ||||
| int const adopted_scalar    = 0x0567890C; | ||||
| int const adopted_array     = 0x0567890A; | ||||
| int const deleted           = 0x498769DE; | ||||
|  | ||||
| using namespace std; // for compilers where things aren't in std | ||||
|  | ||||
| // operator new | ||||
|  | ||||
| static new_handler get_new_handler() | ||||
| { | ||||
|     new_handler p = set_new_handler(0); | ||||
|     set_new_handler(p); | ||||
|     return p; | ||||
| } | ||||
|  | ||||
| static void * allocate(size_t n, int mark) | ||||
| { | ||||
|     int * pm; | ||||
|  | ||||
|     for(;;) | ||||
|     { | ||||
|         pm = static_cast<int*>(malloc(n + m * sizeof(int))); | ||||
|  | ||||
|         if(pm != 0) break; | ||||
|  | ||||
|         if(new_handler pnh = get_new_handler()) | ||||
|         { | ||||
|             pnh(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return 0; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     *pm = mark; | ||||
|  | ||||
|     return pm + m; | ||||
| } | ||||
|  | ||||
| void * operator new(size_t n) throw(bad_alloc) | ||||
| { | ||||
|     void * p = allocate(n, allocated_scalar); | ||||
|  | ||||
| #if !defined(BOOST_NO_EXCEPTIONS) | ||||
|  | ||||
|     if(p == 0) throw bad_alloc(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     return p; | ||||
| } | ||||
|  | ||||
| void * operator new(size_t n, nothrow_t const &) throw() | ||||
| { | ||||
|     return allocate(n, allocated_scalar); | ||||
| } | ||||
|  | ||||
| void * operator new[](size_t n) throw(bad_alloc) | ||||
| { | ||||
|     void * p = allocate(n, allocated_array); | ||||
|  | ||||
| #if !defined(BOOST_NO_EXCEPTIONS) | ||||
|  | ||||
|     if(p == 0) throw bad_alloc(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     return p; | ||||
| } | ||||
|  | ||||
| void * operator new[](size_t n, nothrow_t const &) throw() | ||||
| { | ||||
|     return allocate(n, allocated_array); | ||||
| } | ||||
|  | ||||
| // debug hooks | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| void sp_scalar_constructor_hook(void * p) | ||||
| { | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm != adopted_scalar);    // second smart pointer to the same address | ||||
|     BOOST_ASSERT(*pm != allocated_array);   // allocated with new[] | ||||
|     BOOST_ASSERT(*pm == allocated_scalar);  // not allocated with new | ||||
|  | ||||
|     *pm = adopted_scalar; | ||||
| } | ||||
|  | ||||
| void sp_scalar_constructor_hook(void * px, std::size_t, void *) | ||||
| { | ||||
|     sp_scalar_constructor_hook(px); | ||||
| } | ||||
|  | ||||
| void sp_scalar_destructor_hook(void * p) | ||||
| { | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm == adopted_scalar);    // attempt to destroy nonmanaged block | ||||
|  | ||||
|     *pm = allocated_scalar; | ||||
| } | ||||
|  | ||||
| void sp_scalar_destructor_hook(void * px, std::size_t, void *) | ||||
| { | ||||
|     sp_scalar_destructor_hook(px); | ||||
| } | ||||
|  | ||||
| // It is not possible to handle the array hooks in a portable manner. | ||||
| // The implementation typically reserves a bit of storage for the number | ||||
| // of objects in the array, and the argument of the array hook isn't | ||||
| // equal to the return value of operator new[]. | ||||
|  | ||||
| void sp_array_constructor_hook(void * /* p */) | ||||
| { | ||||
| /* | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     // adjust p depending on the implementation | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm != adopted_array);     // second smart array pointer to the same address | ||||
|     BOOST_ASSERT(*pm != allocated_scalar);  // allocated with new | ||||
|     BOOST_ASSERT(*pm == allocated_array);   // not allocated with new[] | ||||
|  | ||||
|     *pm = adopted_array; | ||||
| */ | ||||
| } | ||||
|  | ||||
| void sp_array_destructor_hook(void * /* p */) | ||||
| { | ||||
| /* | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     // adjust p depending on the implementation | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm == adopted_array); // attempt to destroy nonmanaged block | ||||
|  | ||||
|     *pm = allocated_array; | ||||
| */ | ||||
| } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| // operator delete | ||||
|  | ||||
| void operator delete(void * p) throw() | ||||
| { | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm != deleted);           // double delete | ||||
|     BOOST_ASSERT(*pm != adopted_scalar);    // delete p.get(); | ||||
|     BOOST_ASSERT(*pm != allocated_array);   // allocated with new[] | ||||
|     BOOST_ASSERT(*pm == allocated_scalar);  // not allocated with new | ||||
|  | ||||
|     *pm = deleted; | ||||
|  | ||||
|     free(pm); | ||||
| } | ||||
|  | ||||
| void operator delete(void * p, nothrow_t const &) throw() | ||||
| { | ||||
|     ::operator delete(p); | ||||
| } | ||||
|  | ||||
| void operator delete[](void * p) throw() | ||||
| { | ||||
|     if(p == 0) return; | ||||
|  | ||||
|     int * pm = static_cast<int*>(p); | ||||
|     pm -= m; | ||||
|  | ||||
|     BOOST_ASSERT(*pm != deleted);           // double delete | ||||
|     BOOST_ASSERT(*pm != adopted_scalar);    // delete p.get(); | ||||
|     BOOST_ASSERT(*pm != allocated_scalar);  // allocated with new | ||||
|     BOOST_ASSERT(*pm == allocated_array);   // not allocated with new[] | ||||
|  | ||||
|     *pm = deleted; | ||||
|  | ||||
|     free(pm); | ||||
| } | ||||
|  | ||||
| void operator delete[](void * p, nothrow_t const &) throw() | ||||
| { | ||||
|     ::operator delete[](p); | ||||
| } | ||||
|  | ||||
| #endif // defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
| @@ -9,19 +9,19 @@ | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_ENABLE_DEBUG_HOOKS has been deprecated in 1.87 and support for it will be removed.") | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_ENABLE_DEBUG_HOOKS has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_STD_ALLOCATOR has been deprecated in 1.87 and support for it will be removed.") | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_STD_ALLOCATOR has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_QUICK_ALLOCATOR has been deprecated in 1.87 and support for it will be removed.") | ||||
| BOOST_PRAGMA_MESSAGE("The macro BOOST_SP_USE_QUICK_ALLOCATOR has been deprecated in 1.87 and support for it was removed in 1.90.") | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -1,198 +1,63 @@ | ||||
| #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
| #define BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
|  | ||||
| // MS compatible compilers support #pragma once | ||||
| // Copyright 2003 David Abrahams | ||||
| // Copyright 2003, 2025 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #if defined(_MSC_VER) && (_MSC_VER >= 1020) | ||||
| # pragma once | ||||
| #endif | ||||
| #include <boost/config/header_deprecated.hpp> | ||||
| #include <memory> | ||||
| #include <cstddef> | ||||
|  | ||||
| // | ||||
| //  detail/quick_allocator.hpp | ||||
| // | ||||
| //  Copyright (c) 2003 David Abrahams | ||||
| //  Copyright (c) 2003 Peter Dimov | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #include <boost/smart_ptr/detail/lightweight_mutex.hpp> | ||||
| #include <boost/smart_ptr/detail/sp_type_traits.hpp> | ||||
|  | ||||
| #include <type_traits> | ||||
| #include <new>              // ::operator new, ::operator delete | ||||
| #include <cstddef>          // std::size_t | ||||
| BOOST_HEADER_DEPRECATED("std::allocator or std::pmr::synchronized_pool_resource") | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| template<unsigned size, unsigned align_> union freeblock | ||||
| template<class T> struct quick_allocator | ||||
| { | ||||
|     typedef typename sp_type_with_alignment<align_>::type aligner_type; | ||||
|     aligner_type aligner; | ||||
|     char bytes[size]; | ||||
|     freeblock * next; | ||||
| }; | ||||
|  | ||||
| template<unsigned size, unsigned align_> struct allocator_impl | ||||
| { | ||||
|     typedef freeblock<size, align_> block; | ||||
|  | ||||
|     // It may seem odd to use such small pages. | ||||
|     // | ||||
|     // However, on a typical Windows implementation that uses | ||||
|     // the OS allocator, "normal size" pages interact with the | ||||
|     // "ordinary" operator new, slowing it down dramatically. | ||||
|     // | ||||
|     // 512 byte pages are handled by the small object allocator, | ||||
|     // and don't interfere with ::new. | ||||
|     // | ||||
|     // The other alternative is to use much bigger pages (1M.) | ||||
|     // | ||||
|     // It is surprisingly easy to hit pathological behavior by | ||||
|     // varying the page size. g++ 2.96 on Red Hat Linux 7.2, | ||||
|     // for example, passionately dislikes 496. 512 seems OK. | ||||
|  | ||||
| #if defined(BOOST_QA_PAGE_SIZE) | ||||
|  | ||||
|     enum { items_per_page = BOOST_QA_PAGE_SIZE / size }; | ||||
|  | ||||
| #else | ||||
|  | ||||
|     enum { items_per_page = 512 / size }; // 1048560 / size | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
|     static lightweight_mutex & mutex() | ||||
|     static void* alloc() | ||||
|     { | ||||
|         static freeblock< sizeof( lightweight_mutex ), std::alignment_of< lightweight_mutex >::value > fbm; | ||||
|         static lightweight_mutex * pm = new( &fbm ) lightweight_mutex; | ||||
|         return *pm; | ||||
|         return std::allocator<T>().allocate( 1 ); | ||||
|     } | ||||
|  | ||||
|     static lightweight_mutex * mutex_init; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     static block * free; | ||||
|     static block * page; | ||||
|     static unsigned last; | ||||
|  | ||||
|     static inline void * alloc() | ||||
|     static void* alloc( std::size_t n ) | ||||
|     { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|         lightweight_mutex::scoped_lock lock( mutex() ); | ||||
| #endif | ||||
|         if(block * x = free) | ||||
|         if( n != sizeof(T) ) // class-specific delete called for a derived object | ||||
|         { | ||||
|             free = x->next; | ||||
|             return x; | ||||
|             return ::operator new( n ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if(last == items_per_page) | ||||
|             { | ||||
|                 // "Listen to me carefully: there is no memory leak" | ||||
|                 // -- Scott Meyers, Eff C++ 2nd Ed Item 10 | ||||
|                 page = ::new block[items_per_page]; | ||||
|                 last = 0; | ||||
|             } | ||||
|  | ||||
|             return &page[last++]; | ||||
|             return alloc(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static inline void * alloc(std::size_t n) | ||||
|     static void dealloc( void* p ) | ||||
|     { | ||||
|         if(n != size) // class-specific new called for a derived object | ||||
|         if( p != 0 ) // 18.4.1.1/13 | ||||
|         { | ||||
|             return ::operator new(n); | ||||
|             std::allocator<T>().deallocate( static_cast<T*>( p ), 1 ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void dealloc( void* p, std::size_t n ) | ||||
|     { | ||||
|         if( n != sizeof(T) ) // class-specific delete called for a derived object | ||||
|         { | ||||
|             ::operator delete( p ); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|             lightweight_mutex::scoped_lock lock( mutex() ); | ||||
| #endif | ||||
|             if(block * x = free) | ||||
|             { | ||||
|                 free = x->next; | ||||
|                 return x; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if(last == items_per_page) | ||||
|                 { | ||||
|                     page = ::new block[items_per_page]; | ||||
|                     last = 0; | ||||
|                 } | ||||
|  | ||||
|                 return &page[last++]; | ||||
|             } | ||||
|             dealloc( p ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static inline void dealloc(void * pv) | ||||
|     { | ||||
|         if(pv != 0) // 18.4.1.1/13 | ||||
|         { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|             lightweight_mutex::scoped_lock lock( mutex() ); | ||||
| #endif | ||||
|             block * pb = static_cast<block *>(pv); | ||||
|             pb->next = free; | ||||
|             free = pb; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static inline void dealloc(void * pv, std::size_t n) | ||||
|     { | ||||
|         if(n != size) // class-specific delete called for a derived object | ||||
|         { | ||||
|             ::operator delete(pv); | ||||
|         } | ||||
|         else if(pv != 0) // 18.4.1.1/13 | ||||
|         { | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|             lightweight_mutex::scoped_lock lock( mutex() ); | ||||
| #endif | ||||
|             block * pb = static_cast<block *>(pv); | ||||
|             pb->next = free; | ||||
|             free = pb; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #ifdef BOOST_HAS_THREADS | ||||
|  | ||||
| template<unsigned size, unsigned align_> | ||||
|   lightweight_mutex * allocator_impl<size, align_>::mutex_init = &allocator_impl<size, align_>::mutex(); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| template<unsigned size, unsigned align_> | ||||
|   freeblock<size, align_> * allocator_impl<size, align_>::free = 0; | ||||
|  | ||||
| template<unsigned size, unsigned align_> | ||||
|   freeblock<size, align_> * allocator_impl<size, align_>::page = 0; | ||||
|  | ||||
| template<unsigned size, unsigned align_> | ||||
|   unsigned allocator_impl<size, align_>::last = allocator_impl<size, align_>::items_per_page; | ||||
|  | ||||
| template<class T> | ||||
| struct quick_allocator: public allocator_impl< sizeof(T), std::alignment_of<T>::value > | ||||
| { | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // #ifndef BOOST_SMART_PTR_DETAIL_QUICK_ALLOCATOR_HPP_INCLUDED | ||||
|   | ||||
| @@ -55,13 +55,6 @@ template< class T, class D > class unique_ptr; | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| int const shared_count_id = 0x2C35F101; | ||||
| int const   weak_count_id = 0x298C38A4; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| struct sp_nothrow_tag {}; | ||||
|  | ||||
| template< class D > struct sp_inplace_tag | ||||
| @@ -112,32 +105,19 @@ private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|     int id_; | ||||
| #endif | ||||
|  | ||||
|     friend class weak_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr shared_count() noexcept: pi_(0) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     constexpr explicit shared_count( sp_counted_base * pi ) noexcept: pi_( pi ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     template<class Y> explicit shared_count( Y * p ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
| @@ -165,9 +145,6 @@ public: | ||||
|     } | ||||
|  | ||||
|     template<class P, class D> shared_count( P p, D d ): pi_(0) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
| @@ -195,9 +172,6 @@ public: | ||||
|     } | ||||
|  | ||||
|     template< class P, class D > shared_count( P p, sp_inplace_tag<D> ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifndef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
| @@ -225,9 +199,6 @@ public: | ||||
|     } | ||||
|  | ||||
|     template<class P, class D, class A> shared_count( P p, D d, A a ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         typedef sp_counted_impl_pda<P, D, A> impl_type; | ||||
|  | ||||
| @@ -272,9 +243,6 @@ public: | ||||
|     } | ||||
|  | ||||
|     template< class P, class D, class A > shared_count( P p, sp_inplace_tag< D >, A a ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         typedef sp_counted_impl_pda< P, D, A > impl_type; | ||||
|  | ||||
| @@ -324,9 +292,6 @@ public: | ||||
|  | ||||
|     template<class Y> | ||||
|     explicit shared_count( std::auto_ptr<Y> & r ): pi_( new sp_counted_impl_p<Y>( r.get() ) ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
| @@ -344,9 +309,6 @@ public: | ||||
|  | ||||
|     template<class Y, class D> | ||||
|     explicit shared_count( std::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         typedef typename sp_convert_reference<D>::type D2; | ||||
|  | ||||
| @@ -367,9 +329,6 @@ public: | ||||
|  | ||||
|     template<class Y, class D> | ||||
|     explicit shared_count( boost::movelib::unique_ptr<Y, D> & r ): pi_( 0 ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         typedef typename sp_convert_reference<D>::type D2; | ||||
|  | ||||
| @@ -391,23 +350,14 @@ public: | ||||
|     ~shared_count() /*noexcept*/ | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->release(); | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         id_ = 0; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     shared_count(shared_count const & r) noexcept: pi_(r.pi_) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if( pi_ != 0 ) pi_->add_ref_copy(); | ||||
|     } | ||||
|  | ||||
|     shared_count(shared_count && r) noexcept: pi_(r.pi_) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
|     { | ||||
|         r.pi_ = 0; | ||||
|     } | ||||
| @@ -493,33 +443,20 @@ private: | ||||
|  | ||||
|     sp_counted_base * pi_; | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|     int id_; | ||||
| #endif | ||||
|  | ||||
|     friend class shared_count; | ||||
|  | ||||
| public: | ||||
|  | ||||
|     constexpr weak_count() noexcept: pi_(0) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(weak_count_id) | ||||
| #endif | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     weak_count(shared_count const & r) noexcept: pi_(r.pi_) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(weak_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
|  | ||||
|     weak_count(weak_count const & r) noexcept: pi_(r.pi_) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(weak_count_id) | ||||
| #endif | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_add_ref(); | ||||
|     } | ||||
| @@ -527,9 +464,6 @@ public: | ||||
| // Move support | ||||
|  | ||||
|     weak_count(weak_count && r) noexcept: pi_(r.pi_) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(weak_count_id) | ||||
| #endif | ||||
|     { | ||||
|         r.pi_ = 0; | ||||
|     } | ||||
| @@ -537,9 +471,6 @@ public: | ||||
|     ~weak_count() /*noexcept*/ | ||||
|     { | ||||
|         if(pi_ != 0) pi_->weak_release(); | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         id_ = 0; | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     weak_count & operator= (shared_count const & r) noexcept | ||||
| @@ -614,9 +545,6 @@ public: | ||||
| }; | ||||
|  | ||||
| inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
| { | ||||
|     if( pi_ == 0 || !pi_->add_ref_lock() ) | ||||
|     { | ||||
| @@ -625,9 +553,6 @@ inline shared_count::shared_count( weak_count const & r ): pi_( r.pi_ ) | ||||
| } | ||||
|  | ||||
| inline shared_count::shared_count( weak_count const & r, sp_nothrow_tag ) noexcept: pi_( r.pi_ ) | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         , id_(shared_count_id) | ||||
| #endif | ||||
| { | ||||
|     if( pi_ != 0 && !pi_->add_ref_lock() ) | ||||
|     { | ||||
|   | ||||
| @@ -18,33 +18,18 @@ | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
| # error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible. | ||||
| #endif | ||||
|  | ||||
| #include <boost/smart_ptr/detail/sp_counted_base.hpp> | ||||
| #include <boost/smart_ptr/detail/deprecated_macros.hpp> | ||||
| #include <boost/core/checked_delete.hpp> | ||||
| #include <boost/core/addressof.hpp> | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
| #include <boost/smart_ptr/detail/quick_allocator.hpp> | ||||
| #endif | ||||
|  | ||||
| #include <memory>           // std::allocator, std::allocator_traits | ||||
| #include <cstddef>          // std::size_t | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_scalar_constructor_hook( void * px, std::size_t size, void * pn ); | ||||
| void sp_scalar_destructor_hook( void * px, std::size_t size, void * pn ); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| namespace detail | ||||
| { | ||||
|  | ||||
| @@ -76,16 +61,10 @@ public: | ||||
|  | ||||
|     explicit sp_counted_impl_p( X * px ): px_( px ) | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook( px, sizeof(X), this ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     void dispose() noexcept override | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_destructor_hook( px_, sizeof(X), this ); | ||||
| #endif | ||||
|         boost::checked_delete( px_ ); | ||||
|     } | ||||
|  | ||||
| @@ -103,34 +82,6 @@ public: | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) ); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return quick_allocator<this_type>::alloc(); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         quick_allocator<this_type>::dealloc( p ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| template<class P, class D> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public sp_counted_base | ||||
| @@ -176,34 +127,6 @@ public: | ||||
|     { | ||||
|         return &reinterpret_cast<char&>( del ); | ||||
|     } | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return std::allocator<this_type>().allocate( 1, static_cast<this_type *>(0) ); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         std::allocator<this_type>().deallocate( static_cast<this_type *>(p), 1 ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|  | ||||
|     void * operator new( std::size_t ) | ||||
|     { | ||||
|         return quick_allocator<this_type>::alloc(); | ||||
|     } | ||||
|  | ||||
|     void operator delete( void * p ) | ||||
|     { | ||||
|         quick_allocator<this_type>::dealloc( p ); | ||||
|     } | ||||
|  | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| template<class P, class D, class A> class BOOST_SYMBOL_VISIBLE sp_counted_impl_pda: public sp_counted_base | ||||
|   | ||||
| @@ -22,15 +22,6 @@ | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // Debug hooks | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_array_constructor_hook(void * p); | ||||
| void sp_array_destructor_hook(void * p); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| //  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to | ||||
| //  is guaranteed, either on destruction of the scoped_array or via an explicit | ||||
| //  reset(). Use shared_array or std::vector if your needs are more complex. | ||||
| @@ -55,16 +46,10 @@ public: | ||||
|  | ||||
|     explicit scoped_array( T * p = 0 ) noexcept : px( p ) | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_array_constructor_hook( px ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
|     ~scoped_array() noexcept | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_array_destructor_hook( px ); | ||||
| #endif | ||||
|         boost::checked_array_delete( px ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -31,15 +31,6 @@ | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // Debug hooks | ||||
|  | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|  | ||||
| void sp_scalar_constructor_hook(void * p); | ||||
| void sp_scalar_destructor_hook(void * p); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| //  scoped_ptr mimics a built-in pointer except that it guarantees deletion | ||||
| //  of the object pointed to, either on destruction of the scoped_ptr or via | ||||
| //  an explicit reset(). scoped_ptr is a simple solution for simple needs; | ||||
| @@ -65,27 +56,18 @@ public: | ||||
|  | ||||
|     explicit scoped_ptr( T * p = 0 ) noexcept : px( p ) | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook( px ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #ifndef BOOST_NO_AUTO_PTR | ||||
|  | ||||
|     explicit scoped_ptr( std::auto_ptr<T> p ) noexcept : px( p.release() ) | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_constructor_hook( px ); | ||||
| #endif | ||||
|     } | ||||
|  | ||||
| #endif | ||||
|  | ||||
|     ~scoped_ptr() noexcept | ||||
|     { | ||||
| #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) | ||||
|         boost::sp_scalar_destructor_hook( px ); | ||||
| #endif | ||||
|         boost::checked_delete( px ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -429,3 +429,6 @@ run sp_type_with_alignment_test.cpp ; | ||||
| run sp_ostream_test.cpp ; | ||||
| run ip_ostream_test.cpp ; | ||||
| run lsp_ostream_test.cpp ; | ||||
|  | ||||
| run shared_ptr_alloc_test.cpp ; | ||||
| run quick_allocator_test.cpp ; | ||||
|   | ||||
							
								
								
									
										99
									
								
								test/quick_allocator_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								test/quick_allocator_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| // Copyright 2025 Peter Dimov | ||||
| // Distributed under the Boost Software License, Version 1.0. | ||||
| // https://www.boost.org/LICENSE_1_0.txt | ||||
|  | ||||
| #include <boost/smart_ptr/detail/quick_allocator.hpp> | ||||
| #include <boost/core/lightweight_test.hpp> | ||||
| #include <cstring> | ||||
|  | ||||
| // The interface of quick_allocator has never been documented, | ||||
| // but in can be inferred from the source code to be | ||||
| // | ||||
| // template<class T> struct quick_allocator | ||||
| // { | ||||
| //     // allocate memory for an object of type T | ||||
| //     static void* alloc(); | ||||
| // | ||||
| //     // deallocate the memory returned from alloc() | ||||
| //     // if p == 0, no effect | ||||
| //     static void dealloc( void* p ); | ||||
| // | ||||
| //     // if n == sizeof(T), returns alloc() | ||||
| //     // otherwise, allocates a memory block of size n | ||||
| //     static void* alloc( std::size_t n ); | ||||
| // | ||||
| //     // deallocate the memory returned from alloc( n ) | ||||
| //     // if p == 0, no effect | ||||
| //     static void dealloc( void* p, std::size_t n ); | ||||
| //  }; | ||||
|  | ||||
| struct X | ||||
| { | ||||
|     int data; | ||||
| }; | ||||
|  | ||||
| struct Y: public X | ||||
| { | ||||
|     int data2; | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     using boost::detail::quick_allocator; | ||||
|  | ||||
|     void* p = quick_allocator<Y>::alloc(); | ||||
|     std::memset( p, 0xAA, sizeof(Y) ); | ||||
|  | ||||
|     { | ||||
|         void* p1 = quick_allocator<X>::alloc(); | ||||
|         std::memset( p1, 0xCC, sizeof(X) ); | ||||
|  | ||||
|         void* p2 = quick_allocator<X>::alloc(); | ||||
|         std::memset( p2, 0xDD, sizeof(X) ); | ||||
|  | ||||
|         BOOST_TEST_NE( p1, p2 ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p1 ), 0xCC ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( 0 ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p1 ), 0xCC ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( p1 ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( p2 ); | ||||
|     } | ||||
|  | ||||
|     { | ||||
|         void* p1 = quick_allocator<X>::alloc( sizeof(X) ); | ||||
|         std::memset( p1, 0xCC, sizeof(X) ); | ||||
|  | ||||
|         void* p2 = quick_allocator<X>::alloc( sizeof(Y) ); | ||||
|         std::memset( p2, 0xDD, sizeof(Y) ); | ||||
|  | ||||
|         BOOST_TEST_NE( p1, p2 ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p1 ), 0xCC ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( 0, sizeof(X) ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p1 ), 0xCC ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( p1, sizeof(X) ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( 0, sizeof(Y) ); | ||||
|         BOOST_TEST_EQ( *static_cast<unsigned char*>( p2 ), 0xDD ); | ||||
|  | ||||
|         quick_allocator<X>::dealloc( p2, sizeof(Y) ); | ||||
|     } | ||||
|  | ||||
|     BOOST_TEST_EQ( *static_cast<unsigned char*>( p ), 0xAA ); | ||||
|     quick_allocator<Y>::dealloc( 0 ); | ||||
|  | ||||
|     BOOST_TEST_EQ( *static_cast<unsigned char*>( p ), 0xAA ); | ||||
|     quick_allocator<Y>::dealloc( p ); | ||||
|  | ||||
|     return boost::report_errors(); | ||||
| } | ||||
| @@ -52,7 +52,7 @@ public: | ||||
|  | ||||
|     void * operator new(std::size_t) | ||||
|     { | ||||
|         return std::allocator<X>().allocate(1, static_cast<X*>(0)); | ||||
|         return std::allocator<X>().allocate(1); | ||||
|     } | ||||
|  | ||||
|     void operator delete(void * p) | ||||
| @@ -122,18 +122,6 @@ int main() | ||||
|     std::cout << "BOOST_HAS_THREADS: (not defined)\n"; | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_STD_ALLOCATOR) | ||||
|     std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (defined)\n"; | ||||
| #else | ||||
|     std::cout << "BOOST_SP_USE_STD_ALLOCATOR: (not defined)\n"; | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_SP_USE_QUICK_ALLOCATOR) | ||||
|     std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (defined)\n"; | ||||
| #else | ||||
|     std::cout << "BOOST_SP_USE_QUICK_ALLOCATOR: (not defined)\n"; | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_QA_PAGE_SIZE) | ||||
|     std::cout << "BOOST_QA_PAGE_SIZE: " << BOOST_QA_PAGE_SIZE << "\n"; | ||||
| #else | ||||
|   | ||||
		Reference in New Issue
	
	Block a user