diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..05c9996 --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,23 @@ +# Copyright 2019 - 2021 Alexander Grund +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +# +# Sample codecov configuration file. Edit as required + +codecov: + max_report_age: off + require_ci_to_pass: yes + notify: + # Increase this if you have multiple coverage collection jobs + after_n_builds: 1 + wait_for_ci: yes + +# Change how pull request comments look +comment: + layout: "reach,diff,flags,footer" + +# Ignore specific files or folders. Glob patterns are supported. +# See https://docs.codecov.com/docs/ignoring-paths +ignore: + - extra/**/* + # - test/**/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1d3869..9dac032 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,20 @@ -name: GitHub Actions CI +# +# Copyright 2020-2021 Peter Dimov +# Copyright 2021 Andrey Semashev +# Copyright 2021-2026 Alexander Grund +# Copyright 2022-2025 James E. King III +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +# +# This workflow uses the Boost.CI reusable workflow which builds a variety of +# configurations of your project, runs tests, and generates code coverage reports. +# +--- +name: Boost.CI + +permissions: + contents: read on: pull_request: @@ -6,694 +22,26 @@ on: branches: - master - develop - - githubactions* + - bugfix/** + - feature/** - fix/** + - github/** - pr/** - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: - contents: read + paths-ignore: + - LICENSE + - meta/** + - README.md jobs: - runner-selection: - runs-on: ubuntu-latest - # runs-on: ${{ github.repository_owner == 'boostorg' && fromJSON('[ "self-hosted", "linux", "x64", "ubuntu-latest-aws" ]') || 'ubuntu-latest' }} - outputs: - labelmatrix: ${{ steps.aws_hosted_runners.outputs.labelmatrix }} - steps: - - name: AWS Hosted Runners - id: aws_hosted_runners - uses: cppalliance/aws-hosted-runners@v1.0.0 - - posix: - if: true - defaults: - run: - shell: bash - - strategy: - fail-fast: false - matrix: - include: - - toolset: gcc-10 - cxxstd: "14,17,2a" - os: ubuntu-22.04 - install: g++-10 - supported: true - - toolset: gcc-11 - cxxstd: "14,17,20" - os: ubuntu-22.04 - install: g++-11 - supported: true - - toolset: gcc-12 - cxxstd: "14,17,20" - os: ubuntu-22.04 - install: g++-12 - supported: true - - toolset: gcc-13 - cxxstd: "14,17,20" - os: ubuntu-22.04 - install: g++-13 - supported: true - - toolset: gcc-14 - cxxstd: "14,17,20" - os: ubuntu-24.04 - install: g++-14 - supported: true - - toolset: clang - install: clang-13 - compiler: clang++-13 - cxxstd: "14,17,20" - os: ubuntu-22.04 - supported: true - - toolset: clang - install: clang-14 - compiler: clang++-14 - cxxstd: "14,17,20" - os: ubuntu-22.04 - supported: true - - toolset: clang - install: clang-15 - compiler: clang++-15 - cxxstd: "14,17,20" - os: ubuntu-22.04 - supported: true - - toolset: clang - install: clang-16 - compiler: clang++-16 - cxxstd: "14,17,20" - os: ubuntu-24.04 - supported: true - - toolset: clang - compiler: clang++-17 - cxxstd: "14,17,20,2b" - os: ubuntu-24.04 - install: clang-17 - supported: true - - toolset: clang - compiler: clang++-18 - cxxstd: "14,17,20,2b" - os: ubuntu-24.04 - install: clang-18 - supported: true - - # macos - - description: macos-14 - toolset: clang - cxxstd: "14,17,2a" - os: macos-14 - supported: true - - description: macos-15 - toolset: clang - cxxstd: "14,17,20" - os: macos-15 - supported: true - - description: macos-26 - toolset: clang - cxxstd: "17,20,23" - os: macos-26 - supported: true - - - - needs: [runner-selection] - # runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }} - runs-on: ${{matrix.os}} - container: ${{ matrix.container }} - env: {B2_USE_CCACHE: 1} - - steps: - - name: Check if running in container - if: matrix.container != '' - run: echo "GHA_CONTAINER=${{ matrix.container }}" >> $GITHUB_ENV - - name: If running in container, upgrade packages - if: matrix.container != '' - run: | - apt-get -o Acquire::Retries=3 update && DEBIAN_FRONTEND=noninteractive apt-get -y install tzdata && apt-get -o Acquire::Retries=3 install -y sudo software-properties-common wget curl apt-transport-https make apt-file sudo unzip libssl-dev build-essential autotools-dev autoconf automake g++ libc++-helpers python ruby cpio gcc-multilib g++-multilib pkgconf python3 ccache libpython-dev locales - sudo apt-add-repository ppa:git-core/ppa - sudo apt-get -o Acquire::Retries=3 update && apt-get -o Acquire::Retries=3 -y install git - python_version=$(python3 -c 'import sys; print("{0.major}.{0.minor}".format(sys.version_info))') - if [[ ${python_version} =~ ^3\.[0-5]$ ]]; then - true - else - apt-get install -y python3-distutils - fi - sudo wget https://bootstrap.pypa.io/pip/$python_version/get-pip.py - sudo python3 get-pip.py - sudo /usr/local/bin/pip install cmake - - uses: actions/checkout@v6 - - - name: Install ccache (Linux) - if: runner.os == 'Linux' - run: sudo apt-get install -y ccache && mkdir -p ~/.ccache - - - name: Install ccache (macOS) - if: runner.os == 'macOS' - run: brew install ccache && mkdir -p ~/.ccache - - - name: Cache ccache - uses: actions/cache@v5 - if: env.B2_USE_CCACHE - with: - path: ~/.ccache - key: ccache-${{matrix.os}}-${{matrix.compiler}}-${{ hashFiles('**/*.cpp', '**/*.hpp', '**/*.c', '**/*.h') }} - restore-keys: | - ccache-${{matrix.os}}-${{matrix.compiler}}- - ccache-${{matrix.os}}- - ccache- - - - name: Install packages - if: matrix.install - run: | - for i in {1..3}; do sudo -E apt-add-repository -y "ppa:ubuntu-toolchain-r/test" && break || sleep 2; done - sudo apt-get update - sudo apt-get install -y ${{matrix.install}} - - - name: Setup Boost - shell: bash - run: | - if [[ $(uname) =~ [Ll]inux ]]; then - echo Installing locales for ${TRAVIS_OS_NAME} ... - sudo /usr/sbin/locale-gen fr_FR - sudo /usr/sbin/locale-gen en_GB - sudo locale -a - echo ...done with locales - fi - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - ./bootstrap.sh - ./b2 -d0 headers - - - name: Run tests - shell: bash - run: | - cd ../boost-root - if [[ "${{matrix.supported}}" != "true" ]] ; then - echo "This configuration is not supported because ${{matrix.supported}}" - exit 0 - fi - toolsets=$(sed 's/,/ /g' <<<"${{matrix.toolset}}") - standards=$(sed 's/,/ /g' <<<"${{matrix.cxxstd}}") - variants="debug release" - err=0 - cd libs/$LIBRARY - for toolset in ${toolsets} ; do - for standard in ${standards} ; do - for variant in ${variants} ; do - if [[ err -ne 0 ]] ; then - echo "skipping: ${toolset} ${standard} ${variant}" - else - echo "running: ${toolset} ${standard} ${variant}" - ../../b2 -j3 test toolset=${toolset} cxxstd=${standard} variant=${variant} - err=$? - fi - done - done - done - [[ $err -ne 0 ]] && false || true - - windows: - if: true - strategy: - fail-fast: false - matrix: - include: - - toolset: msvc-14.3 - cxxstd: "14,17,20,latest" - addrmd: 32,64 - os: windows-2022 - supported: true - - toolset: clang-win - cxxstd: "latest,20,17,14" - addrmd: 32,64 - os: windows-2022 - supported: true - - toolset: gcc - cxxstd: "14,17,2a" - addrmd: 64 - os: windows-2022 - supported: true - - needs: [runner-selection] - # runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }} - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Setup Boost - shell: cmd - run: | - echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% - for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi - echo LIBRARY: %LIBRARY% - echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% - echo GITHUB_BASE_REF: %GITHUB_BASE_REF% - echo GITHUB_REF: %GITHUB_REF% - if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% - set BOOST_BRANCH=develop - for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master - echo BOOST_BRANCH: %BOOST_BRANCH% - cd .. - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% - copy libs\%LIBRARY%\tools\user-config.jam %USERPROFILE%\user-config.jam - cmd /c bootstrap - b2 -d0 headers - - - name: Run tests - shell: bash - run: | - echo "current directory: $(pwd)" - cd ../boost-root - if [[ "${{matrix.supported}}" != "true" ]] ; then - echo "This configuration is not supported because ${{matrix.supported}}" - exit 0 - fi - toolsets=$(sed 's/,/ /g' <<<"${{matrix.toolset}}") - standards=$(sed 's/,/ /g' <<<"${{matrix.cxxstd}}") - address_models=$(sed 's/,/ /g' <<<"${{matrix.addrmd}}") - variants="debug release" - cd libs/$LIBRARY - for toolset in ${toolsets} ; do - for standard in ${standards} ; do - for address_model in ${address_models} ; do - for variant in ${variants} ; do - echo "running: ${toolset} ${standard} ${address_model} ${variant}" - ../../b2 -j3 ${{matrix.cxxflags}} test toolset=${toolset} cxxstd=${standard} address-model=${address_model} variant=${variant} || exit $? - done - done - done - done - - - posix-cmake-subdir: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-22.04 - - os: ubuntu-24.04 - - os: macos-14 - - os: macos-15 - - os: macos-26 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Install packages - if: matrix.install - run: sudo apt-get -y install ${{matrix.install}} - - - name: Install ccache (Linux) - if: runner.os == 'Linux' - run: sudo apt-get install -y ccache - - - name: Install ccache (macOS) - if: runner.os == 'macOS' - run: brew install ccache - - - name: Setup Boost - run: | - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - # HACK: boost.functional seems to be missing? - git submodule update --init libs/functional - - - name: Use library with add_subdirectory - run: | - cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test - mkdir __build__ && cd __build__ - cmake -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. - cmake --build . - ctest --output-on-failure --no-tests=error - - posix-cmake-install: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-22.04 - - os: ubuntu-24.04 - - os: macos-14 - - os: macos-15 - - os: macos-26 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Install packages - if: matrix.install - run: sudo apt-get -y install ${{matrix.install}} - - - name: Install ccache (Linux) - if: runner.os == 'Linux' - run: sudo apt-get install -y ccache - - - name: Install ccache (macOS) - if: runner.os == 'macOS' - run: brew install ccache - - - name: Setup Boost - run: | - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - git submodule update --init libs/functional - - - name: Configure - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. - - - name: Install - run: | - cd ../boost-root/__build__ - cmake --build . --target install - - - name: Use the installed library - run: | - cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ - cmake -DCMAKE_INSTALL_PREFIX=~/.local -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. - cmake --build . - ctest --output-on-failure --no-tests=error - - posix-cmake-test: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-22.04 - - os: ubuntu-24.04 - - os: macos-14 - - os: macos-15 - - os: macos-26 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Install packages - if: matrix.install - run: sudo apt-get -y install ${{matrix.install}} - - - name: Install ccache (Linux) - if: runner.os == 'Linux' - run: sudo apt-get install -y ccache - - - name: Install ccache (macOS) - if: runner.os == 'macOS' - run: brew install ccache - - - name: Setup Boost - run: | - echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY - LIBRARY=${GITHUB_REPOSITORY#*/} - echo LIBRARY: $LIBRARY - echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV - echo GITHUB_BASE_REF: $GITHUB_BASE_REF - echo GITHUB_REF: $GITHUB_REF - REF=${GITHUB_BASE_REF:-$GITHUB_REF} - REF=${REF#refs/heads/} - echo REF: $REF - BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true - echo BOOST_BRANCH: $BOOST_BRANCH - cd .. - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY - - git submodule update --init libs/functional - - - name: Configure - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache .. - - - name: Build tests - run: | - cd ../boost-root/__build__ - cmake --build . --target tests - - - name: Run tests - run: | - cd ../boost-root/__build__ - ctest --output-on-failure --no-tests=error - - windows-cmake-subdir: - strategy: - fail-fast: false - matrix: - include: - - os: windows-2022 - - os: windows-2022 - cmake_args: -T ClangCL -A x64 - - os: windows-2022 - cmake_args: -T ClangCL -A Win32 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Setup Boost - shell: cmd - run: | - echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% - for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi - echo LIBRARY: %LIBRARY% - echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% - echo GITHUB_BASE_REF: %GITHUB_BASE_REF% - echo GITHUB_REF: %GITHUB_REF% - if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% - set BOOST_BRANCH=develop - for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master - echo BOOST_BRANCH: %BOOST_BRANCH% - cd .. - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% - - git submodule update --init libs/functional - - - name: Use library with add_subdirectory (Debug) - shell: cmd - run: | - cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test - mkdir __build__ && cd __build__ - cmake ${{ matrix.cmake_args }} .. - cmake --build . --config Debug - ctest --output-on-failure --no-tests=error -C Debug - - - name: Use library with add_subdirectory (Release) - shell: cmd - run: | - cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__ - cmake ${{ matrix.cmake_args }} .. - cmake --build . --config Release - ctest --output-on-failure --no-tests=error -C Release - - windows-cmake-install: - strategy: - fail-fast: false - matrix: - include: - - os: windows-2022 - - os: windows-2022 - cmake_args: -T ClangCL -A x64 - - os: windows-2022 - cmake_args: -T ClangCL -A Win32 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Setup Boost - shell: cmd - run: | - echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% - for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi - echo LIBRARY: %LIBRARY% - echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% - echo GITHUB_BASE_REF: %GITHUB_BASE_REF% - echo GITHUB_REF: %GITHUB_REF% - if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% - set BOOST_BRANCH=develop - for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master - echo BOOST_BRANCH: %BOOST_BRANCH% - cd .. - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% - - git submodule update --init libs/functional - - - name: Configure - shell: cmd - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ${{ matrix.cmake_args }} .. - - - name: Install (Debug) - shell: cmd - run: | - cd ../boost-root/__build__ - cmake --build . --target install --config Debug - - - name: Install (Release) - shell: cmd - run: | - cd ../boost-root/__build__ - cmake --build . --target install --config Release - - - name: Use the installed library (Debug) - shell: cmd - run: | - cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ - cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ${{ matrix.cmake_args }} .. - cmake --build . --config Debug - ctest --output-on-failure --no-tests=error -C Debug - - - name: Use the installed library (Release) - shell: cmd - run: | - cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__ - cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ${{ matrix.cmake_args }} .. - cmake --build . --config Release - ctest --output-on-failure --no-tests=error -C Release - - windows-cmake-test: - strategy: - fail-fast: false - matrix: - include: - - os: windows-2022 - - os: windows-2022 - cmake_args: -T ClangCL -A x64 - - os: windows-2022 - cmake_args: -T ClangCL -A Win32 - - runs-on: ${{matrix.os}} - - steps: - - uses: actions/checkout@v6 - - - name: Setup Boost - shell: cmd - run: | - echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY% - for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi - echo LIBRARY: %LIBRARY% - echo LIBRARY=%LIBRARY%>>%GITHUB_ENV% - echo GITHUB_BASE_REF: %GITHUB_BASE_REF% - echo GITHUB_REF: %GITHUB_REF% - if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF% - set BOOST_BRANCH=develop - for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master - echo BOOST_BRANCH: %BOOST_BRANCH% - cd .. - git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\ - git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY% - - git submodule update --init libs/functional - - - name: Configure - shell: cmd - run: | - cd ../boost-root - mkdir __build__ && cd __build__ - cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON ${{ matrix.cmake_args }} .. - - - name: Build tests (Debug) - shell: cmd - run: | - cd ../boost-root/__build__ - cmake --build . --target tests --config Debug - - - name: Run tests (Debug) - shell: cmd - run: | - cd ../boost-root/__build__ - ctest --output-on-failure --no-tests=error -C Debug - - - name: Build tests (Release) - shell: cmd - run: | - cd ../boost-root/__build__ - cmake --build . --target tests --config Release - - - name: Run tests (Release) - shell: cmd - run: | - cd ../boost-root/__build__ - ctest --output-on-failure --no-tests=error -C Release + call-boost-ci: + name: Run Boost.CI + uses: boostorg/boost-ci/.github/workflows/reusable.yml@master + with: + enable_cmake: true + exclude_cxxstd: '98,03,0x,11' + exclude_compiler: 'gcc-4.7,gcc-5' + exclude_os: 'ubuntu:16.04' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }} + COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..36b7cd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/include/boost/lockfree/detail/freelist.hpp b/include/boost/lockfree/detail/freelist.hpp index e677bd8..15c2e37 100644 --- a/include/boost/lockfree/detail/freelist.hpp +++ b/include/boost/lockfree/detail/freelist.hpp @@ -17,7 +17,9 @@ #include #include -#include +#if __cplusplus < 201703L +# include +#endif #include #include #include @@ -36,12 +38,37 @@ namespace boost { namespace lockfree { namespace detail { //---------------------------------------------------------------------------------------------------------------------- +template < typename Alloc, std::size_t Align = cacheline_bytes > +struct select_allocator +{ +#if __cplusplus >= 201703L + typedef Alloc type; +#else + typedef boost::alignment::aligned_allocator_adaptor< Alloc, Align > type; +#endif +}; + +template < typename Alloc, std::size_t Align = cacheline_bytes > +using select_allocator_t = typename select_allocator< Alloc, Align >::type; + +//---------------------------------------------------------------------------------------------------------------------- + template < typename T, typename Alloc = std::allocator< T > > -class alignas( cacheline_bytes ) freelist_stack : Alloc +class alignas( cacheline_bytes ) freelist_stack : select_allocator_t< Alloc > { + typedef select_allocator_t< Alloc > allocator_type; + struct BOOST_MAY_ALIAS freelist_node { - tagged_ptr< freelist_node > next; +#if __cplusplus >= 201703L + static constexpr std::size_t freelist_node_alignment = alignof( T ); +#else + static constexpr std::size_t freelist_node_alignment = alignof( std::max_align_t ); +#endif + static constexpr auto tagged_ptr_alignment = alignof( tagged_ptr< freelist_node > ); + static constexpr auto member_alignment = std::max( freelist_node_alignment, tagged_ptr_alignment ); + + alignas( member_alignment ) tagged_ptr< freelist_node > next; }; typedef tagged_ptr< freelist_node > tagged_node_ptr; @@ -52,11 +79,11 @@ class alignas( cacheline_bytes ) freelist_stack : Alloc template < typename Allocator > freelist_stack( Allocator const& alloc, std::size_t n = 0 ) : - Alloc( alloc ), + allocator_type( alloc ), pool_( tagged_node_ptr( NULL ) ) { for ( std::size_t i = 0; i != n; ++i ) { - T* node = Alloc::allocate( 1 ); + T* node = allocator_type::allocate( 1 ); std::memset( (void*)node, 0, sizeof( T ) ); #ifdef BOOST_LOCKFREE_FREELIST_INIT_RUNS_DTOR destruct< false >( node ); @@ -70,7 +97,7 @@ class alignas( cacheline_bytes ) freelist_stack : Alloc void reserve( std::size_t count ) { for ( std::size_t i = 0; i != count; ++i ) { - T* node = Alloc::allocate( 1 ); + T* node = allocator_type::allocate( 1 ); std::memset( (void*)node, 0, sizeof( T ) ); deallocate< ThreadSafe >( node ); } @@ -136,7 +163,7 @@ class alignas( cacheline_bytes ) freelist_stack : Alloc freelist_node* current_ptr = current.get_ptr(); if ( current_ptr ) current = current_ptr->next; - Alloc::deallocate( (T*)current_ptr, 1 ); + allocator_type::deallocate( (T*)current_ptr, 1 ); } } @@ -189,7 +216,7 @@ class alignas( cacheline_bytes ) freelist_stack : Alloc for ( ;; ) { if ( !old_pool.get_ptr() ) { if ( !Bounded ) { - T* ptr = Alloc::allocate( 1 ); + T* ptr = allocator_type::allocate( 1 ); std::memset( (void*)ptr, 0, sizeof( T ) ); return ptr; } else @@ -213,7 +240,7 @@ class alignas( cacheline_bytes ) freelist_stack : Alloc if ( !old_pool.get_ptr() ) { if ( !Bounded ) { - T* ptr = Alloc::allocate( 1 ); + T* ptr = allocator_type::allocate( 1 ); std::memset( (void*)ptr, 0, sizeof( T ) ); return ptr; } else @@ -366,11 +393,11 @@ struct alignas( cacheline_bytes ) compiletime_sized_freelist_storage //---------------------------------------------------------------------------------------------------------------------- template < typename T, typename Alloc = std::allocator< T > > -struct runtime_sized_freelist_storage : boost::alignment::aligned_allocator_adaptor< Alloc, cacheline_bytes > +struct runtime_sized_freelist_storage : select_allocator_t< Alloc > { - typedef boost::alignment::aligned_allocator_adaptor< Alloc, cacheline_bytes > allocator_type; - T* nodes_; - std::size_t node_count_; + typedef select_allocator_t< Alloc > allocator_type; + T* nodes_; + std::size_t node_count_; template < typename Allocator > runtime_sized_freelist_storage( Allocator const& alloc, std::size_t count ) : @@ -407,7 +434,7 @@ class fixed_size_freelist : NodeStorage { struct BOOST_MAY_ALIAS freelist_node { - tagged_index next; + alignas( T ) tagged_index next; }; void initialize( void ) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c9ec0e0..d22e381 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,19 +25,26 @@ rule test_all for local fileb in [ glob *.cpp ] { - all_rules += [ run $(fileb) - : # additional args - : # test-files - : # requirements - acc:-lrt - acc-pa_risc:-lrt - windows,gcc:"-lole32 -loleaut32 -lpsapi -ladvapi32" - hpux,gcc:"-Wl,+as,mpas" - linux,clang:"-latomic" - multi - static - BOOST_TEST_NO_OLD_TOOLS - ] ; + local reqs = + acc:-lrt + acc-pa_risc:-lrt + windows,gcc:"-lole32 -loleaut32 -lpsapi -ladvapi32" + hpux,gcc:"-Wl,+as,mpas" + linux,clang:"-latomic" + linux,intel:"-latomic" + cygwin:"-D_XOPEN_SOURCE=600" + multi + static + BOOST_TEST_NO_OLD_TOOLS + ; + + # Interprocess tests fail under QEMU on s390x (bad_alloc in shared memory) + if $(fileb) = queue_interprocess_test.cpp || $(fileb) = stack_interprocess_test.cpp + { + reqs += s390x:no ; + } + + all_rules += [ run $(fileb) : : : $(reqs) ] ; } return $(all_rules) ; diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt index c293154..0e23abe 100644 --- a/test/cmake_install_test/CMakeLists.txt +++ b/test/cmake_install_test/CMakeLists.txt @@ -1,12 +1,17 @@ -# Copyright 2018, 2019 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 - cmake_minimum_required(VERSION 3.5...3.16) project(cmake_install_test LANGUAGES CXX) -find_package(boost_lockfree REQUIRED) +if(BOOST_CI_INSTALL_TEST) + find_package(Boost CONFIG QUIET COMPONENTS lockfree) + if(NOT TARGET Boost::lockfree) + add_library(Boost::lockfree INTERFACE IMPORTED) + set_target_properties(Boost::lockfree PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") + endif() +else() + find_package(boost_lockfree REQUIRED) +endif() add_executable(main main.cpp) target_link_libraries(main Boost::lockfree) diff --git a/test/cmake_subdir_test/CMakeLists.txt b/test/cmake_subdir_test/CMakeLists.txt index 7a4441a..2d17265 100644 --- a/test/cmake_subdir_test/CMakeLists.txt +++ b/test/cmake_subdir_test/CMakeLists.txt @@ -25,7 +25,6 @@ set(deps detail function function_types - functional fusion io mp11 diff --git a/test/cmake_test/CMakeLists.txt b/test/cmake_test/CMakeLists.txt new file mode 100644 index 0000000..ac5e6d1 --- /dev/null +++ b/test/cmake_test/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 2018, 2019 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 + +cmake_minimum_required(VERSION 3.8...3.20) + +project(boost_lockfree_cmake_test LANGUAGES CXX) + +if(BOOST_CI_INSTALL_TEST) + find_package(Boost CONFIG QUIET COMPONENTS lockfree) + if(NOT TARGET Boost::lockfree) + add_library(Boost::lockfree INTERFACE IMPORTED) + set_target_properties(Boost::lockfree PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") + endif() +else() + set(BOOST_INCLUDE_LIBRARIES lockfree) + add_subdirectory(../../../.. deps/boost EXCLUDE_FROM_ALL) +endif() + +add_executable(main ../cmake_install_test/main.cpp) +target_link_libraries(main Boost::lockfree) + +enable_testing() +add_test(NAME main COMMAND main) +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C $) diff --git a/test/freelist_test.cpp b/test/freelist_test.cpp index e508989..7423fab 100644 --- a/test/freelist_test.cpp +++ b/test/freelist_test.cpp @@ -85,6 +85,9 @@ void run_test( void ) for ( int i = 0; i != 4; ++i ) nodes.insert( fl.template construct< threadsafe, bounded >() ); + for ( dummy* d : nodes ) + fl.template destruct< threadsafe >( d ); + if ( bounded ) test_running.store( false ); } @@ -109,11 +112,18 @@ void oom_test( void ) const bool bounded = true; freelist_type fl( std::allocator< int >(), 8 ); - for ( int i = 0; i != 8; ++i ) - fl.template construct< threadsafe, bounded >(); + std::vector< dummy* > allocated_nodes; + for ( int i = 0; i != 8; ++i ) { + dummy* node = fl.template construct< threadsafe, bounded >(); + allocated_nodes.push_back( node ); + } dummy* allocated = fl.template construct< threadsafe, bounded >(); BOOST_TEST_REQUIRE( allocated == (dummy*)NULL ); + + // Clean up allocated nodes + for ( dummy* node : allocated_nodes ) + fl.template destruct< threadsafe >( node ); } BOOST_AUTO_TEST_CASE( oom_tests ) @@ -148,6 +158,16 @@ struct freelist_tester allocated_nodes( 256 ) {} + ~freelist_tester( void ) + { + // Drain remaining nodes on abnormal exit (e.g., test abort, sanitizer stop) + dummy* node; + while ( allocated_nodes.pop( node ) ) { + working_set.erase( node ); + fl.template destruct< true >( node ); + } + } + void run() { running = true; diff --git a/test/spsc_queue_test.cpp b/test/spsc_queue_test.cpp index 0541051..b4f63b8 100644 --- a/test/spsc_queue_test.cpp +++ b/test/spsc_queue_test.cpp @@ -185,9 +185,11 @@ void spsc_queue_buffer_push_return_value( void ) switch ( EnqueueMode ) { case pointer_and_size: BOOST_TEST_REQUIRE( rb.push( data, xqueue_size ) == xqueue_size ); break; case reference_to_array: BOOST_TEST_REQUIRE( rb.push( data ) == xqueue_size ); break; - case iterator_pair: BOOST_TEST_REQUIRE( rb.push( data, data + xqueue_size ) == data + xqueue_size ); break; - case span_: BOOST_TEST_REQUIRE( rb.push( boost::span< const int >( data, xqueue_size ) ) == xqueue_size ); break; - default: assert( false ); + case iterator_pair: + BOOST_TEST_REQUIRE( std::distance( data, rb.push( data, data + xqueue_size ) ) == (int)xqueue_size ); + break; + case span_: BOOST_TEST_REQUIRE( rb.push( boost::span< const int >( data, xqueue_size ) ) == xqueue_size ); break; + default: assert( false ); } switch ( EnqueueMode ) { @@ -197,7 +199,8 @@ void spsc_queue_buffer_push_return_value( void ) BOOST_TEST_REQUIRE( rb.push( boost::span< const int >( data, xqueue_size ) ) == buffer_size - xqueue_size ); break; case iterator_pair: - BOOST_TEST_REQUIRE( rb.push( data, data + xqueue_size ) == data + buffer_size - xqueue_size ); + BOOST_TEST_REQUIRE( std::distance( data, rb.push( data, data + xqueue_size ) ) + == (int)( buffer_size - xqueue_size ) ); break; default: assert( false ); diff --git a/test/spsc_value_stress_test.cpp b/test/spsc_value_stress_test.cpp index 55cba3f..01b1ec7 100644 --- a/test/spsc_value_stress_test.cpp +++ b/test/spsc_value_stress_test.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE( spsc_value_stress_test ) { boost::lockfree::spsc_value< uint64_t > v; - std::atomic< bool > done; + std::atomic< bool > done( false ); std::thread producer( [ & ] { for ( uint64_t i = 0; i != nodes_per_thread; ++i ) @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE( spsc_value_stress_test_allow_multiple_reads ) { boost::lockfree::spsc_value< uint64_t, boost::lockfree::allow_multiple_reads< true > > v; - std::atomic< bool > done; + std::atomic< bool > done( false ); std::thread producer( [ & ] { for ( uint64_t i = 0; i != nodes_per_thread; ++i ) {