Compare commits

..

2 Commits

Author SHA1 Message Date
Peter Dimov 6c24c30c42 Update test/CMakeLists.txt 2023-06-25 18:20:36 +03:00
Christian Mazakas 0d2eaa0b21 Add explicit tests for rw_spinlock 2023-06-25 13:05:10 +03:00
69 changed files with 581 additions and 909 deletions
+16 -30
View File
@@ -31,28 +31,14 @@ environment:
B2_VARIANT: debug,release
matrix:
- FLAVOR: Visual Studio 2008
- FLAVOR: Visual Studio 2008, 2010, 2012
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-9.0
B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2010
- FLAVOR: Visual Studio 2013, 2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-10.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2012
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-11.0
B2_ADDRESS_MODEL: 32 # No 64bit support
- FLAVOR: Visual Studio 2013
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-12.0
- FLAVOR: Visual Studio 2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
B2_TOOLSET: msvc-14.0
B2_TOOLSET: msvc-12.0,msvc-14.0
- FLAVOR: Visual Studio 2017, C++14
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
@@ -69,32 +55,32 @@ environment:
B2_CXXSTD: latest
B2_TOOLSET: msvc-14.1
- FLAVOR: cygwin (32-bit, C++03)
- FLAVOR: cygwin (32-bit, C++03,11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 03
B2_CXXSTD: 03,11
B2_TOOLSET: gcc
- FLAVOR: cygwin (32-bit, C++11)
- FLAVOR: cygwin (32-bit, C++14,1z)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 11
B2_CXXSTD: 14,1z
B2_TOOLSET: gcc
- FLAVOR: cygwin (32-bit, C++14)
- FLAVOR: cygwin (64-bit, C++03,11)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 14
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 03,11
B2_TOOLSET: gcc
- FLAVOR: cygwin (32-bit, C++1z)
- FLAVOR: cygwin (64-bit, C++14,1z)
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
ADDPATH: C:\cygwin\bin;
B2_ADDRESS_MODEL: 32
B2_CXXSTD: 1z
ADDPATH: C:\cygwin64\bin;
B2_ADDRESS_MODEL: 64
B2_CXXSTD: 14,1z
B2_TOOLSET: gcc
- FLAVOR: cygwin (64-bit, latest, C++03)
+39 -57
View File
@@ -32,16 +32,6 @@ env:
CODECOV_NAME: Github Actions
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:
defaults:
run:
@@ -52,55 +42,50 @@ jobs:
matrix:
include:
# Linux, gcc
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', install: 'g++-7' }
- { compiler: gcc-8, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', install: 'g++-8' }
- { compiler: gcc-9, cxxstd: '03,11,14,17', os: 'ubuntu-22.04', install: 'g++-9' }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', install: 'g++-10' }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', install: 'g++-11' }
- { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-20.04, install: 'g++-7' }
- { compiler: gcc-8, cxxstd: '03,11,14,17', os: ubuntu-20.04, install: 'g++-8' }
- { compiler: gcc-9, cxxstd: '03,11,14,17', os: ubuntu-20.04, install: 'g++-9' }
- { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'g++-10' }
- { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'g++-11' }
- { name: "gcc-12 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: gcc-12, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
compiler: gcc-12, cxxstd: '03,11,14', os: ubuntu-22.04, ccache_key: "san1" }
- { name: "gcc-12 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: gcc-12, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" }
compiler: gcc-12, cxxstd: '17,20,2b', os: ubuntu-22.04, ccache_key: "san2" }
- { name: Collect coverage, coverage: yes,
compiler: gcc-12, cxxstd: '03,20', os: 'ubuntu-22.04', install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" }
compiler: gcc-12, cxxstd: '03,20', os: ubuntu-22.04, install: 'g++-12-multilib', address-model: '32,64', ccache_key: "cov" }
- { name: "cfoa tsan (gcc-12)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: gcc-12,
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes, ccache_key: "tsan" }
- { name: "cfoa tsan (gcc)", cxxstd: '11,14,17,20,2b', os: ubuntu-22.04, compiler: gcc-12,
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes }
# Linux, clang, libc++
- { compiler: clang-7, cxxstd: '03,11,14,17', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-7 libc++-7-dev libc++abi-7-dev' }
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-dev' }
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-dev' }
# clang-12 doesn't work on 'ubuntu-22.04', the linker can't find -lunwind for some reason
- { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-20.04, stdlib: libc++, install: 'clang-7 libc++-7-dev libc++abi-7-dev' }
- { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-10 libc++-10-dev libc++abi-10-dev' }
- { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-11 libc++-11-dev libc++abi-11-dev' }
# clang-12 doesn't work on ubuntu-22.04, the linker can't find -lunwind for some reason
- { name: "clang-12 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: clang-12, cxxstd: '03,11,14', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san1" }
compiler: clang-12, cxxstd: '03,11,14', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san1" }
- { name: "clang-12 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: clang-12, cxxstd: '17,20,2b', os: 'ubuntu-20.04', stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { compiler: clang-13, cxxstd: '03,11,14,17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
compiler: clang-12, cxxstd: '17,20,2b', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev', ccache_key: "san2" }
- { compiler: clang-13, cxxstd: '03,11,14,17,20,2b', os: ubuntu-22.04, stdlib: libc++, install: 'clang-13 libc++-13-dev libc++abi-13-dev' }
- { compiler: clang-14, cxxstd: '03,11,14,17,20,2b', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' }
# not using libc++ because of https://github.com/llvm/llvm-project/issues/52771
- { name: "clang-14 w/ sanitizers (03,11,14)", sanitize: yes,
compiler: clang-14, cxxstd: '03,11,14', os: 'ubuntu-22.04', ccache_key: "san1" }
compiler: clang-14, cxxstd: '03,11,14', os: ubuntu-22.04, ccache_key: "san1" }
- { name: "clang-14 w/ sanitizers (17,20,2b)", sanitize: yes,
compiler: clang-14, cxxstd: '17,20,2b', os: 'ubuntu-22.04', ccache_key: "san2" }
compiler: clang-14, cxxstd: '17,20,2b', os: ubuntu-22.04, ccache_key: "san2" }
- { name: "cfoa tsan (clang-14)", cxxstd: '11,14,17,20,2b', os: 'ubuntu-22.04', compiler: clang-14,
- { name: "cfoa tsan (clang)", cxxstd: '11,14,17,20,2b', os: ubuntu-22.04, compiler: clang-14,
targets: 'libs/unordered/test//cfoa_tests', thread-sanitize: yes,
stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev', ccache_key: "tsan" }
- { compiler: clang-15, cxxstd: '03,11,14,17,20,2b', os: 'ubuntu-22.04', stdlib: libc++, install: 'clang-15 libc++-15-dev libc++abi-15-dev' }
stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' }
# OSX, clang
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: 'macos-11' }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: 'macos-12', sanitize: yes, ccache_key: "san1" }
- { compiler: clang, cxxstd: '11,14,17,2a', os: 'macos-12', thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests', ccache_key: "tsan" }
- { compiler: clang, cxxstd: '03,11,14,17,20,2b', os: 'macos-13' }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, }
- { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-12, sanitize: yes }
- { compiler: clang, cxxstd: '11,14,17,2a', os: macos-12, thread-sanitize: yes, targets: 'libs/unordered/test//cfoa_tests' }
timeout-minutes: 360
# posix (gcc-12 w/ sanitizers is taking longer than 210 minutes
# timeout-minutes: 210
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
timeout-minutes: 180
runs-on: ${{matrix.os}}
container: ${{matrix.container}}
env: {B2_USE_CCACHE: 1}
@@ -244,16 +229,15 @@ jobs:
fail-fast: false
matrix:
include:
- { toolset: msvc-14.0, cxxstd: '14,latest', addrmd: '32,64', os: 'windows-2019', variant: 'debug,release' }
- { toolset: msvc-14.2, cxxstd: '14,17,20,latest', addrmd: '32,64', os: 'windows-2019', variant: 'debug,release' }
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '64', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '/RTCc' }
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '32', os: 'windows-2022', variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '"/RTCc /arch:IA32"' }
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: 'windows-2022', variant: 'debug,release' }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: 'windows-2019', variant: 'debug,release' }
- { toolset: msvc-14.0, cxxstd: '14,latest', addrmd: '32,64', os: windows-2019, variant: 'debug,release' }
- { toolset: msvc-14.2, cxxstd: '14,17,20,latest', addrmd: '32,64', os: windows-2019, variant: 'debug,release' }
- { toolset: msvc-14.3, cxxstd: '14,17,20,latest', addrmd: '32,64', os: windows-2022, variant: 'debug,release' }
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '64', os: windows-2022, variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '/RTCc' }
- { toolset: msvc-14.3, cxxstd: '14', addrmd: '32', os: windows-2022, variant: 'debug', defines: '_ALLOW_RTCc_IN_STL', cxxflags: '"/RTCc /arch:IA32"' }
- { toolset: clang-win, cxxstd: '14,17,latest', addrmd: '32,64', os: windows-2022, variant: 'debug,release' }
- { toolset: gcc, cxxstd: '03,11,14,17,2a', addrmd: '64', os: windows-2019, variant: 'debug,release' }
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
@@ -310,8 +294,7 @@ jobs:
- { sys: MINGW32, compiler: gcc, cxxstd: '03,11,17,20' }
- { sys: MINGW64, compiler: gcc, cxxstd: '03,11,17,20' }
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)['windows-latest'] }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
@@ -365,12 +348,11 @@ jobs:
fail-fast: false
matrix:
include:
- { os: 'ubuntu-20.04', build_shared: ON, build_type: Debug, generator: 'Unix Makefiles' }
- { os: 'windows-2019', build_shared: ON, build_type: Debug, generator: 'Visual Studio 16 2019' }
- { os: ubuntu-20.04, build_shared: ON, build_type: Debug, generator: 'Unix Makefiles' }
- { os: windows-2019, build_shared: ON, build_type: Debug, generator: 'Visual Studio 16 2019' }
timeout-minutes: 120
needs: [runner-selection]
runs-on: ${{ fromJSON(needs.runner-selection.outputs.labelmatrix)[matrix.os] }}
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v3
Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

-5
View File
@@ -6,11 +6,6 @@
:github-pr-url: https://github.com/boostorg/unordered/pull
:cpp: C++
== Release 1.84.0
* Added debug mode mechanisms for detecting illegal reentrancies into
a `boost::concurrent_flat_map` from user code.
== Release 1.83.0 - Major update
* Added `boost::concurrent_flat_map`, a fast, thread-safe hashmap based on open addressing.
@@ -1,138 +0,0 @@
/* Copyright 2023 Joaquin M Lopez Munoz.
* 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)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_FOA_ANNOTATED_MUTEX_HPP
#define BOOST_UNORDERED_DETAIL_FOA_ANNOTATED_MUTEX_HPP
#include <boost/config.hpp>
#include <utility>
namespace boost{
namespace unordered{
namespace detail{
namespace foa{
/* reference: https://clang.llvm.org/docs/ThreadSafetyAnalysis.htm */
#if defined(BOOST_CLANG)&&!defined(SWIG)
#define BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(x) __attribute__((x))
#else
#define BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(x)
#endif
#define BOOST_UNORDERED_CAPABILITY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(capability(x))
#define BOOST_UNORDERED_SCOPED_CAPABILITY \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(scoped_lockable)
#define BOOST_UNORDERED_GUARDED_BY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(guarded_by(x))
#define BOOST_UNORDERED_PT_GUARDED_BY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(pt_guarded_by(x))
#define BOOST_UNORDERED_ACQUIRED_BEFORE(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(acquired_before(__VA_ARGS__))
#define BOOST_UNORDERED_ACQUIRED_AFTER(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(acquired_after(__VA_ARGS__))
#define BOOST_UNORDERED_REQUIRES(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(requires_capability(__VA_ARGS__))
#define BOOST_UNORDERED_REQUIRES_SHARED(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(requires_shared_capability(__VA_ARGS__))
#define BOOST_UNORDERED_ACQUIRE(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(acquire_capability(__VA_ARGS__))
#define BOOST_UNORDERED_ACQUIRE_SHARED(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(acquire_shared_capability(__VA_ARGS__))
#define BOOST_UNORDERED_RELEASE(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(release_capability(__VA_ARGS__))
#define BOOST_UNORDERED_RELEASE_SHARED(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(release_shared_capability(__VA_ARGS__))
#define BOOST_UNORDERED_RELEASE_GENERIC(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(release_generic_capability(__VA_ARGS__))
#define BOOST_UNORDERED_TRY_ACQUIRE(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(try_acquire_capability(__VA_ARGS__))
#define BOOST_UNORDERED_TRY_ACQUIRE_SHARED(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR( \
try_acquire_shared_capability(__VA_ARGS__))
#define BOOST_UNORDERED_EXCLUDES(...) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(locks_excluded(__VA_ARGS__))
#define BOOST_UNORDERED_ASSERT_CAPABILITY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(assert_capability(x))
#define BOOST_UNORDERED_ASSERT_SHARED_CAPABILITY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(assert_shared_capability(x))
#define BOOST_UNORDERED_RETURN_CAPABILITY(x) \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(lock_returned(x))
#define BOOST_UNORDERED_NO_THREAD_SAFETY_ANALYSIS \
BOOST_UNORDERED_THREAD_ANNOTATION_ATTR(no_thread_safety_analysis)
template<typename Mutex>
struct BOOST_UNORDERED_CAPABILITY("mutex") annotated_mutex:Mutex
{
using super=Mutex;
using super::super;
void lock() noexcept(noexcept(super::lock()))
BOOST_UNORDERED_ACQUIRE()
{
super::lock();
}
bool try_lock() noexcept(noexcept(super::try_lock()))
BOOST_UNORDERED_TRY_ACQUIRE(true)
{
return super::try_lock();
}
void unlock() noexcept(noexcept(super::unlock()))
BOOST_UNORDERED_RELEASE()
{
super::unlock();
}
void lock_shared() noexcept(noexcept(super::lock_shared()))
BOOST_UNORDERED_ACQUIRE_SHARED()
{
super::lock_shared();
}
bool try_lock_shared() noexcept(noexcept(super::try_lock_shared()))
BOOST_UNORDERED_TRY_ACQUIRE_SHARED(true)
{
return super::try_lock();
}
void unlock_shared() noexcept(noexcept(super::unlock_shared()))
BOOST_UNORDERED_RELEASE_SHARED()
{
super::unlock_shared();
}
};
} /* namespace foa */
} /* namespace detail */
} /* namespace unordered */
} /* namespace boost */
#endif
@@ -19,9 +19,7 @@
#include <boost/cstdint.hpp>
#include <boost/mp11/tuple.hpp>
#include <boost/static_assert.hpp>
#include <boost/unordered/detail/foa/annotated_mutex.hpp>
#include <boost/unordered/detail/foa/core.hpp>
#include <boost/unordered/detail/foa/reentrancy_check.hpp>
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/unordered/detail/foa/tuple_rotate_right.hpp>
#include <cstddef>
@@ -109,10 +107,8 @@ public:
return mutexes[pos];
}
void lock()noexcept BOOST_UNORDERED_NO_THREAD_SAFETY_ANALYSIS
{for(std::size_t n=0;n<N;)mutexes[n++].lock();}
void unlock()noexcept BOOST_UNORDERED_NO_THREAD_SAFETY_ANALYSIS
{for(auto n=N;n>0;)mutexes[--n].unlock();}
void lock()noexcept{for(std::size_t n=0;n<N;)mutexes[n++].lock();}
void unlock()noexcept{for(auto n=N;n>0;)mutexes[--n].unlock();}
private:
cache_aligned_array<Mutex,N> mutexes;
@@ -130,10 +126,8 @@ public:
/* not used but VS in pre-C++17 mode needs to see it for RVO */
shared_lock(const shared_lock&);
void lock() BOOST_UNORDERED_NO_THREAD_SAFETY_ANALYSIS
{BOOST_ASSERT(!owns);m.lock_shared();owns=true;}
void unlock() BOOST_UNORDERED_NO_THREAD_SAFETY_ANALYSIS
{BOOST_ASSERT(owns);m.unlock_shared();owns=false;}
void lock(){BOOST_ASSERT(!owns);m.lock_shared();owns=true;}
void unlock(){BOOST_ASSERT(owns);m.unlock_shared();owns=false;}
private:
Mutex &m;
@@ -217,7 +211,7 @@ struct atomic_integral
struct group_access
{
using mutex_type=annotated_mutex<rw_spinlock>;
using mutex_type=rw_spinlock;
using shared_lock_guard=shared_lock<mutex_type>;
using exclusive_lock_guard=lock_guard<mutex_type>;
using insert_counter_type=std::atomic<boost::uint32_t>;
@@ -841,11 +835,11 @@ public:
}
private:
using mutex_type=annotated_mutex<rw_spinlock>;
using multimutex_type=annotated_mutex<multimutex<mutex_type,128>>; // TODO: adapt 128 to the machine
using shared_lock_guard=reentrancy_checked<shared_lock<mutex_type>>;
using exclusive_lock_guard=reentrancy_checked<lock_guard<multimutex_type>>;
using exclusive_bilock_guard=reentrancy_bichecked<scoped_bilock<multimutex_type>>;
using mutex_type=rw_spinlock;
using multimutex_type=multimutex<mutex_type,128>; // TODO: adapt 128 to the machine
using shared_lock_guard=shared_lock<mutex_type>;
using exclusive_lock_guard=lock_guard<multimutex_type>;
using exclusive_bilock_guard=scoped_bilock<multimutex_type>;
using group_shared_lock_guard=typename group_access::shared_lock_guard;
using group_exclusive_lock_guard=typename group_access::exclusive_lock_guard;
using group_insert_counter_type=typename group_access::insert_counter_type;
@@ -865,18 +859,18 @@ private:
{
thread_local auto id=(++thread_counter)%mutexes.size();
return shared_lock_guard{this,mutexes[id]};
return shared_lock_guard{mutexes[id]};
}
inline exclusive_lock_guard exclusive_access()const
{
return exclusive_lock_guard{this,mutexes};
return exclusive_lock_guard{mutexes};
}
static inline exclusive_bilock_guard exclusive_access(
const concurrent_table& x,const concurrent_table& y)
{
return {&x,&y,x.mutexes,y.mutexes};
return {x.mutexes,y.mutexes};
}
template<typename Hash2,typename Pred2>
@@ -884,7 +878,7 @@ private:
const concurrent_table& x,
const concurrent_table<TypePolicy,Hash2,Pred2,Allocator>& y)
{
return {&x,&y,x.mutexes,y.mutexes};
return {x.mutexes,y.mutexes};
}
/* Tag-dispatched shared/exclusive group access */
@@ -1,181 +0,0 @@
/* Copyright 2023 Joaquin M Lopez Munoz.
* 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)
*
* See https://www.boost.org/libs/unordered for library home page.
*/
#ifndef BOOST_UNORDERED_DETAIL_FOA_REENTRANCY_CHECK_HPP
#define BOOST_UNORDERED_DETAIL_FOA_REENTRANCY_CHECK_HPP
#include <boost/assert.hpp>
#include <boost/unordered/detail/foa/annotated_mutex.hpp>
#include <utility>
#if !defined(BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK)&& \
!defined(BOOST_ASSERT_IS_VOID)
#define BOOST_UNORDERED_REENTRANCY_CHECK
#endif
namespace boost{
namespace unordered{
namespace detail{
namespace foa{
#if defined(BOOST_UNORDERED_REENTRANCY_CHECK)
class entry_trace
{
public:
entry_trace(const void* px_):px{px_}
{
if(px){
BOOST_ASSERT_MSG(!find(px),"reentrancy not allowed");
header()=this;
}
}
/* not used but VS in pre-C++17 mode needs to see it for RVO */
entry_trace(const entry_trace&);
~entry_trace(){clear();}
void clear()
{
if(px){
header()=next;
px=nullptr;
}
}
private:
static entry_trace*& header()
{
thread_local entry_trace *pe=nullptr;
return pe;
}
static bool find(const void* px)
{
for(auto pe=header();pe;pe=pe->next){
if(pe->px==px)return true;
}
return false;
}
const void *px;
entry_trace *next=header();
};
template<typename>
struct reentrancy_checked;
template<template <typename> class LockGuard,typename Mutex>
struct BOOST_UNORDERED_SCOPED_CAPABILITY reentrancy_checked<LockGuard<Mutex>>
{
reentrancy_checked(const void* px,Mutex& m_)
BOOST_UNORDERED_ACQUIRE(m_):
tr{px},lck{m_},m{m_}{}
reentrancy_checked(const reentrancy_checked& x) BOOST_UNORDERED_ACQUIRE(x.m);
~reentrancy_checked() BOOST_UNORDERED_RELEASE() = default;
void unlock() BOOST_UNORDERED_RELEASE()
{
lck.unlock();
tr.clear();
}
entry_trace tr;
LockGuard<Mutex> lck;
Mutex& m;
};
template<typename>
struct reentrancy_bichecked;
template<template <typename> class LockGuard,typename Mutex>
struct BOOST_UNORDERED_SCOPED_CAPABILITY reentrancy_bichecked<LockGuard<Mutex>>
{
template<typename Mutex1, typename Mutex2>
reentrancy_bichecked(const void* px,const void* py,Mutex1& m1_,Mutex2& m2_)
BOOST_UNORDERED_ACQUIRE(m1_,m2_):
tr1{px},tr2{py!=px?py:nullptr},lck{m1_,m2_},m1{m1_},m2{m2_}{}
reentrancy_bichecked(const reentrancy_bichecked& x)
BOOST_UNORDERED_ACQUIRE(x.m1,x.m2);
~reentrancy_bichecked() BOOST_UNORDERED_RELEASE() = default;
void unlock() BOOST_UNORDERED_RELEASE()
{
lck.unlock();
tr2.clear();
tr1.clear();
}
entry_trace tr1,tr2;
LockGuard<Mutex> lck;
Mutex &m1,&m2;
};
#else
template<typename>
struct reentrancy_checked;
template<template <typename> class LockGuard,typename Mutex>
struct BOOST_UNORDERED_SCOPED_CAPABILITY reentrancy_checked<LockGuard<Mutex>>
{
reentrancy_checked(const void*,Mutex& m_)
BOOST_UNORDERED_ACQUIRE(m_):
lck{m_},m{m_}{}
reentrancy_checked(const reentrancy_checked& x) BOOST_UNORDERED_ACQUIRE(x.m);
~reentrancy_checked() BOOST_UNORDERED_RELEASE() = default;
void unlock() BOOST_UNORDERED_RELEASE()
{
lck.unlock();
}
LockGuard<Mutex> lck;
Mutex& m;
};
template<typename>
struct reentrancy_bichecked;
template<template <typename> class LockGuard,typename Mutex>
struct BOOST_UNORDERED_SCOPED_CAPABILITY reentrancy_bichecked<LockGuard<Mutex>>
{
template<typename Mutex1, typename Mutex2>
reentrancy_bichecked(const void*,const void*,Mutex1& m1_,Mutex2& m2_)
BOOST_UNORDERED_ACQUIRE(m1_,m2_):
lck{m1_,m2_},m1{m1_},m2{m2_}{}
reentrancy_bichecked(const reentrancy_bichecked& x)
BOOST_UNORDERED_ACQUIRE(x.m1,x.m2);
~reentrancy_bichecked() BOOST_UNORDERED_RELEASE() = default;
void unlock() BOOST_UNORDERED_RELEASE()
{
lck.unlock();
}
LockGuard<Mutex> lck;
Mutex &m1,&m2;
};
#endif
} /* namespace foa */
} /* namespace detail */
} /* namespace unordered */
} /* namespace boost */
#endif
+2 -8
View File
@@ -140,6 +140,8 @@ foa_tests(SOURCES exception/merge_exception_tests.cpp)
# CFOA tests
cfoa_tests(SOURCES cfoa/rw_spinlock_tests.cpp)
cfoa_tests(SOURCES cfoa/latch_tests.cpp)
cfoa_tests(SOURCES cfoa/insert_tests.cpp)
cfoa_tests(SOURCES cfoa/erase_tests.cpp)
cfoa_tests(SOURCES cfoa/try_emplace_tests.cpp)
@@ -158,13 +160,5 @@ cfoa_tests(SOURCES cfoa/exception_erase_tests.cpp)
cfoa_tests(SOURCES cfoa/exception_constructor_tests.cpp)
cfoa_tests(SOURCES cfoa/exception_assign_tests.cpp)
cfoa_tests(SOURCES cfoa/exception_merge_tests.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test2.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test3.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test4.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test5.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test6.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test7.cpp)
cfoa_tests(SOURCES cfoa/rw_spinlock_test8.cpp)
endif()
+2 -9
View File
@@ -176,6 +176,8 @@ alias foa_tests :
;
local CFOA_TESTS =
latch_tests
rw_spinlock_tests
insert_tests
erase_tests
try_emplace_tests
@@ -194,15 +196,6 @@ local CFOA_TESTS =
exception_constructor_tests
exception_assign_tests
exception_merge_tests
rw_spinlock_test
rw_spinlock_test2
rw_spinlock_test3
rw_spinlock_test4
rw_spinlock_test5
rw_spinlock_test6
rw_spinlock_test7
rw_spinlock_test8
reentrancy_check_test
;
for local test in $(CFOA_TESTS)
+1 -1
View File
@@ -787,7 +787,7 @@ namespace {
std::thread t1, t2, t3;
boost::compat::latch start_latch(2), end_latch(2);
boost::latch start_latch(2), end_latch(2);
auto v1 = make_random_values(1024 * 16, [&] { return gen(rg); });
auto v2 = v1;
+3 -2
View File
@@ -2,10 +2,11 @@
// 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 "latch.hpp"
#include "../helpers/generators.hpp"
#include "../helpers/test.hpp"
#include <boost/compat/latch.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/core/span.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
@@ -369,7 +370,7 @@ std::vector<boost::span<T> > split(
template <class T, class F> void thread_runner(std::vector<T>& values, F f)
{
boost::compat::latch latch(static_cast<std::ptrdiff_t>(num_threads));
boost::latch latch(static_cast<std::ptrdiff_t>(num_threads));
std::vector<std::thread> threads;
auto subslices = split<T>(values, num_threads);
+3 -2
View File
@@ -5,10 +5,11 @@
#ifndef BOOST_UNORDERED_TEST_CFOA_HELPERS_HPP
#define BOOST_UNORDERED_TEST_CFOA_HELPERS_HPP
#include "latch.hpp"
#include "../helpers/generators.hpp"
#include "../helpers/test.hpp"
#include <boost/compat/latch.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/core/span.hpp>
#include <boost/unordered/unordered_flat_map.hpp>
@@ -338,7 +339,7 @@ std::vector<boost::span<T> > split(
template <class T, class F> void thread_runner(std::vector<T>& values, F f)
{
boost::compat::latch latch(static_cast<std::ptrdiff_t>(num_threads));
boost::latch latch(static_cast<std::ptrdiff_t>(num_threads));
std::vector<std::thread> threads;
auto subslices = split<T>(values, num_threads);
+87
View File
@@ -0,0 +1,87 @@
// Copyright (C) 2023 Christian Mazakas
// 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)
#ifndef BOOST_UNORDERED_TEST_CFOA_LATCH_HPP
#define BOOST_UNORDERED_TEST_CFOA_LATCH_HPP
#include <boost/assert.hpp>
#include <climits>
#include <condition_variable>
#include <cstddef>
#include <mutex>
namespace boost {
class latch
{
private:
std::ptrdiff_t n_;
mutable std::mutex m_;
mutable std::condition_variable cv_;
public:
explicit latch(std::ptrdiff_t expected) : n_{expected}, m_{}, cv_{}
{
BOOST_ASSERT(n_ >= 0);
BOOST_ASSERT(n_ <= max());
}
latch(latch const&) = delete;
latch& operator=(latch const&) = delete;
~latch() = default;
void count_down(std::ptrdiff_t n = 1)
{
std::unique_lock<std::mutex> lk(m_);
count_down_and_notify(lk, n);
}
bool try_wait() const noexcept
{
std::unique_lock<std::mutex> lk(m_);
return is_ready();
}
void wait() const
{
std::unique_lock<std::mutex> lk(m_);
wait_impl(lk);
}
void arrive_and_wait(std::ptrdiff_t n = 1)
{
std::unique_lock<std::mutex> lk(m_);
bool should_wait = count_down_and_notify(lk, n);
if (should_wait) {
wait_impl(lk);
}
}
static constexpr std::ptrdiff_t max() noexcept { return INT_MAX; }
private:
bool is_ready() const { return n_ == 0; }
bool count_down_and_notify(
std::unique_lock<std::mutex>& lk, std::ptrdiff_t n)
{
n_ -= n;
if (n_ == 0) {
lk.unlock();
cv_.notify_all();
return false;
}
return true;
}
void wait_impl(std::unique_lock<std::mutex>& lk) const
{
cv_.wait(lk, [this] { return this->is_ready(); });
}
};
} // namespace boost
#endif // BOOST_UNORDERED_TEST_CFOA_LATCH_HPP
+155
View File
@@ -0,0 +1,155 @@
// Copyright (C) 2023 Christian Mazakas
// 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)
#define BOOST_ENABLE_ASSERT_HANDLER
#include "latch.hpp"
#include <boost/core/lightweight_test.hpp>
#include <thread>
#include <vector>
struct exception
{
};
namespace boost {
void assertion_failed(
char const* expr, char const* function, char const* file, long line)
{
(void)expr;
(void)function;
(void)file;
(void)line;
throw exception{};
}
} // namespace boost
namespace {
void test_max() { BOOST_TEST_EQ(boost::latch::max(), INT_MAX); }
void test_constructor()
{
{
auto const f = [] {
boost::latch l(-1);
(void)l;
};
BOOST_TEST_THROWS(f(), exception);
}
{
std::ptrdiff_t n = 0;
boost::latch l(n);
BOOST_TEST(l.try_wait());
}
{
std::ptrdiff_t n = 16;
boost::latch l(n);
BOOST_TEST_NOT(l.try_wait());
l.count_down(16);
BOOST_TEST(l.try_wait());
}
#if PTRDIFF_MAX > INT_MAX
{
auto const f = [] {
std::ptrdiff_t n = INT_MAX;
n += 10;
boost::latch l(n);
(void)l;
};
BOOST_TEST_THROWS(f(), exception);
}
#endif
}
void test_count_down_and_wait()
{
constexpr std::ptrdiff_t n = 1024;
boost::latch l(2 * n);
bool bs[] = {false, false};
std::thread t1([&] {
l.wait();
BOOST_TEST(bs[0]);
BOOST_TEST(bs[1]);
});
std::thread t2([&] {
for (int i = 0; i < n; ++i) {
if (i == (n - 1)) {
bs[0] = true;
} else {
BOOST_TEST_NOT(l.try_wait());
}
l.count_down(1);
}
});
for (int i = 0; i < n; ++i) {
if (i == (n - 1)) {
bs[1] = true;
} else {
BOOST_TEST_NOT(l.try_wait());
}
l.count_down(1);
}
t1.join();
t2.join();
BOOST_TEST(l.try_wait());
}
void test_arrive_and_wait()
{
std::ptrdiff_t const n = 16;
boost::latch l(2 * n);
int xs[n] = {0};
std::vector<std::thread> threads;
for (int i = 0; i < n; ++i) {
threads.emplace_back([&l, &xs, i, n] {
(void)n;
for (int j = 0; j < n; ++j) {
BOOST_TEST_EQ(xs[j], 0);
}
l.arrive_and_wait(2);
xs[i] = 1;
});
}
for (auto& t : threads) {
t.join();
}
for (int i = 0; i < n; ++i) {
BOOST_TEST_EQ(xs[i], 1);
}
}
} // namespace
int main()
{
test_max();
test_constructor();
test_count_down_and_wait();
test_arrive_and_wait();
return boost::report_errors();
}
+1 -1
View File
@@ -103,7 +103,7 @@ namespace {
map2_type x2(2 * vals1.size(), allocator_type(3));
std::thread t1, t2, t3;
boost::compat::latch l(2);
boost::latch l(2);
std::mutex m;
std::condition_variable cv;
-79
View File
@@ -1,79 +0,0 @@
// Copyright 2023 Joaquin M Lopez Munoz
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <cstdlib>
#define BOOST_ENABLE_ASSERT_HANDLER
static bool reentrancy_detected = false;
namespace boost {
// Caveat lector: a proper handler shouldn't throw as it may be executed
// within a noexcept function.
void assertion_failed_msg(
char const*, char const*, char const*, char const*, long)
{
reentrancy_detected = true;
throw 0;
}
void assertion_failed(char const*, char const*, char const*, long) // LCOV_EXCL_START
{
std::abort();
} // LCOV_EXCL_STOP
}
#include <boost/unordered/concurrent_flat_map.hpp>
#include <boost/core/lightweight_test.hpp>
template<typename F>
void detect_reentrancy(F f)
{
reentrancy_detected = false;
try {
f();
}
catch(int) {}
BOOST_TEST(reentrancy_detected);
}
int main()
{
using map = boost::concurrent_flat_map<int, int>;
using value_type = typename map::value_type;
map m1, m2;
m1.emplace(0, 0);
m2.emplace(1, 0);
detect_reentrancy([&] {
m1.visit_all([&](value_type&) { (void)m1.contains(0); });
}); // LCOV_EXCL_LINE
detect_reentrancy([&] {
m1.visit_all([&](value_type&) { m1.rehash(0); });
}); // LCOV_EXCL_LINE
detect_reentrancy([&] {
m1.visit_all([&](value_type&) {
m2.visit_all([&](value_type&) {
m1=m2;
}); // LCOV_EXCL_START
});
});
// LCOV_EXCL_STOP
detect_reentrancy([&] {
m1.visit_all([&](value_type&) {
m2.visit_all([&](value_type&) {
m2=m1;
}); // LCOV_EXCL_START
});
});
// LCOV_EXCL_STOP
return boost::report_errors();
}
+1 -1
View File
@@ -79,7 +79,7 @@ namespace {
map_type x(0, hasher(1), key_equal(2), allocator_type(3));
std::thread t1, t2, t3;
boost::compat::latch l(2);
boost::latch l(2);
std::mutex m;
std::condition_variable cv;
-26
View File
@@ -1,26 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <mutex>
using boost::unordered::detail::foa::rw_spinlock;
// Sanity check only
static rw_spinlock sp;
static rw_spinlock sp2;
int main()
{
sp.lock();
sp2.lock();
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock( sp );
std::lock_guard<rw_spinlock> lock2( sp2 );
}
}
-41
View File
@@ -1,41 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
using boost::unordered::detail::foa::rw_spinlock;
static rw_spinlock sp;
static rw_spinlock sp2;
int main()
{
BOOST_TEST( sp.try_lock() );
BOOST_TEST( !sp.try_lock() );
BOOST_TEST( sp2.try_lock() );
BOOST_TEST( !sp.try_lock() );
BOOST_TEST( !sp2.try_lock() );
sp.unlock();
sp2.unlock();
sp.lock();
BOOST_TEST( !sp.try_lock() );
sp2.lock();
BOOST_TEST( !sp.try_lock() );
BOOST_TEST( !sp2.try_lock() );
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock( sp );
BOOST_TEST( !sp.try_lock() );
std::lock_guard<rw_spinlock> lock2( sp2 );
BOOST_TEST( !sp.try_lock() );
BOOST_TEST( !sp2.try_lock() );
}
return boost::report_errors();
}
-49
View File
@@ -1,49 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
#include <thread>
#include <cstdio>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
static rw_spinlock sp;
void f( int k, int n )
{
std::printf( "Thread %d started.\n", k );
for( int i = 0; i < n; ++i )
{
std::lock_guard<rw_spinlock> lock( sp );
++count;
}
std::printf( "Thread %d finished.\n", k );
}
int main()
{
int const N = 1000000; // iterations
int const M = 8; // threads
std::thread th[ M ];
for( int i = 0; i < M; ++i )
{
th[ i ] = std::thread( f, i, N );
}
for( int i = 0; i < M; ++i )
{
th[ i ].join();
}
BOOST_TEST_EQ( count, N * M );
return boost::report_errors();
}
-29
View File
@@ -1,29 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <mutex>
using boost::unordered::detail::foa::rw_spinlock;
static rw_spinlock sp;
static rw_spinlock sp2;
int main()
{
sp.lock();
sp2.lock_shared();
sp2.lock_shared();
sp.unlock();
sp2.unlock_shared();
sp2.unlock_shared();
{
std::lock_guard<rw_spinlock> lock( sp );
boost::compat::shared_lock<rw_spinlock> lock2( sp2 );
boost::compat::shared_lock<rw_spinlock> lock3( sp2 );
}
}
-42
View File
@@ -1,42 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
using boost::unordered::detail::foa::rw_spinlock;
static rw_spinlock sp;
int main()
{
{
BOOST_TEST( sp.try_lock_shared() );
BOOST_TEST( sp.try_lock_shared() );
sp.unlock_shared();
sp.unlock_shared();
}
{
BOOST_TEST( sp.try_lock() );
BOOST_TEST( !sp.try_lock_shared() );
sp.unlock();
}
{
std::lock_guard<rw_spinlock> lock( sp );
BOOST_TEST( !sp.try_lock_shared() );
}
{
boost::compat::shared_lock<rw_spinlock> lock( sp );
BOOST_TEST( !sp.try_lock() );
BOOST_TEST( sp.try_lock_shared() );
sp.unlock_shared();
}
return boost::report_errors();
}
-60
View File
@@ -1,60 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
#include <thread>
#include <cstdio>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
static rw_spinlock sp;
void f( int k, int n )
{
std::printf( "Thread %d started.\n", k );
int i = 0;
for( ;; ++i )
{
{
boost::compat::shared_lock<rw_spinlock> lock( sp );
if( count >= n ) break;
}
{
std::lock_guard<rw_spinlock> lock( sp );
if( count >= n ) break;
++count;
}
}
std::printf( "Thread %d finished (%i iterations).\n", k, i );
}
int main()
{
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[ M ];
for( int i = 0; i < M; ++i )
{
th[ i ] = std::thread( f, i, N );
}
for( int i = 0; i < M; ++i )
{
th[ i ].join();
}
BOOST_TEST_EQ( count, N );
return boost::report_errors();
}
-62
View File
@@ -1,62 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
#include <thread>
#include <cstdio>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
static rw_spinlock sp;
void f( int k, int n )
{
std::printf( "Thread %d started.\n", k );
int i = 0;
for( ;; ++i )
{
int oldc;
{
boost::compat::shared_lock<rw_spinlock> lock( sp );
if( count >= n ) break;
oldc = count;
}
{
std::lock_guard<rw_spinlock> lock( sp );
if( count == oldc ) ++count;
}
}
std::printf( "Thread %d finished (%i iterations).\n", k, i );
}
int main()
{
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[ M ];
for( int i = 0; i < M; ++i )
{
th[ i ] = std::thread( f, i, N );
}
for( int i = 0; i < M; ++i )
{
th[ i ].join();
}
BOOST_TEST_EQ( count, N );
return boost::report_errors();
}
-64
View File
@@ -1,64 +0,0 @@
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <boost/core/lightweight_test.hpp>
#include <mutex>
#include <thread>
#include <cstdio>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
static rw_spinlock sp;
void f( int k, int m, int n )
{
std::printf( "Thread %d of %d started.\n", k, m );
for( int i = 0; i < n; ++i )
{
int oldc;
for( ;; )
{
{
boost::compat::shared_lock<rw_spinlock> lock( sp );
oldc = count;
}
if( oldc % m == k ) break;
}
{
std::lock_guard<rw_spinlock> lock( sp );
if( count == oldc ) ++count;
}
}
std::printf( "Thread %d of %d finished.\n", k, m );
}
int main()
{
int const N = 100; // total iterations
int const M = 4; // threads
std::thread th[ M ];
for( int i = 0; i < M; ++i )
{
th[ i ] = std::thread( f, i, M, N );
}
for( int i = 0; i < M; ++i )
{
th[ i ].join();
}
BOOST_TEST_EQ( count, N * M );
return boost::report_errors();
}
+255
View File
@@ -0,0 +1,255 @@
// Copyright 2023 Peter Dimov
// Copyright 2023 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include "helpers.hpp"
#include <boost/unordered/detail/foa/rw_spinlock.hpp>
#include <boost/compat/shared_lock.hpp>
#include <mutex>
#include <thread>
using boost::unordered::detail::foa::rw_spinlock;
static int count = 0;
UNORDERED_AUTO_TEST (rw_spinlock_test) {
rw_spinlock sp, sp2;
sp.lock();
sp2.lock();
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock(sp);
std::lock_guard<rw_spinlock> lock2(sp2);
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test2) {
rw_spinlock sp, sp2;
BOOST_TEST(sp.try_lock());
BOOST_TEST(!sp.try_lock());
BOOST_TEST(sp2.try_lock());
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
sp.unlock();
sp2.unlock();
sp.lock();
BOOST_TEST(!sp.try_lock());
sp2.lock();
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
sp.unlock();
sp2.unlock();
{
std::lock_guard<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock());
std::lock_guard<rw_spinlock> lock2(sp2);
BOOST_TEST(!sp.try_lock());
BOOST_TEST(!sp2.try_lock());
}
}
void f(rw_spinlock& sp, int n)
{
for (int i = 0; i < n; ++i) {
std::lock_guard<rw_spinlock> lock(sp);
++count;
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test3) {
count = 0;
rw_spinlock sp;
int const N = 1000000; // iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
th[i] = std::thread([=, &sp] { f(sp, N); });
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N * M);
}
UNORDERED_AUTO_TEST (rw_spinlock_test4) {
rw_spinlock sp, sp2;
sp.lock();
sp2.lock_shared();
sp2.lock_shared();
sp.unlock();
sp2.unlock_shared();
sp2.unlock_shared();
{
std::lock_guard<rw_spinlock> lock(sp);
boost::compat::shared_lock<rw_spinlock> lock2(sp2);
boost::compat::shared_lock<rw_spinlock> lock3(sp2);
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test5) {
rw_spinlock sp;
{
BOOST_TEST(sp.try_lock_shared());
BOOST_TEST(sp.try_lock_shared());
sp.unlock_shared();
sp.unlock_shared();
}
{
BOOST_TEST(sp.try_lock());
BOOST_TEST(!sp.try_lock_shared());
sp.unlock();
}
{
std::lock_guard<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock_shared());
}
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
BOOST_TEST(!sp.try_lock());
BOOST_TEST(sp.try_lock_shared());
sp.unlock_shared();
}
}
UNORDERED_AUTO_TEST (rw_spinlock_test6) {
count = 0;
rw_spinlock sp;
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int n = N;
th[i] = std::thread([n, &sp] {
for (;;) {
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
if (count >= n)
break;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count >= n)
break;
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N);
}
UNORDERED_AUTO_TEST (rw_spinlock_test7) {
rw_spinlock sp;
int const N = 1000000; // total iterations
int const M = 8; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int n = N;
th[i] = std::thread([=, &sp] {
for (;;) {
int oldc;
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
if (count >= n)
break;
oldc = count;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count == oldc)
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N);
}
UNORDERED_AUTO_TEST (rw_spinlock_test8) {
count = 0;
rw_spinlock sp;
int const N = 1000; // total iterations
int const M = 4; // threads
std::thread th[M];
for (int i = 0; i < M; ++i) {
int k = i;
int m = M;
int n = N;
th[i] = std::thread([k, m, n, &sp] {
for (int j = 0; j < n; ++j) {
int oldc;
for (;;) {
{
boost::compat::shared_lock<rw_spinlock> lock(sp);
oldc = count;
}
if (oldc % m == k)
break;
}
{
std::lock_guard<rw_spinlock> lock(sp);
if (count == oldc)
++count;
}
}
});
}
for (int i = 0; i < M; ++i) {
th[i].join();
}
BOOST_TEST_EQ(count, N * M);
}
RUN_TESTS()
+1 -1
View File
@@ -190,7 +190,7 @@ namespace {
map_type x2(vals2.size(), hasher(2), key_equal(1), allocator_type(3));
std::thread t1, t2, t3;
boost::compat::latch l(2);
boost::latch l(2);
std::mutex m;
std::condition_variable cv;
+1 -1
View File
@@ -520,7 +520,7 @@ namespace {
X x;
std::thread t1, t2;
boost::compat::latch l(2);
boost::latch l(2);
std::vector<std::string> strs(values.size());
t1 = std::thread([&l, &values, &x, &strs] {