forked from boostorg/smart_ptr
		
	Compare commits
	
		
			18 Commits
		
	
	
		
			feature/is
			...
			feature/qu
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					82e80c7175 | ||
| 
						 | 
					81318213a6 | ||
| 
						 | 
					85c2a6ea74 | ||
| 
						 | 
					9723621128 | ||
| 
						 | 
					6dffeb8a75 | ||
| 
						 | 
					bee3766c04 | ||
| 
						 | 
					86a873a58c | ||
| 
						 | 
					c808ca7ac8 | ||
| 
						 | 
					a4e0508ab7 | ||
| 
						 | 
					1dcc441ca1 | ||
| 
						 | 
					cdf118b15b | ||
| 
						 | 
					ab75e1f892 | ||
| 
						 | 
					dcfb560de3 | ||
| 
						 | 
					362fb1d677 | ||
| 
						 | 
					79dac0e691 | ||
| 
						 | 
					d08d035bdf | ||
| 
						 | 
					709e446968 | ||
| 
						 | 
					0b0924ff82 | 
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										87
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										87
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -19,41 +19,44 @@ jobs:
 | 
			
		||||
        include:
 | 
			
		||||
          - toolset: gcc-4.8
 | 
			
		||||
            cxxstd: "11"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-4.8-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-5
 | 
			
		||||
            cxxstd: "11,14,1z"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-5-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-6
 | 
			
		||||
            cxxstd: "11,14,1z"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-6-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-7
 | 
			
		||||
            cxxstd: "11,14,17"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-7-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-8
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-8-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-9
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-9-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-10
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: g++-10-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-11
 | 
			
		||||
@@ -73,61 +76,77 @@ jobs:
 | 
			
		||||
            install: g++-13-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-14
 | 
			
		||||
            cxxstd: "11,14,17,20,2b"
 | 
			
		||||
            cxxstd: "11,14,17,20,23,2c"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:24.04
 | 
			
		||||
            install: g++-14-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: gcc-15
 | 
			
		||||
            cxxstd: "11,14,17,20,23,2c"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:25.04
 | 
			
		||||
            install: g++-15-multilib
 | 
			
		||||
            address-model: 32,64
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-3.9
 | 
			
		||||
            cxxstd: "11,14"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-3.9
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-4.0
 | 
			
		||||
            cxxstd: "11,14"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-4.0
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-5.0
 | 
			
		||||
            cxxstd: "11,14,1z"
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            container: ubuntu:18.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-5.0
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-6.0
 | 
			
		||||
            cxxstd: "11,14,17"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-6.0
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-7
 | 
			
		||||
            cxxstd: "11,14,17"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-7
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-8
 | 
			
		||||
            cxxstd: "11,14,17"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-8
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-9
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-9
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-10
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-10
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-11
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-11
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-12
 | 
			
		||||
            cxxstd: "11,14,17,20"
 | 
			
		||||
            os: ubuntu-20.04
 | 
			
		||||
            container: ubuntu:20.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-12
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-13
 | 
			
		||||
            cxxstd: "11,14,17,20,2b"
 | 
			
		||||
@@ -166,10 +185,16 @@ jobs:
 | 
			
		||||
            install: clang-18
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-19
 | 
			
		||||
            cxxstd: "11,14,17,20,2b"
 | 
			
		||||
            container: ubuntu:24.10
 | 
			
		||||
            cxxstd: "11,14,17,20,23,2c"
 | 
			
		||||
            container: ubuntu:24.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-19
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            compiler: clang++-20
 | 
			
		||||
            cxxstd: "11,14,17,20,23,2c"
 | 
			
		||||
            container: ubuntu:25.04
 | 
			
		||||
            os: ubuntu-latest
 | 
			
		||||
            install: clang-20
 | 
			
		||||
          - toolset: clang
 | 
			
		||||
            cxxstd: "11,14,17,20,2b"
 | 
			
		||||
            os: macos-13
 | 
			
		||||
@@ -251,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
 | 
			
		||||
@@ -270,7 +287,7 @@ jobs:
 | 
			
		||||
          - toolset: gcc
 | 
			
		||||
            cxxstd: "11,14,17,2a"
 | 
			
		||||
            addrmd: 64
 | 
			
		||||
            os: windows-2019
 | 
			
		||||
            os: windows-2022
 | 
			
		||||
 | 
			
		||||
    runs-on: ${{matrix.os}}
 | 
			
		||||
 | 
			
		||||
@@ -310,7 +327,6 @@ jobs:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: ubuntu-20.04
 | 
			
		||||
          - os: ubuntu-22.04
 | 
			
		||||
          - os: ubuntu-24.04
 | 
			
		||||
          - os: macos-13
 | 
			
		||||
@@ -359,7 +375,6 @@ jobs:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: ubuntu-20.04
 | 
			
		||||
          - os: ubuntu-22.04
 | 
			
		||||
          - os: ubuntu-24.04
 | 
			
		||||
          - os: macos-13
 | 
			
		||||
@@ -418,7 +433,6 @@ jobs:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: ubuntu-20.04
 | 
			
		||||
          - os: ubuntu-22.04
 | 
			
		||||
          - os: ubuntu-24.04
 | 
			
		||||
          - os: macos-13
 | 
			
		||||
@@ -475,8 +489,7 @@ jobs:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: windows-2019
 | 
			
		||||
          - os: windows-2022
 | 
			
		||||
          - os: windows-latest
 | 
			
		||||
 | 
			
		||||
    runs-on: ${{matrix.os}}
 | 
			
		||||
 | 
			
		||||
@@ -524,8 +537,7 @@ jobs:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - os: windows-2019
 | 
			
		||||
          - os: windows-2022
 | 
			
		||||
          - os: windows-latest
 | 
			
		||||
 | 
			
		||||
    runs-on: ${{matrix.os}}
 | 
			
		||||
 | 
			
		||||
@@ -591,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,5 +1,5 @@
 | 
			
		||||
////
 | 
			
		||||
Copyright 2019, 2020 Peter Dimov
 | 
			
		||||
Copyright 2019-2025 Peter Dimov
 | 
			
		||||
 | 
			
		||||
Distributed under the Boost Software License, Version 1.0.
 | 
			
		||||
 | 
			
		||||
@@ -13,6 +13,10 @@ http://www.boost.org/LICENSE_1_0.txt
 | 
			
		||||
:toc-title:
 | 
			
		||||
:idprefix: changelog_
 | 
			
		||||
 | 
			
		||||
## Changes in 1.88.0
 | 
			
		||||
 | 
			
		||||
* Fix `operator<<` for wide streams (accidentally broken in 1.87.0)
 | 
			
		||||
 | 
			
		||||
## Changes in 1.87.0
 | 
			
		||||
 | 
			
		||||
* {cpp}03 is no longer supported, a {cpp}11 compiler is required.
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								include/boost/smart_ptr/detail/sp_cxx20_constexpr.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								include/boost/smart_ptr/detail/sp_cxx20_constexpr.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
#ifndef BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
#pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//  detail/sp_noexcept.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright 2025 Mathias Stearn
 | 
			
		||||
//
 | 
			
		||||
//  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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// This macro is used to mark functions as constexpr if the compiler supports
 | 
			
		||||
// constexpr destructors. Since you can't have a constexpr smart pointer object,
 | 
			
		||||
// everything except null constructors are guided behind this macro. Because
 | 
			
		||||
// this also guards a use of dynamic_cast, we need to check for its availability
 | 
			
		||||
// as well. It isn't worth splitting out since all known compilers that support
 | 
			
		||||
// constexpr dynamic_cast also support constexpr destructors.
 | 
			
		||||
//
 | 
			
		||||
// WARNING: This does not check for changing active member of a union in
 | 
			
		||||
// constant expressions which is allowed in C++20. If that is needed, we
 | 
			
		||||
// need to raise the checked version to 202002L.
 | 
			
		||||
#if defined(__cpp_constexpr_dynamic_alloc) && __cpp_constexpr_dynamic_alloc >= 201907L \
 | 
			
		||||
    && defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
 | 
			
		||||
#define BOOST_SP_CXX20_CONSTEXPR constexpr
 | 
			
		||||
#else
 | 
			
		||||
#define BOOST_SP_CXX20_CONSTEXPR
 | 
			
		||||
#define BOOST_SP_NO_CXX20_CONSTEXPR
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_SMART_PTR_DETAIL_SP_CXX20_CONSTEXPR_HPP_INCLUDED
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
//  See http://www.boost.org/libs/smart_ptr/ for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/smart_ptr/detail/sp_cxx20_constexpr.hpp>
 | 
			
		||||
#include <boost/smart_ptr/detail/sp_convertible.hpp>
 | 
			
		||||
#include <boost/smart_ptr/detail/sp_noexcept.hpp>
 | 
			
		||||
#include <boost/assert.hpp>
 | 
			
		||||
@@ -53,29 +54,29 @@ public:
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr( T * p, bool add_ref = true ): px( p )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( T * p, bool add_ref = true ): px( p )
 | 
			
		||||
    {
 | 
			
		||||
        if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class U>
 | 
			
		||||
    intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
 | 
			
		||||
    : px( rhs.get() )
 | 
			
		||||
    {
 | 
			
		||||
        if( px != 0 ) intrusive_ptr_add_ref( px );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
 | 
			
		||||
    {
 | 
			
		||||
        if( px != 0 ) intrusive_ptr_add_ref( px );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~intrusive_ptr()
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR ~intrusive_ptr()
 | 
			
		||||
    {
 | 
			
		||||
        if( px != 0 ) intrusive_ptr_release( px );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
 | 
			
		||||
    template<class U> BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
@@ -83,12 +84,12 @@ public:
 | 
			
		||||
 | 
			
		||||
// Move support
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px )
 | 
			
		||||
    {
 | 
			
		||||
        rhs.px = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
@@ -97,76 +98,76 @@ public:
 | 
			
		||||
    template<class U> friend class intrusive_ptr;
 | 
			
		||||
 | 
			
		||||
    template<class U>
 | 
			
		||||
    intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
 | 
			
		||||
    : px( rhs.px )
 | 
			
		||||
    {
 | 
			
		||||
        rhs.px = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<class U>
 | 
			
		||||
    intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr & operator=(intrusive_ptr const & rhs)
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr const & rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    intrusive_ptr & operator=(T * rhs)
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(T * rhs)
 | 
			
		||||
    {
 | 
			
		||||
        this_type(rhs).swap(*this);
 | 
			
		||||
        return *this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset()
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR void reset()
 | 
			
		||||
    {
 | 
			
		||||
        this_type().swap( *this );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset( T * rhs )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs )
 | 
			
		||||
    {
 | 
			
		||||
        this_type( rhs ).swap( *this );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset( T * rhs, bool add_ref )
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs, bool add_ref )
 | 
			
		||||
    {
 | 
			
		||||
        this_type( rhs, add_ref ).swap( *this );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * get() const noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR T * get() const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * detach() noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR T * detach() noexcept
 | 
			
		||||
    {
 | 
			
		||||
        T * ret = px;
 | 
			
		||||
        px = 0;
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT( px != 0 );
 | 
			
		||||
        return *px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_ASSERT( px != 0 );
 | 
			
		||||
        return px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    explicit operator bool () const noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR explicit operator bool () const noexcept
 | 
			
		||||
    {
 | 
			
		||||
        return px != 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void swap(intrusive_ptr & rhs) noexcept
 | 
			
		||||
    BOOST_SP_CXX20_CONSTEXPR void swap(intrusive_ptr & rhs) noexcept
 | 
			
		||||
    {
 | 
			
		||||
        T * tmp = px;
 | 
			
		||||
        px = rhs.px;
 | 
			
		||||
@@ -178,101 +179,101 @@ private:
 | 
			
		||||
    T * px;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a.get() == b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a.get() == b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a.get() != b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a == b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return a != b.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return p.get() == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return p.get() == 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return p.get() != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return p.get() != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return std::less<T *>()(a.get(), b.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept
 | 
			
		||||
{
 | 
			
		||||
    lhs.swap(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mem_fn support
 | 
			
		||||
 | 
			
		||||
template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept
 | 
			
		||||
template<class T> BOOST_SP_CXX20_CONSTEXPR inline T * get_pointer(intrusive_ptr<T> const & p) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return p.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// pointer casts
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return const_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
 | 
			
		||||
{
 | 
			
		||||
    return dynamic_cast<T *>(p.get());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept
 | 
			
		||||
{
 | 
			
		||||
    T * p2 = dynamic_cast<T*>( p.get() );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -245,6 +245,7 @@ run atomic_sp_test.cpp ;
 | 
			
		||||
 | 
			
		||||
run sp_constexpr_test.cpp ;
 | 
			
		||||
run sp_constexpr_test2.cpp ;
 | 
			
		||||
compile ip_constexpr_test.cpp ;
 | 
			
		||||
 | 
			
		||||
run atomic_sp_constexpr_test.cpp ;
 | 
			
		||||
 | 
			
		||||
@@ -428,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 ;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								test/ip_constexpr_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								test/ip_constexpr_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
			
		||||
//
 | 
			
		||||
// ip_constexpr_test.cpp
 | 
			
		||||
//
 | 
			
		||||
// Copyright 2025 Mathias Stearn
 | 
			
		||||
//
 | 
			
		||||
// 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/intrusive_ptr.hpp>
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_SP_NO_CXX20_CONSTEXPR
 | 
			
		||||
 | 
			
		||||
struct dummy {
 | 
			
		||||
    // no-ops, so safe on pointers to static constexpr variables
 | 
			
		||||
    friend constexpr void intrusive_ptr_add_ref(const dummy *) {}
 | 
			
		||||
    friend constexpr void intrusive_ptr_release(const dummy *) {}
 | 
			
		||||
};
 | 
			
		||||
static constexpr dummy d;
 | 
			
		||||
 | 
			
		||||
struct subdummy : dummy {};
 | 
			
		||||
 | 
			
		||||
// Test that basic operations work at compile time.
 | 
			
		||||
static_assert(bool(boost::intrusive_ptr<const dummy>(&d)));
 | 
			
		||||
static_assert(!bool(boost::intrusive_ptr<dummy>(nullptr)));
 | 
			
		||||
static_assert(!bool(boost::intrusive_ptr<dummy>()));
 | 
			
		||||
static_assert(!bool(boost::intrusive_ptr<dummy>(boost::intrusive_ptr<subdummy>())));
 | 
			
		||||
static_assert(&*boost::intrusive_ptr<const dummy>(&d) == &d);
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(&d).operator->() == &d);
 | 
			
		||||
static_assert(boost::intrusive_ptr<dummy>() == nullptr);
 | 
			
		||||
static_assert(boost::intrusive_ptr<dummy>() == boost::intrusive_ptr<dummy>(nullptr));
 | 
			
		||||
static_assert(boost::intrusive_ptr<dummy>() != boost::intrusive_ptr<const dummy>(&d));
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(&d) != nullptr);
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d));
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d).get());
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(&d) == boost::intrusive_ptr<const dummy>(&d).detach());
 | 
			
		||||
static_assert(!(boost::intrusive_ptr<const dummy>(&d) < boost::intrusive_ptr<const dummy>(&d)));
 | 
			
		||||
static_assert(boost::get_pointer(boost::intrusive_ptr<const dummy>(&d)) == &d);
 | 
			
		||||
static_assert(boost::static_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
 | 
			
		||||
static_assert(boost::const_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
 | 
			
		||||
static_assert(boost::dynamic_pointer_cast<const dummy>( boost::intrusive_ptr<const dummy>(&d)) == &d);
 | 
			
		||||
 | 
			
		||||
constexpr auto lvalue = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
constexpr auto lvalue_convertible = boost::intrusive_ptr<const subdummy>();
 | 
			
		||||
static_assert(boost::intrusive_ptr<const dummy>(lvalue) == &d);
 | 
			
		||||
static_assert(!boost::intrusive_ptr<const dummy>(lvalue_convertible));
 | 
			
		||||
static_assert(boost::static_pointer_cast<const dummy>(lvalue) == &d);
 | 
			
		||||
static_assert(boost::const_pointer_cast<const dummy>(lvalue) == &d);
 | 
			
		||||
static_assert(boost::dynamic_pointer_cast<const dummy>(lvalue) == &d);
 | 
			
		||||
 | 
			
		||||
// Works in places that static_assert doesn't, like expressions with
 | 
			
		||||
// non-constexpr variables in constexpr functions.
 | 
			
		||||
template <typename T> constexpr void semi_static_assert(T b) {
 | 
			
		||||
    if (!b)
 | 
			
		||||
        throw "assertion failed"; // Not constexpr so fails compile.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
constexpr bool test_swap() {
 | 
			
		||||
    auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
    auto p2 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
    swap(p1, p2);
 | 
			
		||||
    semi_static_assert(!p1 && p2);
 | 
			
		||||
    p1.swap(p2);
 | 
			
		||||
    semi_static_assert(p1 && !p2);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
static_assert(test_swap());
 | 
			
		||||
 | 
			
		||||
constexpr bool test_reset_assign() {
 | 
			
		||||
    // Test assignments resulting in nullptr
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1.reset();
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1.reset(nullptr);
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1 = nullptr;
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1 = boost::intrusive_ptr<subdummy>();
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        p1 = lvalue_convertible;
 | 
			
		||||
        semi_static_assert(!p1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Test assignments resulting in &d
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        p1.reset(&d);
 | 
			
		||||
        semi_static_assert(p1 == &d);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        p1.reset(&d, true);
 | 
			
		||||
        semi_static_assert(p1 == &d);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        p1 = boost::intrusive_ptr<const dummy>(&d);
 | 
			
		||||
        semi_static_assert(p1 == &d);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        p1 = lvalue;
 | 
			
		||||
        semi_static_assert(p1 == &d);
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto p1 = boost::intrusive_ptr<const dummy>();
 | 
			
		||||
        p1 = &d;
 | 
			
		||||
        semi_static_assert(p1 == &d);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
static_assert(test_reset_assign());
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										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