1
0
forked from boostorg/core

Compare commits

...

23 Commits

Author SHA1 Message Date
Andrey Semashev
7cbbb08e7b Use libstdc++11 for clang prior to 16.
Clang prior to version 16 does not support libstdc++13 that is installed
by default in GHA image ubuntu 22.04 in C++20 mode.
2023-11-25 16:04:12 +03:00
Peter Dimov
ba6360e8ed Update test/Jamfile 2023-10-06 11:30:51 +03:00
Peter Dimov
2a70a0f239 Update ci.yml 2023-10-06 11:20:05 +03:00
Peter Dimov
31a2f7fb6b Merge pull request #158 from iskunk/feature/fix-intel-build
Fix Intel compiler build
2023-10-06 04:21:16 +03:00
Daniel Richard G
0120dbfe65 Fix Intel compiler build 2023-10-05 20:26:24 -04:00
Andrey Semashev
5f6fe65eb2 Merge pull request #149 from boostorg/feature/invoke_swap
Rename `boost::swap` to `boost::core::invoke_swap`, deprecate `boost::swap`
2023-08-25 14:50:06 +03:00
Peter Dimov
c7134904e2 Android doesn't support pthread_setcancelstate. Fixes #150. 2023-07-25 18:03:51 +03:00
Andrey Semashev
9fc2a2f1ac Renamed boost::swap to boost::core::invoke_swap, deprecated boost::swap.
The rename allows to avoid forming an infinite recursion in compile time
(because of noexcept specification that needs to resolve the unqualified call
to swap) or run time (in case if the boost::swap function is the only one
suitable for the passed arguments).

To avoid the compile-time recursion, removed noexcept specification from
boost::swap. The specification is still present in boost::core::invoke_swap.

Deprecated boost::swap and associated headers. boost::core::invoke_swap
is defined in a new boost/core/invoke_swap.hpp header.

Updated docs and tests. Removed tests that check inclusion of deprecated
headers.

Fixes https://github.com/boostorg/core/issues/148.
2023-07-12 12:17:07 +03:00
Peter Dimov
216999e552 Avoid -Wsign-conversion warning in checked_delete.hpp 2023-06-25 13:46:53 +03:00
Peter Dimov
66890c3f3d Use SwitchToThread instead of Sleep(0) is sp_thread_yield; the general consensus is that it's newer and 'smarter' 2023-06-18 21:54:13 +03:00
Andrey Semashev
8d6d20059a Switch CI to clang-15 from stock Ubuntu repos. 2023-06-05 03:13:05 +03:00
Peter Dimov
ee596e3d37 Update documentation 2023-06-02 20:39:42 +03:00
Peter Dimov
de8fe4fad7 Fix libc++16 failures 2023-06-02 19:32:28 +03:00
Peter Dimov
d4db3eccec Add Clang 16 to CI 2023-06-02 18:07:06 +03:00
Peter Dimov
3b96d237c0 Update test/CMakeLists.txt 2023-06-02 04:32:42 +03:00
Peter Dimov
0e71b6158d Add noexcept to yield primitives 2023-06-02 04:27:12 +03:00
Peter Dimov
23ef6d3531 Disable cancelation around nanosleep in sp_thread_sleep 2023-06-02 03:57:38 +03:00
Peter Dimov
e088fb8929 Add yield_prim_pthread_cancel_test 2023-06-02 03:27:29 +03:00
Peter Dimov
57151ab82e Update sp_thread_pause.hpp 2023-06-02 02:05:36 +03:00
Peter Dimov
992326b1c8 Decrease loop count of sp_thread_sleep_test 2023-06-02 02:04:46 +03:00
Peter Dimov
4e769d1cdd Add boost/core/yield_primitives.hpp 2023-06-01 23:08:32 +03:00
Peter Dimov
bf17035a2d Disable bit_cast_test_cx when __builtin_bit_cast is not available 2023-06-01 03:20:22 +03:00
Peter Dimov
5a3b4df5de Use __builtin_bit_cast when available 2023-06-01 02:38:57 +03:00
55 changed files with 958 additions and 230 deletions

View File

@@ -334,6 +334,14 @@ local windows_pipeline(name, image, environment, arch = "amd64") =
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"],
),
linux_pipeline(
"Linux 22.04 Clang 16",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '03,11,14,17,20,2b' },
"clang-16",
["deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main"],
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '03,11,14,1z' } + ubsan,

View File

@@ -121,6 +121,13 @@ jobs:
os: ubuntu-22.04
install:
- g++-12-multilib
- toolset: gcc-13
cxxstd: "03,11,14,17,20,23"
address-model: 32,64
os: ubuntu-latest
container: ubuntu:23.04
install:
- g++-13-multilib
- name: UBSAN
toolset: gcc-12
cxxstd: "03,11,14,17,20,23"
@@ -221,34 +228,40 @@ jobs:
os: ubuntu-22.04
install:
- clang-11
- g++-11
gcc_toolchain: 11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install:
- clang-12
- g++-11
gcc_toolchain: 11
- toolset: clang
compiler: clang++-13
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install:
- clang-13
- g++-11
gcc_toolchain: 11
- toolset: clang
compiler: clang++-14
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install:
- clang-14
- g++-11
gcc_toolchain: 11
- toolset: clang
compiler: clang++-15
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install:
- clang-15
sources:
- "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"
source_keys:
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
- g++-11
gcc_toolchain: 11
- toolset: clang
compiler: clang++-15
cxxstd: "03,11,14,17,20,2b"
@@ -257,31 +270,55 @@ jobs:
- clang-15
- libc++-15-dev
- libc++abi-15-dev
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
- toolset: clang
compiler: clang++-16
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-latest
container: ubuntu:23.04
install:
- clang-16
- libc++-16-dev
- libc++abi-16-dev
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
- toolset: clang
compiler: clang++-17
cxxstd: "03,11,14,17,20,2b"
os: ubuntu-22.04
install:
- clang-17
- libc++-17-dev
- libc++abi-17-dev
sources:
- "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-15 main"
- "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-17 main"
source_keys:
- "https://apt.llvm.org/llvm-snapshot.gpg.key"
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
- name: UBSAN
toolset: clang
compiler: clang++-14
compiler: clang++-15
cxxstd: "03,11,14,17,20,2b"
cxxflags: -stdlib=libc++
linkflags: -stdlib=libc++
ubsan: 1
os: ubuntu-22.04
install:
- clang-14
- libc++-14-dev
- libc++abi-14-dev
- clang-15
- libc++-15-dev
- libc++abi-15-dev
- toolset: clang
cxxstd: "03,11,14,17,2a"
os: macos-11
- toolset: clang
cxxstd: "03,11,14,17,2a"
cxxstd: "03,11,14,17,20,2b"
os: macos-12
- toolset: clang
cxxstd: "03,11,14,17,20,2b"
os: macos-13
timeout-minutes: 120
runs-on: ${{matrix.os}}
@@ -551,6 +588,7 @@ jobs:
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}
@@ -598,6 +636,7 @@ jobs:
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}
@@ -655,6 +694,7 @@ jobs:
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}

View File

@@ -1,12 +1,29 @@
[/
Copyright 2021 Peter Dimov
Copyright 2022 Andrey Semashev
Copyright 2022-2023 Andrey Semashev
Distributed under the Boost Software License, Version 1.0.
https://boost.org/LICENSE_1_0.txt)
]
[section Revision History]
[section Changes in 1.84.0]
* `boost::swap` utility function has been renamed to `boost::core::invoke_swap` to
avoid forming a potential infinite recursion when the arguments are not swappable.
The new function is defined in `boost/core/invoke_swap.hpp` and is functionally equivalent
to `boost::swap`. The old `boost::swap` name is preserved for backward compatibility
but deprecated and will be removed in a future release. Its `noexcept` specification
has been removed to avoid compile errors caused by compile-time recursion.
`BOOST_ALLOW_DEPRECATED_SYMBOLS` or `BOOST_ALLOW_DEPRECATED` can be defined to suppress
deprecation warnings for the transition period. ([@https://github.com/boostorg/core/issues/148 #148])
* Headers `boost/swap.hpp`, `boost/utility/swap.hpp` and `boost/core/swap.hpp` are
deprecated and will be removed. Please, switch to `boost/core/invoke_swap.hpp`.
`BOOST_ALLOW_DEPRECATED_HEADERS` or `BOOST_ALLOW_DEPRECATED` can be defined to suppress
deprecation warnings.
[endsect]
[section Changes in 1.83.0]
* Added support for incomplete types to [link core.type_name `boost::core::type_name`].
@@ -14,6 +31,8 @@
`constexpr` on recent MSVC versions (VS2019 update 5 and later.)
* Added `boost::core::byteswap` (an implementation of `std::byteswap` from
C++23) to [link core.bit `boost/core/bit.hpp`].
* Moved the yield primitives `sp_thread_pause`, `sp_thread_yield`, `sp_thread_sleep`
from SmartPtr implementation details to `boost/core/yield_primitives.hpp`.
[endsect]

View File

@@ -83,3 +83,4 @@ criteria for inclusion is that the utility component be:
[include uncaught_exceptions.qbk]
[include use_default.qbk]
[include verbose_terminate_handler.qbk]
[include yield_primitives.qbk]

View File

@@ -20,17 +20,17 @@
[endsimplesect]
[section Header <boost/core/swap.hpp>]
[section Header <boost/core/invoke_swap.hpp>]
[^template<class T> void swap(T& left, T& right) noexcept(['see below]);]
[^template<class T> void invoke_swap(T& left, T& right) noexcept(['see below]);]
[endsect]
[section Introduction]
The template function `boost::swap` allows the values of two
variables to be swapped, using argument dependent lookup to
select a specialized swap function if available. If no
The template function `boost::core::invoke_swap` allows the
values of two variables to be swapped, using argument dependent
lookup to select a specialized swap function if available. If no
specialized swap function is available, `std::swap` is used.
[endsect]
@@ -56,9 +56,9 @@ Although this is legal C++, no Boost libraries use this method,
whereas many Boost libraries provide specialized swap functions
in their own namespaces.
`boost::swap` also supports swapping built-in arrays. Note that
`std::swap` originally did not do so, but a request to add an
overload of `std::swap` for built-in arrays has been accepted
`boost::core::invoke_swap` also supports swapping built-in arrays.
Note that `std::swap` originally did not do so, but a request to
add an overload of `std::swap` for built-in arrays has been accepted
by the C++ Standards Committee[footnote
[@http://open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#809
LWG Defect Report 809: std::swap should be overloaded for array
@@ -68,14 +68,15 @@ by the C++ Standards Committee[footnote
[section Exception Safety]
`boost::swap` provides the same exception guarantee as the
underlying swap function used, with one exception; for an array
`boost::core::invoke_swap` provides the same exception guarantee as
the underlying swap function used, with one exception; for an array
of type `T[n]`, where `n > 1` and the underlying swap function
for `T` provides the strong exception guarantee, `boost::swap`
provides only the basic exception guarantee.
for `T` provides the strong exception guarantee,
`boost::core::invoke_swap` provides only the basic exception guarantee.
In C++11 and later, `boost::swap` propagates the same `noexcept`
specification as the one specified in the underlying swap function.
In C++11 and later, `boost::core::invoke_swap` propagates the same
`noexcept` specification as the one specified in the underlying swap
function.
[endsect]
@@ -104,7 +105,7 @@ Or:
[section Portability]
Several older compilers do not support argument dependent
lookup. On these compilers `boost::swap` will call
lookup. On these compilers `boost::core::invoke_swap` will call
`std::swap`, ignoring any specialized swap functions that
could be found as a result of argument dependent lookup.
@@ -118,7 +119,9 @@ could be found as a result of argument dependent lookup.
tests, and documentation
* *Steven Watanabe* - for the idea to make `boost::swap` less
specialized than `std::swap`, thereby allowing the function
to have the name 'swap' without introducing ambiguity
to have the name 'swap' without introducing ambiguity. However,
later the function was renamed to `boost::core::invoke_swap`
to avoid potential infinite recursion.
[endsect]

79
doc/yield_primitives.qbk Normal file
View File

@@ -0,0 +1,79 @@
[/
Copyright 2023 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
https://boost.org/LICENSE_1_0.txt
]
[section:yield_primitives Yield Primitives]
[simplesect Authors]
* Peter Dimov
[endsimplesect]
[section Header <boost/core/yield_primitives.hpp>]
The header `<boost/core/yield_primitives.hpp>` implements a
collection of primitives that allow the current thread to
yield the CPU in various ways.
Very low level, specialized functionality, generally only useful for
implementing spinlocks. Normal synchronization primitives should
almost always be preferable in application code.
[section Synopsis]
``
namespace boost
{
namespace core
{
void sp_thread_pause() noexcept;
void sp_thread_yield() noexcept;
void sp_thread_sleep() noexcept;
} // namespace core
} // namespace boost
``
[endsect]
[section sp_thread_pause]
`void sp_thread_pause() noexcept;`
Emits a PAUSE instruction (on x86) or a YIELD instruction (on ARM).
A portable equivalent of the GCC builtin function `__builtin_ia32_pause`.
[endsect]
[section sp_thread_yield]
`void sp_thread_yield() noexcept;`
Informs the scheduler that the current thread wishes to relinquish
the rest of its timeslice.
A portable equivalent of POSIX `sched_yield`.
[endsect]
[section sp_thread_sleep]
`void sp_thread_sleep() noexcept;`
Sleeps for a short period, as if by calling POSIX `nanosleep` with
a small, implementation-dependent, interval (usually one microsecond).
A more forcing yield primitive than `sp_thread_yield`, because it's
generally not ignored even if all other waiting threads are of lower
priority.
[endsect]
[endsect]
[endsect]

View File

@@ -43,6 +43,16 @@
# define BOOST_CORE_HAS_BUILTIN_ISCONSTEVAL
#endif
#if defined(__has_builtin)
# if __has_builtin(__builtin_bit_cast)
# define BOOST_CORE_HAS_BUILTIN_BIT_CAST
# endif
#endif
#if defined(BOOST_MSVC) && BOOST_MSVC >= 1926
# define BOOST_CORE_HAS_BUILTIN_BIT_CAST
#endif
namespace boost
{
namespace core
@@ -50,6 +60,16 @@ namespace core
// bit_cast
#if defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST)
template<class To, class From>
BOOST_CONSTEXPR To bit_cast( From const & from ) BOOST_NOEXCEPT
{
return __builtin_bit_cast( To, from );
}
#else
template<class To, class From>
To bit_cast( From const & from ) BOOST_NOEXCEPT
{
@@ -60,6 +80,8 @@ To bit_cast( From const & from ) BOOST_NOEXCEPT
return to;
}
#endif
// countl
#if defined(__GNUC__) || defined(__clang__)

View File

@@ -30,16 +30,33 @@ namespace boost
template<class T> inline void checked_delete(T * x) BOOST_NOEXCEPT
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410L
static_assert( sizeof(T) != 0, "Type must be complete" );
#else
typedef char type_must_be_complete[ sizeof(T) ];
(void) sizeof(type_must_be_complete);
#endif
delete x;
}
template<class T> inline void checked_array_delete(T * x) BOOST_NOEXCEPT
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
#if defined(__cpp_static_assert) && __cpp_static_assert >= 200410L
static_assert( sizeof(T) != 0, "Type must be complete" );
#else
typedef char type_must_be_complete[ sizeof(T) ];
(void) sizeof(type_must_be_complete);
#endif
delete [] x;
}

View File

@@ -0,0 +1,71 @@
#ifndef BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED
#define BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/core/detail/sp_thread_pause.hpp
//
// inline void bost::core::sp_thread_pause();
//
// Emits a "pause" instruction.
//
// Copyright 2008, 2020, 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#if defined(__has_builtin)
# if __has_builtin(__builtin_ia32_pause) && !defined(__INTEL_COMPILER)
# define BOOST_CORE_HAS_BUILTIN_IA32_PAUSE
# endif
#endif
#if defined(BOOST_CORE_HAS_BUILTIN_IA32_PAUSE)
# define BOOST_CORE_SP_PAUSE() __builtin_ia32_pause()
#elif defined(_MSC_VER) && ( defined(_M_IX86) || defined(_M_X64) )
# include <intrin.h>
# define BOOST_CORE_SP_PAUSE() _mm_pause()
#elif defined(_MSC_VER) && ( defined(_M_ARM) || defined(_M_ARM64) )
# include <intrin.h>
# define BOOST_CORE_SP_PAUSE() __yield()
#elif defined(__GNUC__) && ( defined(__i386__) || defined(__x86_64__) )
# define BOOST_CORE_SP_PAUSE() __asm__ __volatile__( "rep; nop" : : : "memory" )
#elif defined(__GNUC__) && ( (defined(__ARM_ARCH) && __ARM_ARCH >= 8) || defined(__ARM_ARCH_8A__) || defined(__aarch64__) )
# define BOOST_CORE_SP_PAUSE() __asm__ __volatile__( "yield" : : : "memory" )
#else
# define BOOST_CORE_SP_PAUSE() ((void)0)
#endif
namespace boost
{
namespace core
{
BOOST_FORCEINLINE void sp_thread_pause() BOOST_NOEXCEPT
{
BOOST_CORE_SP_PAUSE();
}
} // namespace core
} // namespace boost
#undef BOOST_CORE_SP_PAUSE
#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_PAUSE_HPP_INCLUDED

View File

@@ -0,0 +1,122 @@
#ifndef BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED
#define BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/core/detail/sp_thread_sleep.hpp
//
// inline void bost::core::sp_thread_sleep();
//
// Cease execution for a while to yield to other threads,
// as if by calling nanosleep() with an appropriate interval.
//
// Copyright 2008, 2020, 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using Sleep(1) in sp_thread_sleep")
#endif
#include <boost/core/detail/sp_win32_sleep.hpp>
namespace boost
{
namespace core
{
namespace detail
{
inline void sp_thread_sleep() BOOST_NOEXCEPT
{
Sleep( 1 );
}
} // namespace detail
using boost::core::detail::sp_thread_sleep;
} // namespace core
} // namespace boost
#elif defined(BOOST_HAS_NANOSLEEP)
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using nanosleep() in sp_thread_sleep")
#endif
#include <time.h>
#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__)
# include <pthread.h>
#endif
namespace boost
{
namespace core
{
inline void sp_thread_sleep() BOOST_NOEXCEPT
{
#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__)
int oldst;
pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldst );
#endif
// g++ -Wextra warns on {} or {0}
struct timespec rqtp = { 0, 0 };
// POSIX says that timespec has tv_sec and tv_nsec
// But it doesn't guarantee order or placement
rqtp.tv_sec = 0;
rqtp.tv_nsec = 1000;
nanosleep( &rqtp, 0 );
#if defined(BOOST_HAS_PTHREADS) && !defined(__ANDROID__)
pthread_setcancelstate( oldst, &oldst );
#endif
}
} // namespace core
} // namespace boost
#else
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sp_thread_yield() in sp_thread_sleep")
#endif
#include <boost/core/detail/sp_thread_yield.hpp>
namespace boost
{
namespace core
{
inline void sp_thread_sleep() BOOST_NOEXCEPT
{
sp_thread_yield();
}
} // namespace core
} // namespace boost
#endif
#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_SLEEP_HPP_INCLUDED

View File

@@ -0,0 +1,100 @@
#ifndef BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED
#define BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/core/detail/sp_thread_yield.hpp
//
// inline void bost::core::sp_thread_yield();
//
// Gives up the remainder of the time slice,
// as if by calling sched_yield().
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( __CYGWIN__ )
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using SwitchToThread() in sp_thread_yield")
#endif
#include <boost/core/detail/sp_win32_sleep.hpp>
namespace boost
{
namespace core
{
namespace detail
{
inline void sp_thread_yield() BOOST_NOEXCEPT
{
SwitchToThread();
}
} // namespace detail
using boost::core::detail::sp_thread_yield;
} // namespace core
} // namespace boost
#elif defined(BOOST_HAS_SCHED_YIELD)
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sched_yield() in sp_thread_yield")
#endif
#ifndef _AIX
# include <sched.h>
#else
// AIX's sched.h defines ::var which sometimes conflicts with Lambda's var
extern "C" int sched_yield(void);
#endif
namespace boost
{
namespace core
{
inline void sp_thread_yield() BOOST_NOEXCEPT
{
sched_yield();
}
} // namespace core
} // namespace boost
#else
#if defined(BOOST_SP_REPORT_IMPLEMENTATION)
BOOST_PRAGMA_MESSAGE("Using sp_thread_pause() in sp_thread_yield")
#endif
#include <boost/core/detail/sp_thread_pause.hpp>
namespace boost
{
namespace core
{
inline void sp_thread_yield() BOOST_NOEXCEPT
{
sp_thread_pause();
}
} // namespace core
} // namespace boost
#endif
#endif // #ifndef BOOST_CORE_DETAIL_SP_THREAD_YIELD_HPP_INCLUDED

View File

@@ -0,0 +1,54 @@
#ifndef BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED
#define BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
// boost/core/detail/sp_win32_sleep.hpp
//
// Declares the Win32 Sleep() function.
//
// Copyright 2008, 2020 Peter Dimov
// Distributed under the Boost Software License, Version 1.0
// https://www.boost.org/LICENSE_1_0.txt
#if defined( BOOST_USE_WINDOWS_H )
# include <windows.h>
#endif
namespace boost
{
namespace core
{
namespace detail
{
#if !defined( BOOST_USE_WINDOWS_H )
#if defined(__clang__) && defined(__x86_64__)
// clang x64 warns that __stdcall is ignored
# define BOOST_CORE_SP_STDCALL
#else
# define BOOST_CORE_SP_STDCALL __stdcall
#endif
#if defined(__LP64__) // Cygwin 64
extern "C" __declspec(dllimport) void BOOST_CORE_SP_STDCALL Sleep( unsigned int ms );
#else
extern "C" __declspec(dllimport) void BOOST_CORE_SP_STDCALL Sleep( unsigned long ms );
#endif
extern "C" __declspec(dllimport) int BOOST_CORE_SP_STDCALL SwitchToThread();
#undef BOOST_CORE_SP_STDCALL
#endif // !defined( BOOST_USE_WINDOWS_H )
} // namespace detail
} // namespace core
} // namespace boost
#endif // #ifndef BOOST_CORE_DETAIL_SP_WIN32_SLEEP_HPP_INCLUDED

View File

@@ -0,0 +1,93 @@
// Copyright (C) 2007, 2008 Steven Watanabe, Joseph Gauterin, Niels Dekker
// Copyright (C) 2023 Andrey Semashev
//
// 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)
// For more information, see http://www.boost.org
#ifndef BOOST_CORE_INVOKE_SWAP_HPP
#define BOOST_CORE_INVOKE_SWAP_HPP
// Note: the implementation of this utility contains various workarounds:
// - invoke_swap_impl is put outside the boost namespace, to avoid infinite
// recursion (causing stack overflow) when swapping objects of a primitive
// type.
// - std::swap is imported with a using-directive, rather than
// a using-declaration, because some compilers (including MSVC 7.1,
// Borland 5.9.3, and Intel 8.1) don't do argument-dependent lookup
// when it has a using-declaration instead.
// - The main entry function is called invoke_swap rather than swap
// to avoid forming an infinite recursion when the arguments are not
// swappable.
#include <boost/core/enable_if.hpp>
#include <boost/config.hpp>
#if __cplusplus >= 201103L || defined(BOOST_DINKUMWARE_STDLIB)
#include <utility> // for std::swap (C++11)
#else
#include <algorithm> // for std::swap (C++98)
#endif
#include <cstddef> // for std::size_t
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_GCC) && (BOOST_GCC < 40700)
// gcc 4.6 ICEs on noexcept specifications below
#define BOOST_CORE_SWAP_NOEXCEPT_IF(x)
#else
#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
#endif
namespace boost_swap_impl {
// we can't use type_traits here
template<class T> struct is_const { enum _vt { value = 0 }; };
template<class T> struct is_const<T const> { enum _vt { value = 1 }; };
// Use std::swap if argument dependent lookup fails.
// We need to have this at namespace scope to be able to use unqualified swap() call
// in noexcept specification.
using namespace std;
template<class T>
BOOST_GPU_ENABLED
inline void invoke_swap_impl(T& left, T& right) BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(swap(left, right)))
{
swap(left, right);
}
template<class T, std::size_t N>
BOOST_GPU_ENABLED
inline void invoke_swap_impl(T (& left)[N], T (& right)[N])
BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::invoke_swap_impl(left[0], right[0])))
{
for (std::size_t i = 0; i < N; ++i)
{
::boost_swap_impl::invoke_swap_impl(left[i], right[i]);
}
}
} // namespace boost_swap_impl
namespace boost {
namespace core {
template<class T>
BOOST_GPU_ENABLED
inline typename enable_if_c< !::boost_swap_impl::is_const<T>::value >::type
invoke_swap(T& left, T& right)
BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::invoke_swap_impl(left, right)))
{
::boost_swap_impl::invoke_swap_impl(left, right);
}
} // namespace core
} // namespace boost
#undef BOOST_CORE_SWAP_NOEXCEPT_IF
#endif // BOOST_CORE_INVOKE_SWAP_HPP

View File

@@ -10,80 +10,31 @@
#define BOOST_CORE_SWAP_HPP
// Note: the implementation of this utility contains various workarounds:
// - swap_impl is put outside the boost namespace, to avoid infinite
// recursion (causing stack overflow) when swapping objects of a primitive
// type.
// - std::swap is imported with a using-directive, rather than
// a using-declaration, because some compilers (including MSVC 7.1,
// Borland 5.9.3, and Intel 8.1) don't do argument-dependent lookup
// when it has a using-declaration instead.
// - boost::swap has two template arguments, instead of one, to
// avoid ambiguity when swapping objects of a Boost type that does
// not have its own boost::swap overload.
#include <boost/core/enable_if.hpp>
#include <boost/config.hpp>
#if __cplusplus >= 201103L || defined(BOOST_DINKUMWARE_STDLIB)
#include <utility> // for std::swap (C++11)
#else
#include <algorithm> // for std::swap (C++98)
#endif
#include <cstddef> // for std::size_t
#include <boost/config/header_deprecated.hpp>
#include <boost/core/invoke_swap.hpp>
#ifdef BOOST_HAS_PRAGMA_ONCE
#pragma once
#endif
#if defined(BOOST_GCC) && (BOOST_GCC < 40700)
// gcc 4.6 ICEs on noexcept specifications below
#define BOOST_CORE_SWAP_NOEXCEPT_IF(x)
#else
#define BOOST_CORE_SWAP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
#endif
namespace boost_swap_impl
{
// we can't use type_traits here
template<class T> struct is_const { enum _vt { value = 0 }; };
template<class T> struct is_const<T const> { enum _vt { value = 1 }; };
// Use std::swap if argument dependent lookup fails.
// We need to have this at namespace scope to be able to use unqualified swap() call
// in noexcept specification.
using namespace std;
template<class T>
BOOST_GPU_ENABLED
void swap_impl(T& left, T& right) BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(swap(left, right)))
{
swap(left, right);
}
template<class T, std::size_t N>
BOOST_GPU_ENABLED
void swap_impl(T (& left)[N], T (& right)[N])
BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left[0], right[0])))
{
for (std::size_t i = 0; i < N; ++i)
{
::boost_swap_impl::swap_impl(left[i], right[i]);
}
}
}
BOOST_HEADER_DEPRECATED("boost/core/invoke_swap.hpp")
namespace boost
{
template<class T1, class T2>
BOOST_GPU_ENABLED
typename enable_if_c< !boost_swap_impl::is_const<T1>::value && !boost_swap_impl::is_const<T2>::value >::type
BOOST_DEPRECATED("This function is deprecated, use boost::core::invoke_swap instead.")
inline typename enable_if_c< !boost_swap_impl::is_const<T1>::value && !boost_swap_impl::is_const<T2>::value >::type
swap(T1& left, T2& right)
BOOST_CORE_SWAP_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(::boost_swap_impl::swap_impl(left, right)))
{
::boost_swap_impl::swap_impl(left, right);
boost::core::invoke_swap(left, right);
}
}
#undef BOOST_CORE_SWAP_NOEXCEPT_IF
#endif // BOOST_CORE_SWAP_HPP

View File

@@ -0,0 +1,12 @@
#ifndef BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED
#define BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/detail/sp_thread_pause.hpp>
#include <boost/core/detail/sp_thread_yield.hpp>
#include <boost/core/detail/sp_thread_sleep.hpp>
#endif // #ifndef BOOST_CORE_YIELD_PRIMITIVES_HPP_INCLUDED

View File

@@ -10,8 +10,11 @@
#define BOOST_SWAP_HPP
// The header file at this path is deprecated;
// use boost/core/swap.hpp instead.
// use boost/core/invoke_swap.hpp instead.
#include <boost/config/header_deprecated.hpp>
#include <boost/core/swap.hpp>
BOOST_HEADER_DEPRECATED("boost/core/invoke_swap.hpp")
#endif

View File

@@ -10,8 +10,11 @@
#define BOOST_UTILITY_SWAP_HPP
// The header file at this path is deprecated;
// use boost/core/swap.hpp instead.
// use boost/core/invoke_swap.hpp instead.
#include <boost/config/header_deprecated.hpp>
#include <boost/core/swap.hpp>
BOOST_HEADER_DEPRECATED("boost/core/invoke_swap.hpp")
#endif

View File

@@ -38,6 +38,13 @@ boost_test(TYPE run SOURCES serialization_split_free_test.cpp)
boost_test(TYPE run SOURCES serialization_split_member_test.cpp)
boost_test(TYPE run SOURCES serialization_construct_data_test.cpp)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(BOOST_TEST_LINK_LIBRARIES Boost::core Threads::Threads)
boost_test(TYPE run SOURCES yield_prim_pthread_cancel_test.cpp)
endif()
add_subdirectory(swap)

View File

@@ -17,7 +17,7 @@ project : requirements
<toolset>gcc:<warnings-as-errors>on
<toolset>gcc-4.4:<cxxflags>-Wno-sign-compare ;
local warning-as-errors-off =
local warnings-as-errors-off =
"-<toolset>msvc:<warnings-as-errors>on"
"-<toolset>gcc:<warnings-as-errors>on"
"-<toolset>clang:<warnings-as-errors>on" ;
@@ -32,36 +32,36 @@ run addressof_np_test.cpp ;
run addressof_fn_test.cpp ;
compile addressof_constexpr_test.cpp ;
compile-fail addressof_fail_rvalue.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
run checked_delete_test.cpp ;
compile-fail checked_delete_fail.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail checked_delete_fail2.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile ref_ct_test.cpp ;
run ref_test.cpp ;
run ref_ref_test.cpp ;
run ref_fn_test.cpp ;
compile-fail ref_rv_fail1.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_rv_fail2.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_rv_fail3.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_rv_fail4.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_rv_fail5.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_implicit_fail.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_implicit_fail2.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_implicit_fail3.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail ref_implicit_fail4.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
run ref_cv_test.cpp ;
run ref_conversion_test.cpp ;
@@ -75,18 +75,18 @@ run eif_no_disambiguation.cpp : ;
run eif_partial_specializations.cpp : ;
compile-fail noncopyable_compile_fail.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
run explicit_operator_bool.cpp ;
run explicit_operator_bool_noexcept.cpp ;
compile-fail explicit_operator_bool_compile_fail_conv_int.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail explicit_operator_bool_compile_fail_conv_pvoid.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail explicit_operator_bool_compile_fail_delete.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail explicit_operator_bool_compile_fail_shift.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile ignore_unused_test.cpp ;
@@ -181,9 +181,9 @@ run demangled_name_test.cpp : : : <rtti>off <test-info>always_show_run_output :
run scoped_enum.cpp ;
compile-fail scoped_enum_compile_fail_conv_from_int.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
compile-fail scoped_enum_compile_fail_conv_to_int.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
run underlying_type.cpp ;
@@ -304,6 +304,7 @@ run bit_byteswap_test.cpp
compile-fail bit_width_fail.cpp
: <warnings>off ;
compile bit_cast_test_cx.cpp ;
compile bit_rotate_test_cx.cpp ;
compile bit_countr_test_cx.cpp ;
compile bit_countl_test_cx.cpp ;
@@ -348,7 +349,7 @@ run sv_common_reference_test.cpp ;
compile sv_common_reference_test2.cpp ;
compile sv_windows_h_test.cpp ;
compile-fail sv_nullptr_fail.cpp
: $(warning-as-errors-off) ;
: $(warnings-as-errors-off) ;
run span_test.cpp ;
run span_types_test.cpp ;
@@ -377,13 +378,21 @@ run memory_resource_test.cpp ;
run data_test.cpp ;
run size_test.cpp ;
run serialization_nvp_test.cpp : : : <library>/boost//serialization/<warnings>off <undefined-sanitizer>norecover:<build>no ;
run serialization_split_free_test.cpp : : : <library>/boost//serialization/<warnings>off <undefined-sanitizer>norecover:<link>static ;
run serialization_split_member_test.cpp : : : <library>/boost//serialization/<warnings>off <undefined-sanitizer>norecover:<link>static ;
run serialization_construct_data_test.cpp : : : <library>/boost//serialization/<warnings>off <undefined-sanitizer>norecover:<link>static ;
local with-serialization = <library>/boost//serialization/<warnings>off $(warnings-as-errors-off) <undefined-sanitizer>norecover:<link>static ;
run serialization_nvp_test.cpp : : : $(with-serialization) <undefined-sanitizer>norecover:<build>no ;
run serialization_split_free_test.cpp : : : $(with-serialization) ;
run serialization_split_member_test.cpp : : : $(with-serialization) ;
run serialization_construct_data_test.cpp : : : $(with-serialization) ;
run identity_test.cpp ;
run identity_rvalue_test.cpp ;
run sp_thread_pause_test.cpp ;
run sp_thread_yield_test.cpp ;
run sp_thread_sleep_test.cpp ;
run yield_prim_windows_h_test.cpp ;
run yield_prim_pthread_cancel_test.cpp : ;
use-project /boost/core/swap : ./swap ;
build-project ./swap ;

28
test/bit_cast_test_cx.cpp Normal file
View File

@@ -0,0 +1,28 @@
// constexpr test for boost/core/bit.hpp (bit_cast)
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/bit.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if defined(BOOST_NO_CXX11_CONSTEXPR)
BOOST_PRAGMA_MESSAGE( "Test skipped because BOOST_NO_CXX11_CONSTEXPR is defined" )
#elif !defined(BOOST_CORE_HAS_BUILTIN_BIT_CAST)
BOOST_PRAGMA_MESSAGE( "Test skipped because BOOST_CORE_HAS_BUILTIN_BIT_CAST is not defined" )
#else
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
STATIC_ASSERT( boost::core::bit_cast<boost::uint32_t>( 1.0f ) == 0x3F800000u );
STATIC_ASSERT( boost::core::bit_cast<boost::uint64_t>( 1.0 ) == 0x3FF0000000000000ull );
#endif

View File

@@ -0,0 +1,15 @@
// Test for sp_thread_pause
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/yield_primitives.hpp>
int main()
{
for( int i = 0; i < 1048576; ++i )
{
boost::core::sp_thread_pause();
}
}

View File

@@ -0,0 +1,15 @@
// Test for sp_thread_sleep
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/yield_primitives.hpp>
int main()
{
for( int i = 0; i < 100; ++i )
{
boost::core::sp_thread_sleep();
}
}

View File

@@ -0,0 +1,15 @@
// Test for sp_thread_yield
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/yield_primitives.hpp>
int main()
{
for( int i = 0; i < 10000; ++i )
{
boost::core::sp_thread_yield();
}
}

View File

@@ -7,10 +7,19 @@
#include <boost/core/lightweight_test_trait.hpp>
#include <iterator>
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 160000
// std::char_traits<Ch> is deprecated for non-char types
typedef wchar_t Ch;
#else
struct Ch
{
};
#endif
int main()
{
typedef boost::core::basic_string_view<Ch> ch_string_view;

View File

@@ -7,12 +7,8 @@
# bring in rules for testing
import testing ;
compile swap_root_header_1.cpp ;
compile swap_root_header_2.cpp ;
compile swap_lib_header_1.cpp ;
compile swap_lib_header_2.cpp ;
compile swap_mixed_headers_1.cpp ;
compile swap_mixed_headers_2.cpp ;
compile swap_noexcept.cpp ;
compile-fail swap_const_wrapper_fail.cpp ;

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of arrays of swap_test_class objects by means of boost::swap.
// Tests swapping an array of arrays of swap_test_class objects by means of boost::core::invoke_swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -59,7 +59,7 @@ int main()
ptr2[i].set_data( static_cast<int>(i + number_of_elements) );
}
boost::swap(array1, array2);
boost::core::invoke_swap(array1, array2);
for (std::size_t i = 0; i < number_of_elements; ++i)
{

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of arrays of integers by means of boost::swap.
// Tests swapping an array of arrays of integers by means of boost::core::invoke_swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -32,7 +32,7 @@ int main()
ptr2[i] = static_cast<int>(i + number_of_elements);
}
boost::swap(array1, array2);
boost::core::invoke_swap(array1, array2);
for (std::size_t i = 0; i < number_of_elements; ++i)
{

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of arrays of swap_test_class objects by means of boost::swap.
// Tests swapping an array of arrays of swap_test_class objects by means of boost::core::invoke_swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -54,7 +54,7 @@ int main()
std::copy(initial_array2, initial_array2 + array_size, array2);
swap_test_class::reset();
boost::swap(array1, array2);
boost::core::invoke_swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of integers by means of boost::swap.
// Tests swapping an array of integers by means of boost::core::invoke_swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -27,7 +27,7 @@ int main()
std::copy(initial_array1, initial_array1 + array_size, array1);
std::copy(initial_array2, initial_array2 + array_size, array2);
boost::swap(array1, array2);
boost::core::invoke_swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping an array of swap_test_template<int> objects by means of boost::swap.
// Tests swapping an array of swap_test_template<int> objects by means of boost::core::invoke_swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -60,7 +60,7 @@ int main()
std::copy(initial_array2, initial_array2 + array_size, array2);
swap_test_class::reset();
boost::swap(array1, array2);
boost::core::invoke_swap(array1, array2);
BOOST_CHECK(std::equal(array1, array1 + array_size, initial_array2));
BOOST_CHECK(std::equal(array2, array2 + array_size, initial_array1));

View File

@@ -1,8 +1,8 @@
// Copyright 2018 Andrzej Krzemieński
// Copyright 2018 Andrzej Krzemieński
// Copyright 2018 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
#include <boost/core/swap.hpp>
#include <boost/core/invoke_swap.hpp>
namespace boost
{
@@ -14,7 +14,7 @@ template<class T> struct Wrapper
template<class T> inline void swap( Wrapper<T> & w, Wrapper<T> & v )
{
boost::swap( w, v );
boost::core::invoke_swap( w, v );
}
} // namespace boost

View File

@@ -6,5 +6,5 @@
// Tests that the swap header compiles as a standalone translation unit
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>

View File

@@ -6,6 +6,6 @@
// Tests that the swap header include guards work correctly
#include <boost/utility/swap.hpp>
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/invoke_swap.hpp>

View File

@@ -1,11 +0,0 @@
// Copyright (c) 2007 Joseph Gauterin
//
// 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)
// Tests that the swap headers work when both are included
#include <boost/swap.hpp>
#include <boost/utility/swap.hpp>

View File

@@ -1,12 +0,0 @@
// Copyright (c) 2007 Joseph Gauterin
//
// 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)
// Tests that the swap headers work when both are included
#include <boost/utility/swap.hpp>
#include <boost/swap.hpp>

View File

@@ -4,15 +4,15 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// boost::swap internally does an unqualified function call to swap.
// boost::core::invoke_swap internally does an unqualified function call to swap.
// This could have led to ambiguity or infinite recursion, when the
// objects to be swapped would themselves be from the boost namespace.
// If so, boost::swap itself might be found by argument dependent lookup.
// The implementation of boost::swap resolves this issue by giving
// boost::swap two template argumetns, thereby making it less specialized
// If so, boost::core::invoke_swap itself might be found by argument dependent lookup.
// The implementation of boost::core::invoke_swap resolves this issue by giving
// boost::core::invoke_swap two template argumetns, thereby making it less specialized
// than std::swap.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -33,7 +33,7 @@ int main()
boost::swap_test_class object2 = initial_value2;
boost::swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -4,9 +4,9 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests that boost::swap propagates noexcept specification correctly
// Tests that boost::core::invoke_swap propagates noexcept specification correctly
#include <boost/core/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) && \
@@ -34,9 +34,9 @@ struct class_with_except_swap
} // namespace test_ns
static_assert(noexcept(boost::swap(test_ns::class_with_noexcept_swap::instance(), test_ns::class_with_noexcept_swap::instance())),
"boost::swap for class_with_noexcept_swap should have noexcept specification");
static_assert(!noexcept(boost::swap(test_ns::class_with_except_swap::instance(), test_ns::class_with_except_swap::instance())),
"boost::swap for class_with_except_swap should not have noexcept specification");
static_assert(noexcept(boost::core::invoke_swap(test_ns::class_with_noexcept_swap::instance(), test_ns::class_with_noexcept_swap::instance())),
"boost::core::invoke_swap for class_with_noexcept_swap should have noexcept specification");
static_assert(!noexcept(boost::core::invoke_swap(test_ns::class_with_except_swap::instance(), test_ns::class_with_except_swap::instance())),
"boost::core::invoke_swap for class_with_except_swap should not have noexcept specification");
#endif // !defined(BOOST_NO_CXX11_NOEXCEPT) && !defined(BOOST_NO_CXX11_STATIC_ASSERT) ...

View File

@@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -14,7 +14,7 @@ int main()
int object1 = 1;
int object2 = 2;
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1,2);
BOOST_CHECK_EQUAL(object2,1);

View File

@@ -1,10 +0,0 @@
// Copyright (c) 2007 Joseph Gauterin
//
// 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)
// Tests that the swap header compiles as a standalone translation unit
#include <boost/swap.hpp>

View File

@@ -1,11 +0,0 @@
// Copyright (c) 2007 Joseph Gauterin
//
// 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)
// Tests that the swap header include guards work correctly
#include <boost/swap.hpp>
#include <boost/swap.hpp>

View File

@@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -33,7 +33,7 @@ int main()
boost::swap_test_class object2 = initial_value2;
boost::swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -8,13 +8,13 @@
// properly swapped, when both boost and the other namespace have a custom
// swap function for that class. Note that it shouldn't be necessary for a class
// in an other namespace to have a custom swap function in boost, because the
// boost::swap utility should find the swap function in the other namespace, by
// argument dependent lookup (ADL). Unfortunately ADL isn't fully implemented
// by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1, and
// Borland 5.9.3. Users of those compilers might consider adding a swap overload
// boost::core::invoke_swap utility should find the swap function in the other
// namespace, by argument dependent lookup (ADL). Unfortunately ADL isn't fully
// implemented by some specific compiler versions, including Intel C++ 8.1, MSVC 7.1,
// and Borland 5.9.3. Users of those compilers might consider adding a swap overload
// to the boost namespace.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -52,7 +52,7 @@ int main()
other::swap_test_class object2 = initial_value2;
other::swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -27,7 +27,7 @@ int main()
swap_test_class object2 = initial_value2;
swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -33,7 +33,7 @@ int main()
other::swap_test_class object2 = initial_value2;
other::swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -4,7 +4,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -32,7 +32,7 @@ int main()
swap_test_class object2 = initial_value2;
swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK(object1 == initial_value2);
BOOST_CHECK(object2 == initial_value1);

View File

@@ -4,11 +4,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::bitset<T> objects by means of boost::swap.
// Tests swapping std::bitset<T> objects by means of boost::core::invoke_swap.
// Unlike most other Standard C++ Library template classes,
// std::bitset<T> does not have its own std::swap overload.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -24,7 +24,7 @@ int main()
bitset_type object1 = initial_value1;
bitset_type object2 = initial_value2;
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1,initial_value2);
BOOST_CHECK_EQUAL(object2,initial_value1);

View File

@@ -4,11 +4,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::time_base::dateorder objects by means of boost::swap.
// Tests swapping std::time_base::dateorder objects by means of boost::core::invoke_swap.
// std::time_base::dateorder is an enumerated type. It does not have an
// std::swap overload or template specialization.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -23,7 +23,7 @@ int main()
std::time_base::dateorder object1 = initial_value1;
std::time_base::dateorder object2 = initial_value2;
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1,initial_value2);
BOOST_CHECK_EQUAL(object2,initial_value1);

View File

@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::string objects by means of boost::swap.
// Tests swapping std::string objects by means of boost::core::invoke_swap.
// std::string has its own std::swap overload.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -22,7 +22,7 @@ int main()
std::string object1 = initial_value1;
std::string object2 = initial_value2;
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1,initial_value2);
BOOST_CHECK_EQUAL(object2,initial_value1);

View File

@@ -4,11 +4,11 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::type_info pointers by means of boost::swap.
// Tests swapping std::type_info pointers by means of boost::core::invoke_swap.
// There is no std::swap overload or template specialization
// for std::type_info pointers.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -23,7 +23,7 @@ int main()
const std::type_info * ptr1 = initial_value1;
const std::type_info * ptr2 = initial_value2;
boost::swap(ptr1,ptr2);
boost::core::invoke_swap(ptr1,ptr2);
BOOST_CHECK_EQUAL(ptr1,initial_value2);
BOOST_CHECK_EQUAL(ptr2,initial_value1);

View File

@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::vector objects by means of boost::swap,
// Tests swapping std::vector objects by means of boost::core::invoke_swap,
// having boost::swap_test_class as vector element type.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -45,7 +45,7 @@ int main()
swap_test_class_type::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1.size(),initial_size2);
BOOST_CHECK_EQUAL(object2.size(),initial_size1);

View File

@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::vector objects by means of boost::swap,
// Tests swapping std::vector objects by means of boost::core::invoke_swap,
// having ::swap_test_class as vector element type.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -38,7 +38,7 @@ int main()
swap_test_class::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1.size(),initial_size2);
BOOST_CHECK_EQUAL(object2.size(),initial_size1);

View File

@@ -4,10 +4,10 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Tests swapping std::vector objects by means of boost::swap,
// Tests swapping std::vector objects by means of boost::core::invoke_swap,
// having other::swap_test_class as vector element type.
#include <boost/utility/swap.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/core/lightweight_test.hpp>
#define BOOST_CHECK BOOST_TEST
#define BOOST_CHECK_EQUAL BOOST_TEST_EQ
@@ -45,7 +45,7 @@ int main()
swap_test_class_type::reset();
boost::swap(object1,object2);
boost::core::invoke_swap(object1,object2);
BOOST_CHECK_EQUAL(object1.size(),initial_size2);
BOOST_CHECK_EQUAL(object2.size(),initial_size1);

View File

@@ -310,7 +310,11 @@ int main()
TEST(std::pair<void, void>);
TEST(std::pair<std::pair<void, void>, void>);
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 160000
// std::char_traits<Ch> is deprecated for non-char types
#else
TEST(std::basic_string<Ch>);
#endif
TEST(std::string);
TEST(std::wstring);
@@ -402,7 +406,11 @@ int main()
#if !defined(BOOST_NO_CXX17_HDR_STRING_VIEW)
#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION >= 160000
// std::char_traits<Ch> is deprecated for non-char types
#else
TEST(std::basic_string_view<Ch>);
#endif
TEST(std::string_view);
TEST(std::wstring_view);

View File

@@ -0,0 +1,54 @@
// Test that yield primitives aren't cancelation points
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/core/yield_primitives.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/pragma_message.hpp>
#if !defined(BOOST_HAS_PTHREADS)
BOOST_PRAGMA_MESSAGE( "Skipping test because BOOST_HAS_PTHREADS is not defined" )
int main() {}
#else
#include <pthread.h>
pthread_mutex_t s_mx = PTHREAD_MUTEX_INITIALIZER;
void* threadfunc( void* )
{
pthread_mutex_lock( &s_mx );
pthread_mutex_unlock( &s_mx );
boost::core::sp_thread_pause();
boost::core::sp_thread_yield();
boost::core::sp_thread_sleep();
return 0;
}
int main()
{
pthread_mutex_lock( &s_mx );
pthread_t th;
pthread_create( &th, 0, threadfunc, 0 );
pthread_cancel( th );
pthread_mutex_unlock( &s_mx );
void* r;
pthread_join( th, &r );
BOOST_TEST_EQ( r, (void*)0 );
return boost::report_errors();
}
#endif

View File

@@ -0,0 +1,18 @@
// Test for yield_primitives.hpp compatibility with windows.h
//
// Copyright 2023 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
# include <windows.h>
#endif
#include <boost/core/yield_primitives.hpp>
int main()
{
boost::core::sp_thread_pause();
boost::core::sp_thread_yield();
boost::core::sp_thread_sleep();
}