mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8373208: Make Atomic class template constant initializable
Reviewed-by: stefank, dholmes
This commit is contained in:
parent
f88cbfb8c6
commit
623164651c
@ -26,7 +26,6 @@
|
||||
#define SHARE_RUNTIME_ATOMIC_HPP
|
||||
|
||||
#include "cppstdlib/type_traits.hpp"
|
||||
#include "metaprogramming/enableIf.hpp"
|
||||
#include "metaprogramming/primitiveConversions.hpp"
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
@ -89,8 +88,12 @@
|
||||
// value will be initialized as if by translating the value that would be
|
||||
// provided by default constructing an atomic type for the value type's
|
||||
// decayed type.
|
||||
|
||||
// (3) Atomic pointers and atomic integers additionally provide
|
||||
//
|
||||
// (3) Constructors for all atomic types are constexpr, to ensure non-local
|
||||
// atomic variables are constant initialized (C++17 6.6.2) when initialized
|
||||
// with suitable arguments.
|
||||
//
|
||||
// (4) Atomic pointers and atomic integers additionally provide
|
||||
//
|
||||
// member functions:
|
||||
// v.add_then_fetch(i [, o]) -> T
|
||||
@ -102,7 +105,7 @@
|
||||
// type of i must be signed, or both must be unsigned. Atomic pointers perform
|
||||
// element arithmetic.
|
||||
//
|
||||
// (4) Atomic integers additionally provide
|
||||
// (5) Atomic integers additionally provide
|
||||
//
|
||||
// member functions:
|
||||
// v.and_then_fetch(x [, o]) -> T
|
||||
@ -112,7 +115,7 @@
|
||||
// v.fetch_then_or(x [, o]) -> T
|
||||
// v.fetch_then_xor(x [, o]) -> T
|
||||
//
|
||||
// (5) Atomic pointers additionally provide
|
||||
// (6) Atomic pointers additionally provide
|
||||
//
|
||||
// nested types:
|
||||
// ElementType -> std::remove_pointer_t<T>
|
||||
@ -217,7 +220,7 @@ class AtomicImpl::CommonCore {
|
||||
T volatile _value;
|
||||
|
||||
protected:
|
||||
explicit CommonCore(T value) : _value(value) {}
|
||||
explicit constexpr CommonCore(T value) : _value(value) {}
|
||||
~CommonCore() = default;
|
||||
|
||||
T volatile* value_ptr() { return &_value; }
|
||||
@ -290,7 +293,7 @@ class AtomicImpl::SupportsArithmetic : public CommonCore<T> {
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit SupportsArithmetic(T value) : CommonCore<T>(value) {}
|
||||
explicit constexpr SupportsArithmetic(T value) : CommonCore<T>(value) {}
|
||||
~SupportsArithmetic() = default;
|
||||
|
||||
public:
|
||||
@ -333,7 +336,7 @@ class AtomicImpl::Atomic<T, AtomicImpl::Category::Integer>
|
||||
: public SupportsArithmetic<T>
|
||||
{
|
||||
public:
|
||||
explicit Atomic(T value = 0) : SupportsArithmetic<T>(value) {}
|
||||
explicit constexpr Atomic(T value = 0) : SupportsArithmetic<T>(value) {}
|
||||
|
||||
NONCOPYABLE(Atomic);
|
||||
|
||||
@ -373,7 +376,7 @@ class AtomicImpl::Atomic<T, AtomicImpl::Category::Byte>
|
||||
: public CommonCore<T>
|
||||
{
|
||||
public:
|
||||
explicit Atomic(T value = 0) : CommonCore<T>(value) {}
|
||||
explicit constexpr Atomic(T value = 0) : CommonCore<T>(value) {}
|
||||
|
||||
NONCOPYABLE(Atomic);
|
||||
|
||||
@ -389,7 +392,7 @@ class AtomicImpl::Atomic<T, AtomicImpl::Category::Pointer>
|
||||
: public SupportsArithmetic<T>
|
||||
{
|
||||
public:
|
||||
explicit Atomic(T value = nullptr) : SupportsArithmetic<T>(value) {}
|
||||
explicit constexpr Atomic(T value = nullptr) : SupportsArithmetic<T>(value) {}
|
||||
|
||||
NONCOPYABLE(Atomic);
|
||||
|
||||
@ -410,12 +413,21 @@ class AtomicImpl::Atomic<T, AtomicImpl::Category::Translated> {
|
||||
|
||||
Atomic<Decayed> _value;
|
||||
|
||||
static Decayed decay(T x) { return Translator::decay(x); }
|
||||
// The decay function and the constructors are constexpr so that a non-local
|
||||
// atomic object constructed with constant arguments will be a constant
|
||||
// initialization. One might ask why it's not a problem that some
|
||||
// specializations of these functions are not constant expressions. The
|
||||
// answer lies in C++17 10.1.5/6, along with us having *some* constexpr
|
||||
// translator decay functions, constexpr ctors for some translated types,
|
||||
// and constexpr ctors for some decayed types. Also, C++23 removes those
|
||||
// restrictions on constexpr functions and ctors.
|
||||
|
||||
static constexpr Decayed decay(T x) { return Translator::decay(x); }
|
||||
static T recover(Decayed x) { return Translator::recover(x); }
|
||||
|
||||
// Support for default construction via the default construction of _value.
|
||||
struct UseDecayedCtor {};
|
||||
explicit Atomic(UseDecayedCtor) : _value() {}
|
||||
explicit constexpr Atomic(UseDecayedCtor) : _value() {}
|
||||
using DefaultCtorSelect =
|
||||
std::conditional_t<std::is_default_constructible_v<T>, T, UseDecayedCtor>;
|
||||
|
||||
@ -424,9 +436,9 @@ public:
|
||||
|
||||
// If T is default constructible, construct from a default constructed T.
|
||||
// Otherwise, default construct the underlying Atomic<Decayed>.
|
||||
Atomic() : Atomic(DefaultCtorSelect()) {}
|
||||
constexpr Atomic() : Atomic(DefaultCtorSelect()) {}
|
||||
|
||||
explicit Atomic(T value) : _value(decay(value)) {}
|
||||
explicit constexpr Atomic(T value) : _value(decay(value)) {}
|
||||
|
||||
NONCOPYABLE(Atomic);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user