mirror of https://github.com/ARMmbed/mbed-os.git
Move Atomic.h to <mstd_atomic>
`mbed::Atomic<T>` becomes `mstd::atomic<T>`, alongside the other standard C++ library lookalikes.pull/11039/head
parent
da3cd6f053
commit
b1c35b7a86
|
@ -18,6 +18,8 @@
|
||||||
#include "unity/unity.h"
|
#include "unity/unity.h"
|
||||||
#include "utest/utest.h"
|
#include "utest/utest.h"
|
||||||
|
|
||||||
|
#include <mstd_atomic>
|
||||||
|
|
||||||
#if !MBED_CONF_RTOS_PRESENT
|
#if !MBED_CONF_RTOS_PRESENT
|
||||||
#error [NOT_SUPPORTED] test not supported
|
#error [NOT_SUPPORTED] test not supported
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,6 +30,8 @@ using utest::v1::Case;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using mstd::atomic;
|
||||||
|
|
||||||
/* Lock-free operations will be much faster - keep runtime down */
|
/* Lock-free operations will be much faster - keep runtime down */
|
||||||
#define ADD_UNLOCKED_ITERATIONS (SystemCoreClock / 1000)
|
#define ADD_UNLOCKED_ITERATIONS (SystemCoreClock / 1000)
|
||||||
#define ADD_LOCKED_ITERATIONS (SystemCoreClock / 8000)
|
#define ADD_LOCKED_ITERATIONS (SystemCoreClock / 8000)
|
||||||
|
@ -53,7 +57,7 @@ struct add_release_incrementer {
|
||||||
static void op(A *ptr)
|
static void op(A *ptr)
|
||||||
{
|
{
|
||||||
for (long i = add_iterations(*ptr); i > 0; i--) {
|
for (long i = add_iterations(*ptr); i > 0; i--) {
|
||||||
ptr->fetch_add(1, mbed::memory_order_release);
|
ptr->fetch_add(1, mstd::memory_order_release);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -120,8 +124,8 @@ void test_atomic_add()
|
||||||
{
|
{
|
||||||
struct {
|
struct {
|
||||||
volatile T nonatomic1;
|
volatile T nonatomic1;
|
||||||
Atomic<T> atomic1;
|
atomic<T> atomic1;
|
||||||
volatile Atomic<T> atomic2; // use volatile just to exercise the templates' volatile methods
|
volatile atomic<T> atomic2; // use volatile just to exercise the templates' volatile methods
|
||||||
volatile T nonatomic2;
|
volatile T nonatomic2;
|
||||||
} data = { 0, { 0 }, { 1 }, 0 }; // test initialisation
|
} data = { 0, { 0 }, { 1 }, 0 }; // test initialisation
|
||||||
|
|
||||||
|
@ -201,17 +205,17 @@ void struct_incrementer_b(A *data)
|
||||||
template<typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
void test_atomic_struct()
|
void test_atomic_struct()
|
||||||
{
|
{
|
||||||
TEST_ASSERT_EQUAL(N, sizeof(Atomic<T>));
|
TEST_ASSERT_EQUAL(N, sizeof(atomic<T>));
|
||||||
|
|
||||||
// Small structures don't have value constructor implemented;
|
// Small structures don't have value constructor implemented;
|
||||||
Atomic<T> data;
|
atomic<T> data;
|
||||||
atomic_init(&data, T{0, 0, 0});
|
atomic_init(&data, T{0, 0, 0});
|
||||||
|
|
||||||
Thread t1(osPriorityNormal, THREAD_STACK);
|
Thread t1(osPriorityNormal, THREAD_STACK);
|
||||||
Thread t2(osPriorityNormal, THREAD_STACK);
|
Thread t2(osPriorityNormal, THREAD_STACK);
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(osOK, t1.start(callback(struct_incrementer_a<Atomic<T> >, &data)));
|
TEST_ASSERT_EQUAL(osOK, t1.start(callback(struct_incrementer_a<atomic<T> >, &data)));
|
||||||
TEST_ASSERT_EQUAL(osOK, t2.start(callback(struct_incrementer_b<Atomic<T> >, &data)));
|
TEST_ASSERT_EQUAL(osOK, t2.start(callback(struct_incrementer_b<atomic<T> >, &data)));
|
||||||
|
|
||||||
for (long i = add_iterations(data); i > 0; i--) {
|
for (long i = add_iterations(data); i > 0; i--) {
|
||||||
T curval = data, newval;
|
T curval = data, newval;
|
||||||
|
|
2
mbed.h
2
mbed.h
|
@ -89,7 +89,7 @@
|
||||||
#include "platform/mbed_wait_api.h"
|
#include "platform/mbed_wait_api.h"
|
||||||
#include "platform/mbed_thread.h"
|
#include "platform/mbed_thread.h"
|
||||||
#include "hal/sleep_api.h"
|
#include "hal/sleep_api.h"
|
||||||
#include "platform/Atomic.h"
|
#include "platform/mbed_atomic.h"
|
||||||
#include "platform/mbed_power_mgmt.h"
|
#include "platform/mbed_power_mgmt.h"
|
||||||
#include "platform/mbed_rtc_time.h"
|
#include "platform/mbed_rtc_time.h"
|
||||||
#include "platform/mbed_poll.h"
|
#include "platform/mbed_poll.h"
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* mbed Microcontroller Library
|
||||||
|
* Copyright (c) 2019 ARM Limited
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifndef __atomic
|
||||||
|
#define __atomic
|
||||||
|
|
||||||
|
// Just go straight to the main file
|
||||||
|
#include <mstd_atomic>
|
||||||
|
|
||||||
|
#define ATOMIC_VAR_INIT(x) { x }
|
||||||
|
#define ATOMIC_FLAG_INIT MSTD_ATOMIC_FLAG_INIT
|
||||||
|
|
||||||
|
// And then pull it all into our std
|
||||||
|
namespace std {
|
||||||
|
using mstd::atomic;
|
||||||
|
using mstd::atomic_is_lock_free;
|
||||||
|
using mstd::atomic_store;
|
||||||
|
using mstd::atomic_store_explicit;
|
||||||
|
using mstd::atomic_load;
|
||||||
|
using mstd::atomic_load_explicit;
|
||||||
|
using mstd::atomic_exchange;
|
||||||
|
using mstd::atomic_exchange_explicit;
|
||||||
|
using mstd::atomic_compare_exchange_weak;
|
||||||
|
using mstd::atomic_compare_exchange_weak_explicit;
|
||||||
|
using mstd::atomic_compare_exchange_strong;
|
||||||
|
using mstd::atomic_compare_exchange_strong_explicit;
|
||||||
|
using mstd::atomic_fetch_add;
|
||||||
|
using mstd::atomic_fetch_add_explicit;
|
||||||
|
using mstd::atomic_fetch_sub;
|
||||||
|
using mstd::atomic_fetch_sub_explicit;
|
||||||
|
using mstd::atomic_fetch_and;
|
||||||
|
using mstd::atomic_fetch_and_explicit;
|
||||||
|
using mstd::atomic_fetch_or;
|
||||||
|
using mstd::atomic_fetch_or_explicit;
|
||||||
|
using mstd::atomic_fetch_xor;
|
||||||
|
using mstd::atomic_fetch_xor_explicit;
|
||||||
|
using mstd::atomic_flag;
|
||||||
|
using mstd::atomic_flag_test_and_set;
|
||||||
|
using mstd::atomic_flag_test_and_set_explicit;
|
||||||
|
using mstd::atomic_flag_clear;
|
||||||
|
using mstd::atomic_flag_clear_explicit;
|
||||||
|
using mstd::atomic_init;
|
||||||
|
using mstd::memory_order;
|
||||||
|
using mstd::kill_dependency;
|
||||||
|
using mstd::atomic_thread_fence;
|
||||||
|
using mstd::atomic_signal_fence;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __atomic */
|
|
@ -15,8 +15,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBED_ATOMIC_H
|
#ifndef MSTD_ATOMIC_
|
||||||
#define MBED_ATOMIC_H
|
#define MSTD_ATOMIC_
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
#include "platform/CriticalSectionLock.h"
|
#include "platform/CriticalSectionLock.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomic template and types are designed to be as close as possible to C++11
|
* mstd::atomic template and types are designed to be as close as possible to C++11
|
||||||
* std::atomic. Key differences:
|
* std::atomic. Key differences:
|
||||||
*
|
*
|
||||||
* - Operations are specified as atomic with respect to interrupts as well as
|
* - Operations are specified as atomic with respect to interrupts as well as
|
||||||
|
@ -43,34 +43,34 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MBED_EXCLUSIVE_ACCESS
|
#ifndef MBED_EXCLUSIVE_ACCESS
|
||||||
#define MBED_ATOMIC_BOOL_LOCK_FREE 0
|
#define MSTD_ATOMIC_BOOL_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_CHAR_LOCK_FREE 0
|
#define MSTD_ATOMIC_CHAR_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_CHAR16_T_LOCK_FREE 0
|
#define MSTD_ATOMIC_CHAR16_T_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_CHAR32_T_LOCK_FREE 0
|
#define MSTD_ATOMIC_CHAR32_T_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_WCHAR_T_LOCK_FREE 0
|
#define MSTD_ATOMIC_WCHAR_T_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_SHORT_LOCK_FREE 0
|
#define MSTD_ATOMIC_SHORT_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_INT_LOCK_FREE 0
|
#define MSTD_ATOMIC_INT_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_LONG_LOCK_FREE 0
|
#define MSTD_ATOMIC_LONG_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_LLONG_LOCK_FREE 0
|
#define MSTD_ATOMIC_LLONG_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_POINTER_LOCK_FREE 0
|
#define MSTD_ATOMIC_POINTER_LOCK_FREE 0
|
||||||
#else
|
#else
|
||||||
#define MBED_ATOMIC_BOOL_LOCK_FREE 2
|
#define MSTD_ATOMIC_BOOL_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_CHAR_LOCK_FREE 2
|
#define MSTD_ATOMIC_CHAR_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_CHAR16_T_LOCK_FREE 2
|
#define MSTD_ATOMIC_CHAR16_T_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_CHAR32_T_LOCK_FREE 2
|
#define MSTD_ATOMIC_CHAR32_T_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_WCHAR_T_LOCK_FREE 2
|
#define MSTD_ATOMIC_WCHAR_T_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_SHORT_LOCK_FREE 2
|
#define MSTD_ATOMIC_SHORT_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_INT_LOCK_FREE 2
|
#define MSTD_ATOMIC_INT_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_LONG_LOCK_FREE 2
|
#define MSTD_ATOMIC_LONG_LOCK_FREE 2
|
||||||
#define MBED_ATOMIC_LLONG_LOCK_FREE 0
|
#define MSTD_ATOMIC_LLONG_LOCK_FREE 0
|
||||||
#define MBED_ATOMIC_POINTER_LOCK_FREE 2
|
#define MSTD_ATOMIC_POINTER_LOCK_FREE 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace mbed {
|
namespace mstd {
|
||||||
|
|
||||||
/** Atomic template
|
/** Atomic template
|
||||||
*
|
*
|
||||||
* `mbed::Atomic<T>` is intended to work as per C++14 `std::atomic<T>`. `T` must be a
|
* `mstd::atomic<T>` is intended to work as per C++14 `std::atomic<T>`. `T` must be a
|
||||||
* _TriviallyCopyable_, _CopyConstructible_ and _CopyAssignable_ type.
|
* _TriviallyCopyable_, _CopyConstructible_ and _CopyAssignable_ type.
|
||||||
* - All standard methods of `std::atomic` are supplied:
|
* - All standard methods of `std::atomic` are supplied:
|
||||||
* + For any `T`: `load`, `store`, `exchange`, `compare_exchange_weak`,
|
* + For any `T`: `load`, `store`, `exchange`, `compare_exchange_weak`,
|
||||||
|
@ -85,15 +85,15 @@ namespace mbed {
|
||||||
* otherwise critical sections are used.
|
* otherwise critical sections are used.
|
||||||
* - If used with large objects, interrupt latency may be impacted.
|
* - If used with large objects, interrupt latency may be impacted.
|
||||||
* - Valid initialisation forms are:
|
* - Valid initialisation forms are:
|
||||||
* + `Atomic<int> foo;` (zero initialized if static or thread-local, else value indeterminate)
|
* + `atomic<int> foo;` (zero initialized if static or thread-local, else value indeterminate)
|
||||||
* + `atomic_init(&foo, 2);` (initialize a default-initialized variable, once only, not atomic)
|
* + `atomic_init(&foo, 2);` (initialize a default-initialized variable, once only, not atomic)
|
||||||
* + `Atomic<int> foo(2);` (value initialization)
|
* + `atomic<int> foo(2);` (value initialization)
|
||||||
* + `Atomic<int> foo = { 2 };` (also legal C11 with _Atomic int)
|
* + `atomic<int> foo = { 2 };` (also legal C11 with _Atomic int)
|
||||||
* + `Atomic<int> foo = 2;` (C++17 or later only - also legal C11 with _Atomic int)
|
* + `atomic<int> foo = 2;` (C++17 or later only - also legal C11 with _Atomic int)
|
||||||
* Note that the lack of a copy constructor limits the simple-looking assignment initialization
|
* Note that the lack of a copy constructor limits the simple-looking assignment initialization
|
||||||
* to C++17 or later only.
|
* to C++17 or later only.
|
||||||
* - The value constructor is not available for small custom types.
|
* - The value constructor is not available for small custom types.
|
||||||
* - `MBED_ATOMIC_XXX_LOCK_FREE` replaces `ATOMIC_XXX_LOCK_FREE` - "locking" forms
|
* - `MSTD_ATOMIC_XXX_LOCK_FREE` replaces `ATOMIC_XXX_LOCK_FREE` - "locking" forms
|
||||||
* take a critical section, non-locking do not.
|
* take a critical section, non-locking do not.
|
||||||
* - For `bool`, integer types and pointers, storage is compatible with the
|
* - For `bool`, integer types and pointers, storage is compatible with the
|
||||||
* plain types. If necessary, they can be substituted as plain types for C
|
* plain types. If necessary, they can be substituted as plain types for C
|
||||||
|
@ -101,7 +101,7 @@ namespace mbed {
|
||||||
* @code
|
* @code
|
||||||
* struct foo {
|
* struct foo {
|
||||||
* #ifdef __cplusplus
|
* #ifdef __cplusplus
|
||||||
* mbed::atomic_uint32_t counter; // Use C++ templates from C++ code
|
* mstd::atomic_uint32_t counter; // Use C++ templates from C++ code
|
||||||
* #else
|
* #else
|
||||||
* uint32_t counter; // Could use core_util_atomic_xxx_u32 from C code, or just have this for structure layout.
|
* uint32_t counter; // Could use core_util_atomic_xxx_u32 from C code, or just have this for structure layout.
|
||||||
* #endif
|
* #endif
|
||||||
|
@ -109,9 +109,9 @@ namespace mbed {
|
||||||
* @endcode
|
* @endcode
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Atomic;
|
class atomic;
|
||||||
|
|
||||||
/* Pull C enum from mbed_critical.h into mbed namespace */
|
/* Pull C enum from mbed_critical.h into mstd namespace */
|
||||||
using memory_order = ::mbed_memory_order;
|
using memory_order = ::mbed_memory_order;
|
||||||
constexpr memory_order memory_order_relaxed = mbed_memory_order_relaxed;
|
constexpr memory_order memory_order_relaxed = mbed_memory_order_relaxed;
|
||||||
constexpr memory_order memory_order_consume = mbed_memory_order_consume;
|
constexpr memory_order memory_order_consume = mbed_memory_order_consume;
|
||||||
|
@ -127,10 +127,10 @@ namespace impl {
|
||||||
*/
|
*/
|
||||||
// *INDENT-OFF*
|
// *INDENT-OFF*
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using atomic_container = std::conditional <sizeof(T) <= sizeof(uint8_t), uint8_t,
|
using atomic_container = conditional <sizeof(T) <= sizeof(uint8_t), uint8_t,
|
||||||
std::conditional_t<sizeof(T) <= sizeof(uint16_t), uint16_t,
|
conditional_t<sizeof(T) <= sizeof(uint16_t), uint16_t,
|
||||||
std::conditional_t<sizeof(T) <= sizeof(uint32_t), uint32_t,
|
conditional_t<sizeof(T) <= sizeof(uint32_t), uint32_t,
|
||||||
std::conditional_t<sizeof(T) <= sizeof(uint64_t), uint64_t,
|
conditional_t<sizeof(T) <= sizeof(uint64_t), uint64_t,
|
||||||
T
|
T
|
||||||
>>>>;
|
>>>>;
|
||||||
// *INDENT-ON*
|
// *INDENT-ON*
|
||||||
|
@ -142,16 +142,16 @@ template<typename N>
|
||||||
struct atomic_container_is_lock_free;
|
struct atomic_container_is_lock_free;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct atomic_container_is_lock_free<uint8_t> : mstd::bool_constant<bool(MBED_ATOMIC_CHAR_LOCK_FREE)> { };
|
struct atomic_container_is_lock_free<uint8_t> : bool_constant<bool(MSTD_ATOMIC_CHAR_LOCK_FREE)> { };
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct atomic_container_is_lock_free<uint16_t> : mstd::bool_constant<bool(MBED_ATOMIC_SHORT_LOCK_FREE)> { };
|
struct atomic_container_is_lock_free<uint16_t> : bool_constant<bool(MSTD_ATOMIC_SHORT_LOCK_FREE)> { };
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct atomic_container_is_lock_free<uint32_t> : mstd::bool_constant<bool(MBED_ATOMIC_INT_LOCK_FREE)> { };
|
struct atomic_container_is_lock_free<uint32_t> : bool_constant<bool(MSTD_ATOMIC_INT_LOCK_FREE)> { };
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct atomic_container_is_lock_free<uint64_t> : mstd::bool_constant<bool(MBED_ATOMIC_LLONG_LOCK_FREE)> { };
|
struct atomic_container_is_lock_free<uint64_t> : bool_constant<bool(MSTD_ATOMIC_LLONG_LOCK_FREE)> { };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using atomic_is_lock_free = atomic_container_is_lock_free<atomic_container_t<T>>;
|
using atomic_is_lock_free = atomic_container_is_lock_free<atomic_container_t<T>>;
|
||||||
|
@ -571,7 +571,7 @@ protected:
|
||||||
|
|
||||||
/* Template for an integer or pointer Atomic, including increment and
|
/* Template for an integer or pointer Atomic, including increment and
|
||||||
* decrement functionality. If StrideT is void, then the increment and
|
* decrement functionality. If StrideT is void, then the increment and
|
||||||
* decrement operators are ill-formed, as desired for Atomic<void *>.
|
* decrement operators are ill-formed, as desired for atomic<void *>.
|
||||||
*/
|
*/
|
||||||
template<typename T, typename DiffT = T, typename StrideT = char, typename A = atomic_container_t<T>>
|
template<typename T, typename DiffT = T, typename StrideT = char, typename A = atomic_container_t<T>>
|
||||||
struct AtomicWithAdd : public AtomicBaseInt<T, A> {
|
struct AtomicWithAdd : public AtomicBaseInt<T, A> {
|
||||||
|
@ -703,15 +703,15 @@ struct AtomicWithBitwise : public AtomicWithAdd<T, A> {
|
||||||
*/
|
*/
|
||||||
// *INDENT-OFF*
|
// *INDENT-OFF*
|
||||||
template<typename T, typename = void>
|
template<typename T, typename = void>
|
||||||
struct AtomicSelector : mstd::type_identity<AtomicBaseRaw<T>> { };
|
struct AtomicSelector : type_identity<AtomicBaseRaw<T>> { };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct AtomicSelector<T, std::enable_if_t<std::is_same<bool, T>::value>>
|
struct AtomicSelector<T, enable_if_t<is_same<bool, T>::value>>
|
||||||
: mstd::type_identity<AtomicBaseInt<T>> { };
|
: type_identity<AtomicBaseInt<T>> { };
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct AtomicSelector<T, std::enable_if_t<std::is_integral<T>::value && !std::is_same<bool, T>::value>>
|
struct AtomicSelector<T, enable_if_t<is_integral<T>::value && !is_same<bool, T>::value>>
|
||||||
: mstd::type_identity<AtomicWithBitwise<T>> { };
|
: type_identity<AtomicWithBitwise<T>> { };
|
||||||
// *INDENT-ON*
|
// *INDENT-ON*
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -720,23 +720,23 @@ using Atomic = typename AtomicSelector<T>::type;
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_init(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept;
|
void atomic_init(volatile atomic<T> *obj, typename atomic<T>::value_type desired) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_init(Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept;
|
void atomic_init(atomic<T> *obj, typename atomic<T>::value_type desired) noexcept;
|
||||||
|
|
||||||
/* Base template - let impl::Atomic<T> dispatch to raw, base integer or integer-with-bitwise */
|
/* Base template - let impl::Atomic<T> dispatch to raw, base integer or integer-with-bitwise */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Atomic : public impl::Atomic<T> {
|
struct atomic : public impl::Atomic<T> {
|
||||||
// Constraints from LWG 3012
|
// Constraints from LWG 3012
|
||||||
static_assert(std::is_trivially_copyable<T>::value, "Atomic types must be TriviallyCopyable");
|
static_assert(is_trivially_copyable<T>::value, "Atomic types must be TriviallyCopyable");
|
||||||
static_assert(std::is_copy_constructible<T>::value, "Atomic types must be CopyConstructible");
|
static_assert(is_copy_constructible<T>::value, "Atomic types must be CopyConstructible");
|
||||||
static_assert(std::is_move_constructible<T>::value, "Atomic types must be MoveConstructible");
|
static_assert(is_move_constructible<T>::value, "Atomic types must be MoveConstructible");
|
||||||
static_assert(std::is_copy_assignable<T>::value, "Atomic types must be CopyAssignable");
|
static_assert(is_copy_assignable<T>::value, "Atomic types must be CopyAssignable");
|
||||||
static_assert(std::is_move_assignable<T>::value, "Atomic types must be MoveAssignable");
|
static_assert(is_move_assignable<T>::value, "Atomic types must be MoveAssignable");
|
||||||
Atomic() noexcept = default;
|
atomic() noexcept = default;
|
||||||
Atomic(const Atomic &) = delete;
|
atomic(const atomic &) = delete;
|
||||||
constexpr Atomic(T v) noexcept : impl::Atomic<T>(std::move(v))
|
constexpr atomic(T v) noexcept : impl::Atomic<T>(std::move(v))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
operator T() const volatile noexcept
|
operator T() const volatile noexcept
|
||||||
|
@ -757,10 +757,10 @@ struct Atomic : public impl::Atomic<T> {
|
||||||
this->store(desired);
|
this->store(desired);
|
||||||
return desired;
|
return desired;
|
||||||
}
|
}
|
||||||
Atomic &operator=(const Atomic &) = delete;
|
atomic &operator=(const atomic &) = delete;
|
||||||
private:
|
private:
|
||||||
friend void atomic_init<>(volatile Atomic *obj, typename Atomic::value_type desired) noexcept;
|
friend void atomic_init<>(volatile atomic *obj, typename atomic::value_type desired) noexcept;
|
||||||
friend void atomic_init<>(Atomic *obj, typename Atomic::value_type desired) noexcept;
|
friend void atomic_init<>(atomic *obj, typename atomic::value_type desired) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -770,10 +770,10 @@ private:
|
||||||
* "aptr.load()->member" to use it to access a structure. *aptr is fine though.
|
* "aptr.load()->member" to use it to access a structure. *aptr is fine though.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct Atomic<T *> : public impl::AtomicWithAdd<T *, ptrdiff_t, T> {
|
struct atomic<T *> : public impl::AtomicWithAdd<T *, ptrdiff_t, T> {
|
||||||
Atomic() noexcept = default;
|
atomic() noexcept = default;
|
||||||
Atomic(const Atomic &) = delete;
|
atomic(const atomic &) = delete;
|
||||||
constexpr Atomic(T *v) noexcept : impl::AtomicWithAdd<T *, ptrdiff_t, T>(v)
|
constexpr atomic(T *v) noexcept : impl::AtomicWithAdd<T *, ptrdiff_t, T>(v)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
operator T *() const volatile noexcept
|
operator T *() const volatile noexcept
|
||||||
|
@ -794,190 +794,190 @@ struct Atomic<T *> : public impl::AtomicWithAdd<T *, ptrdiff_t, T> {
|
||||||
this->store(desired);
|
this->store(desired);
|
||||||
return desired;
|
return desired;
|
||||||
}
|
}
|
||||||
Atomic &operator=(const Atomic &) = delete;
|
atomic &operator=(const atomic &) = delete;
|
||||||
private:
|
private:
|
||||||
friend void atomic_init<>(volatile Atomic *obj, typename Atomic::value_type desired) noexcept;
|
friend void atomic_init<>(volatile atomic *obj, typename atomic::value_type desired) noexcept;
|
||||||
friend void atomic_init<>(Atomic *obj, typename Atomic::value_type desired) noexcept;
|
friend void atomic_init<>(atomic *obj, typename atomic::value_type desired) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
using atomic_bool = Atomic<bool>;
|
using atomic_bool = atomic<bool>;
|
||||||
using atomic_char = Atomic<char>;
|
using atomic_char = atomic<char>;
|
||||||
using atomic_schar = Atomic<signed char>;
|
using atomic_schar = atomic<signed char>;
|
||||||
using atomic_uchar = Atomic<unsigned char>;
|
using atomic_uchar = atomic<unsigned char>;
|
||||||
using atomic_char16_t = Atomic<char16_t>;
|
using atomic_char16_t = atomic<char16_t>;
|
||||||
using atomic_char32_t = Atomic<char32_t>;
|
using atomic_char32_t = atomic<char32_t>;
|
||||||
using atomic_wchar_t = Atomic<wchar_t>;
|
using atomic_wchar_t = atomic<wchar_t>;
|
||||||
using atomic_short = Atomic<short>;
|
using atomic_short = atomic<short>;
|
||||||
using atomic_ushort = Atomic<unsigned short>;
|
using atomic_ushort = atomic<unsigned short>;
|
||||||
using atomic_int = Atomic<int>;
|
using atomic_int = atomic<int>;
|
||||||
using atomic_uint = Atomic<unsigned int>;
|
using atomic_uint = atomic<unsigned int>;
|
||||||
using atomic_long = Atomic<long>;
|
using atomic_long = atomic<long>;
|
||||||
using atomic_ulong = Atomic<unsigned long>;
|
using atomic_ulong = atomic<unsigned long>;
|
||||||
using atomic_llong = Atomic<long long>;
|
using atomic_llong = atomic<long long>;
|
||||||
using atomic_ullong = Atomic<unsigned long long>;
|
using atomic_ullong = atomic<unsigned long long>;
|
||||||
using atomic_int8_t = Atomic<int8_t>;
|
using atomic_int8_t = atomic<int8_t>;
|
||||||
using atomic_uint8_t = Atomic<uint8_t>;
|
using atomic_uint8_t = atomic<uint8_t>;
|
||||||
using atomic_int16_t = Atomic<int16_t>;
|
using atomic_int16_t = atomic<int16_t>;
|
||||||
using atomic_uint16_t = Atomic<uint16_t>;
|
using atomic_uint16_t = atomic<uint16_t>;
|
||||||
using atomic_int32_t = Atomic<int32_t>;
|
using atomic_int32_t = atomic<int32_t>;
|
||||||
using atomic_uint32_t = Atomic<uint32_t>;
|
using atomic_uint32_t = atomic<uint32_t>;
|
||||||
using atomic_int64_t = Atomic<int64_t>;
|
using atomic_int64_t = atomic<int64_t>;
|
||||||
using atomic_uint64_t = Atomic<uint64_t>;
|
using atomic_uint64_t = atomic<uint64_t>;
|
||||||
using atomic_int_least8_t = Atomic<int_least8_t>;
|
using atomic_int_least8_t = atomic<int_least8_t>;
|
||||||
using atomic_uint_least8_t = Atomic<uint_least8_t>;
|
using atomic_uint_least8_t = atomic<uint_least8_t>;
|
||||||
using atomic_int_least16_t = Atomic<int_least16_t>;
|
using atomic_int_least16_t = atomic<int_least16_t>;
|
||||||
using atomic_uint_least16_t = Atomic<uint_least16_t>;
|
using atomic_uint_least16_t = atomic<uint_least16_t>;
|
||||||
using atomic_int_least32_t = Atomic<int_least32_t>;
|
using atomic_int_least32_t = atomic<int_least32_t>;
|
||||||
using atomic_uint_least32_t = Atomic<uint_least32_t>;
|
using atomic_uint_least32_t = atomic<uint_least32_t>;
|
||||||
using atomic_int_least64_t = Atomic<int_least64_t>;
|
using atomic_int_least64_t = atomic<int_least64_t>;
|
||||||
using atomic_uint_least64_t = Atomic<uint_least64_t>;
|
using atomic_uint_least64_t = atomic<uint_least64_t>;
|
||||||
using atomic_int_fast8_t = Atomic<int_fast8_t>;
|
using atomic_int_fast8_t = atomic<int_fast8_t>;
|
||||||
using atomic_uint_fast8_t = Atomic<uint_fast8_t>;
|
using atomic_uint_fast8_t = atomic<uint_fast8_t>;
|
||||||
using atomic_int_fast16_t = Atomic<int_fast16_t>;
|
using atomic_int_fast16_t = atomic<int_fast16_t>;
|
||||||
using atomic_uint_fast16_t = Atomic<uint_fast16_t>;
|
using atomic_uint_fast16_t = atomic<uint_fast16_t>;
|
||||||
using atomic_int_fast32_t = Atomic<int_fast32_t>;
|
using atomic_int_fast32_t = atomic<int_fast32_t>;
|
||||||
using atomic_uint_fast32_t = Atomic<uint_fast32_t>;
|
using atomic_uint_fast32_t = atomic<uint_fast32_t>;
|
||||||
using atomic_int_fast64_t = Atomic<int_fast64_t>;
|
using atomic_int_fast64_t = atomic<int_fast64_t>;
|
||||||
using atomic_uint_fast64_t = Atomic<uint_fast64_t>;
|
using atomic_uint_fast64_t = atomic<uint_fast64_t>;
|
||||||
using atomic_intptr_t = Atomic<intptr_t>;
|
using atomic_intptr_t = atomic<intptr_t>;
|
||||||
using atomic_uintptr_t = Atomic<uintptr_t>;
|
using atomic_uintptr_t = atomic<uintptr_t>;
|
||||||
using atomic_size_t = Atomic<size_t>;
|
using atomic_size_t = atomic<size_t>;
|
||||||
using atomic_ptrdiff_t = Atomic<ptrdiff_t>;
|
using atomic_ptrdiff_t = atomic<ptrdiff_t>;
|
||||||
using atomic_intmax_t = Atomic<intmax_t>;
|
using atomic_intmax_t = atomic<intmax_t>;
|
||||||
using atomic_uintmax_t = Atomic<uintmax_t>;
|
using atomic_uintmax_t = atomic<uintmax_t>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_init(Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
void atomic_init(atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
obj->init(desired);
|
obj->init(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_init(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
void atomic_init(volatile atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
obj->init(desired);
|
obj->init(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_is_lock_free(const Atomic<T> *obj) noexcept
|
bool atomic_is_lock_free(const atomic<T> *obj) noexcept
|
||||||
{
|
{
|
||||||
return obj->is_lock_free();
|
return obj->is_lock_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_is_lock_free(const volatile Atomic<T> *obj) noexcept
|
bool atomic_is_lock_free(const volatile atomic<T> *obj) noexcept
|
||||||
{
|
{
|
||||||
return obj->is_lock_free();
|
return obj->is_lock_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_store(Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
void atomic_store(atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
obj->store(desired);
|
obj->store(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_store(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
void atomic_store(volatile atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
obj->store(desired);
|
obj->store(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_store_explicit(Atomic<T> *obj, typename Atomic<T>::value_type desired, memory_order order) noexcept
|
void atomic_store_explicit(atomic<T> *obj, typename atomic<T>::value_type desired, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
obj->store(desired, order);
|
obj->store(desired, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void atomic_store_explicit(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired, memory_order order) noexcept
|
void atomic_store_explicit(volatile atomic<T> *obj, typename atomic<T>::value_type desired, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
obj->store(desired, order);
|
obj->store(desired, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_load(const Atomic<T> *obj) noexcept
|
T atomic_load(const atomic<T> *obj) noexcept
|
||||||
{
|
{
|
||||||
return obj->load();
|
return obj->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_load(const volatile Atomic<T> *obj) noexcept
|
T atomic_load(const volatile atomic<T> *obj) noexcept
|
||||||
{
|
{
|
||||||
return obj->load();
|
return obj->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_load_explicit(const Atomic<T> *obj, memory_order order) noexcept
|
T atomic_load_explicit(const atomic<T> *obj, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->load(order);
|
return obj->load(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_load_explicit(const volatile Atomic<T> *obj, memory_order order) noexcept
|
T atomic_load_explicit(const volatile atomic<T> *obj, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->load(order);
|
return obj->load(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_exchange(Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
T atomic_exchange(atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->exchange(desired);
|
return obj->exchange(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_exchange(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired) noexcept
|
T atomic_exchange(volatile atomic<T> *obj, typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->exchange(desired);
|
return obj->exchange(desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_exchange_explicit(Atomic<T> *obj, typename Atomic<T>::value_type desired, memory_order order) noexcept
|
T atomic_exchange_explicit(atomic<T> *obj, typename atomic<T>::value_type desired, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->exchange(desired, order);
|
return obj->exchange(desired, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_exchange_explicit(volatile Atomic<T> *obj, typename Atomic<T>::value_type desired, memory_order order) noexcept
|
T atomic_exchange_explicit(volatile atomic<T> *obj, typename atomic<T>::value_type desired, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->exchange(desired, order);
|
return obj->exchange(desired, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_weak(Atomic<T> *obj,
|
bool atomic_compare_exchange_weak(atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired) noexcept
|
typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->compare_exchange_weak(obj, *currentExpected, desired);
|
return obj->compare_exchange_weak(obj, *currentExpected, desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_weak(volatile Atomic<T> *obj,
|
bool atomic_compare_exchange_weak(volatile atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired) noexcept
|
typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->compare_exchange_weak(obj, *currentExpected, desired);
|
return obj->compare_exchange_weak(obj, *currentExpected, desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_strong(Atomic<T> *obj,
|
bool atomic_compare_exchange_strong(atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired) noexcept
|
typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->compare_exchange_strong(obj, *currentExpected, desired);
|
return obj->compare_exchange_strong(obj, *currentExpected, desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_strong(volatile Atomic<T> *obj,
|
bool atomic_compare_exchange_strong(volatile atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired) noexcept
|
typename atomic<T>::value_type desired) noexcept
|
||||||
{
|
{
|
||||||
return obj->compare_exchange_strong(obj, *currentExpected, desired);
|
return obj->compare_exchange_strong(obj, *currentExpected, desired);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_weak_explicit(Atomic<T> *obj,
|
bool atomic_compare_exchange_weak_explicit(atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired,
|
typename atomic<T>::value_type desired,
|
||||||
memory_order success,
|
memory_order success,
|
||||||
memory_order failure) noexcept
|
memory_order failure) noexcept
|
||||||
{
|
{
|
||||||
|
@ -985,9 +985,9 @@ bool atomic_compare_exchange_weak_explicit(Atomic<T> *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_weak_explicit(volatile Atomic<T> *obj,
|
bool atomic_compare_exchange_weak_explicit(volatile atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired,
|
typename atomic<T>::value_type desired,
|
||||||
memory_order success,
|
memory_order success,
|
||||||
memory_order failure) noexcept
|
memory_order failure) noexcept
|
||||||
{
|
{
|
||||||
|
@ -995,9 +995,9 @@ bool atomic_compare_exchange_weak_explicit(volatile Atomic<T> *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_strong_explicit(Atomic<T> *obj,
|
bool atomic_compare_exchange_strong_explicit(atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired,
|
typename atomic<T>::value_type desired,
|
||||||
memory_order success,
|
memory_order success,
|
||||||
memory_order failure) noexcept
|
memory_order failure) noexcept
|
||||||
{
|
{
|
||||||
|
@ -1005,9 +1005,9 @@ bool atomic_compare_exchange_strong_explicit(Atomic<T> *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool atomic_compare_exchange_strong_explicit(volatile Atomic<T> *obj,
|
bool atomic_compare_exchange_strong_explicit(volatile atomic<T> *obj,
|
||||||
typename Atomic<T>::value_type *currentExpected,
|
typename atomic<T>::value_type *currentExpected,
|
||||||
typename Atomic<T>::value_type desired,
|
typename atomic<T>::value_type desired,
|
||||||
memory_order success,
|
memory_order success,
|
||||||
memory_order failure) noexcept
|
memory_order failure) noexcept
|
||||||
{
|
{
|
||||||
|
@ -1015,121 +1015,121 @@ bool atomic_compare_exchange_strong_explicit(volatile Atomic<T> *obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_add(Atomic<T> *obj, typename Atomic<T>::difference_type arg) noexcept
|
T atomic_fetch_add(atomic<T> *obj, typename atomic<T>::difference_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_add(arg);
|
return obj->fetch_add(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_add(volatile Atomic<T> *obj, typename Atomic<T>::difference_type arg) noexcept
|
T atomic_fetch_add(volatile atomic<T> *obj, typename atomic<T>::difference_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_add(arg);
|
return obj->fetch_add(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_add_explicit(Atomic<T> *obj, typename Atomic<T>::difference_type arg, memory_order order) noexcept
|
T atomic_fetch_add_explicit(atomic<T> *obj, typename atomic<T>::difference_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_add(arg, order);
|
return obj->fetch_add(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_add_explicit(volatile Atomic<T> *obj, typename Atomic<T>::difference_type arg, memory_order order) noexcept
|
T atomic_fetch_add_explicit(volatile atomic<T> *obj, typename atomic<T>::difference_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_add(arg, order);
|
return obj->fetch_add(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_sub(Atomic<T> *obj, typename Atomic<T>::difference_type arg) noexcept
|
T atomic_fetch_sub(atomic<T> *obj, typename atomic<T>::difference_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_sub(arg);
|
return obj->fetch_sub(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_sub(volatile Atomic<T> *obj, typename Atomic<T>::difference_type arg) noexcept
|
T atomic_fetch_sub(volatile atomic<T> *obj, typename atomic<T>::difference_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_sub(arg);
|
return obj->fetch_sub(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_sub_explicit(Atomic<T> *obj, typename Atomic<T>::difference_type arg, memory_order order) noexcept
|
T atomic_fetch_sub_explicit(atomic<T> *obj, typename atomic<T>::difference_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_sub(arg, order);
|
return obj->fetch_sub(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_sub_explicit(volatile Atomic<T> *obj, typename Atomic<T>::difference_type arg, memory_order order) noexcept
|
T atomic_fetch_sub_explicit(volatile atomic<T> *obj, typename atomic<T>::difference_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_sub(arg, order);
|
return obj->fetch_sub(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_and(Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_and(atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_and(arg);
|
return obj->fetch_and(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_and(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_and(volatile atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_and(arg);
|
return obj->fetch_and(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_and_explicit(Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_and_explicit(atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_and(arg, order);
|
return obj->fetch_and(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_and_explicit(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_and_explicit(volatile atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_and(arg, order);
|
return obj->fetch_and(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_or(Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_or(atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_or(arg);
|
return obj->fetch_or(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_or(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_or(volatile atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_or(arg);
|
return obj->fetch_or(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_or_explicit(Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_or_explicit(atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_or(arg, order);
|
return obj->fetch_or(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_or_explicit(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_or_explicit(volatile atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_or(arg, order);
|
return obj->fetch_or(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_xor(Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_xor(atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_xor(arg);
|
return obj->fetch_xor(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_xor(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg) noexcept
|
T atomic_fetch_xor(volatile atomic<T> *obj, typename atomic<T>::value_type arg) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_xor(arg);
|
return obj->fetch_xor(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_xor_explicit(Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_xor_explicit(atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_xor(arg, order);
|
return obj->fetch_xor(arg, order);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T atomic_fetch_xor_explicit(volatile Atomic<T> *obj, typename Atomic<T>::value_type arg, memory_order order) noexcept
|
T atomic_fetch_xor_explicit(volatile atomic<T> *obj, typename atomic<T>::value_type arg, memory_order order) noexcept
|
||||||
{
|
{
|
||||||
return obj->fetch_xor(arg, order);
|
return obj->fetch_xor(arg, order);
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1207,7 @@ MBED_FORCEINLINE void atomic_flag_clear_explicit(atomic_flag *flag, memory_order
|
||||||
flag->clear(order);
|
flag->clear(order);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MBED_ATOMIC_FLAG_INIT { CORE_UTIL_ATOMIC_FLAG_INIT }
|
#define MSTD_ATOMIC_FLAG_INIT { CORE_UTIL_ATOMIC_FLAG_INIT }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T kill_dependency(T y) noexcept
|
T kill_dependency(T y) noexcept
|
||||||
|
@ -1232,6 +1232,6 @@ MBED_FORCEINLINE void atomic_thread_fence(memory_order order) noexcept
|
||||||
|
|
||||||
/**@}*/
|
/**@}*/
|
||||||
|
|
||||||
} // namespace mbed
|
} // namespace mstd
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1338,7 +1338,7 @@ DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_and)
|
||||||
DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_or)
|
DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_or)
|
||||||
DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_xor)
|
DO_MBED_ATOMIC_OP_U_TEMPLATES(fetch_xor)
|
||||||
|
|
||||||
namespace mbed {
|
namespace mstd {
|
||||||
namespace impl {
|
namespace impl {
|
||||||
|
|
||||||
// Use custom assembler forms for pre-ops where available, else construct from post-ops
|
// Use custom assembler forms for pre-ops where available, else construct from post-ops
|
||||||
|
|
Loading…
Reference in New Issue