Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide graceful failure for Bernoulli code on platforms with no atomics. #684

Merged
merged 5 commits into from
Sep 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class bernoulli_numbers_cache
return out;
}

#ifndef BOOST_HAS_THREADS
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_MATH_BERNOULLI_UNTHREADED)
//
// Single threaded code, very simple:
//
Expand All @@ -382,6 +382,8 @@ class bernoulli_numbers_cache
*out = (i >= m_overflow_limit) ? policies::raise_overflow_error<T>("boost::math::bernoulli_b2n<%1%>(std::size_t)", 0, T(i), pol) : bn[i];
++out;
}
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
static_assert(sizeof(T) == 1, "Unsupported configuration: your platform appears to have no atomic integers. If you are happy with thread-unsafe code, then you may define BOOST_MATH_BERNOULLI_UNTHREADED to suppress this error.");
#else
//
// Double-checked locking pattern, lets us access cached already cached values
Expand Down Expand Up @@ -464,7 +466,7 @@ class bernoulli_numbers_cache
return out;
}

#ifndef BOOST_HAS_THREADS
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_MATH_BERNOULLI_UNTHREADED)
//
// Single threaded code, very simple:
//
Expand Down Expand Up @@ -494,6 +496,8 @@ class bernoulli_numbers_cache
}
++out;
}
#elif defined(BOOST_MATH_NO_ATOMIC_INT)
static_assert(sizeof(T) == 1, "Unsupported configuration: your platform appears to have no atomic integers. If you are happy with thread-unsafe code, then you may define BOOST_MATH_BERNOULLI_UNTHREADED to suppress this error.");
#else
//
// Double-checked locking pattern, lets us access cached already cached values
Expand Down Expand Up @@ -555,7 +559,7 @@ class bernoulli_numbers_cache
// The value at which we know overflow has already occurred for the Bn:
std::size_t m_overflow_limit;

#ifdef BOOST_HAS_THREADS
#if defined(BOOST_HAS_THREADS) && !defined(BOOST_MATH_NO_ATOMIC_INT)
std::mutex m_mutex;
atomic_counter_type m_counter, m_current_precision;
#else
Expand Down
10 changes: 5 additions & 5 deletions include/boost/math/tools/atomic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,27 @@
namespace boost {
namespace math {
namespace detail {
#if ATOMIC_INT_LOCK_FREE == 2
#if (ATOMIC_INT_LOCK_FREE == 2) && !defined(BOOST_MATH_NO_ATOMIC_INT)
typedef std::atomic<int> atomic_counter_type;
typedef std::atomic<unsigned> atomic_unsigned_type;
typedef int atomic_integer_type;
typedef unsigned atomic_unsigned_integer_type;
#elif ATOMIC_SHORT_LOCK_FREE == 2
#elif (ATOMIC_SHORT_LOCK_FREE == 2) && !defined(BOOST_MATH_NO_ATOMIC_INT)
typedef std::atomic<short> atomic_counter_type;
typedef std::atomic<unsigned short> atomic_unsigned_type;
typedef short atomic_integer_type;
typedef unsigned short atomic_unsigned_type;
#elif ATOMIC_LONG_LOCK_FREE == 2
#elif (ATOMIC_LONG_LOCK_FREE == 2) && !defined(BOOST_MATH_NO_ATOMIC_INT)
typedef std::atomic<long> atomic_unsigned_integer_type;
typedef std::atomic<unsigned long> atomic_unsigned_type;
typedef unsigned long atomic_unsigned_type;
typedef long atomic_integer_type;
#elif ATOMIC_LLONG_LOCK_FREE == 2
#elif (ATOMIC_LLONG_LOCK_FREE == 2) && !defined(BOOST_MATH_NO_ATOMIC_INT)
typedef std::atomic<long long> atomic_unsigned_integer_type;
typedef std::atomic<unsigned long long> atomic_unsigned_type;
typedef long long atomic_integer_type;
typedef unsigned long long atomic_unsigned_integer_type;
#else
#elif !defined(BOOST_MATH_NO_ATOMIC_INT)
# define BOOST_MATH_NO_ATOMIC_INT
#endif
} // Namespace detail
Expand Down
3 changes: 3 additions & 0 deletions test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,9 @@ test-suite misc :

# [ run __temporary_test.cpp test_instances//test_instances : : : <test-info>always_show_run_output <pch>off ]
[ compile test_no_long_double_policy.cpp ]
[ compile bernoulli_no_atomic_d.cpp ]
[ compile bernoulli_no_atomic_mp.cpp ]
[ compile-fail bernoulli_no_atomic_fail.cpp ]
;

test-suite interpolators :
Expand Down
14 changes: 14 additions & 0 deletions test/bernoulli_no_atomic_d.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// (C) Copyright John Maddock 2021.
// Use, modification and distribution are subject to 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_MATH_NO_ATOMIC_INT

#include <boost/math/special_functions/bernoulli.hpp>
#include "compile_test/test_compile_result.hpp"

void compile_and_link_test()
{
check_result<double>(boost::math::bernoulli_b2n<double>(4));
}
15 changes: 15 additions & 0 deletions test/bernoulli_no_atomic_fail.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// (C) Copyright John Maddock 2021.
// Use, modification and distribution are subject to 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_MATH_NO_ATOMIC_INT

#include <boost/math/special_functions/bernoulli.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include "compile_test/test_compile_result.hpp"

void compile_and_link_test()
{
check_result<boost::multiprecision::cpp_bin_float_50>(boost::math::bernoulli_b2n<boost::multiprecision::cpp_bin_float_50>(4));
}
16 changes: 16 additions & 0 deletions test/bernoulli_no_atomic_mp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// (C) Copyright John Maddock 2021.
// Use, modification and distribution are subject to 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_MATH_NO_ATOMIC_INT
#define BOOST_MATH_BERNOULLI_UNTHREADED

#include <boost/math/special_functions/bernoulli.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include "compile_test/test_compile_result.hpp"

void compile_and_link_test()
{
check_result<boost::multiprecision::cpp_bin_float_50>(boost::math::bernoulli_b2n<boost::multiprecision::cpp_bin_float_50>(4));
}