Replace amd::Atomic with std::atomic. Remove make_atomic uses by
converting the variable to std::atomic and making sure the memory
order is relaxed when synchronizes-with is not needed.

Delete utils/atomic.hpp.

Change-Id: I0b36db8d604a8510ac6e36b32885fd16a1b8ccfa
Этот коммит содержится в:
Laurent Morichetti
2020-08-28 21:38:05 -07:00
коммит произвёл Saleel Kudchadker
родитель cef70aa8d3
Коммит 5d4b6f74d3
22 изменённых файлов: 46 добавлений и 495 удалений
-1
Просмотреть файл
@@ -19,7 +19,6 @@
THE SOFTWARE. */
#include "device/device.hpp"
#include "thread/atomic.hpp"
#include "thread/monitor.hpp"
#include "utils/options.hpp"
#include "comgrctx.hpp"
+2 -1
Просмотреть файл
@@ -30,6 +30,7 @@
#include "comgrctx.hpp"
#include <algorithm>
#include <atomic>
#include <cstdio>
#include <fstream>
#include <iostream>
@@ -1345,7 +1346,7 @@ bool Program::initBuild(amd::option::Options* options) {
programOptions_ = options;
if (options->oVariables->DumpFlags > 0) {
static amd::Atomic<unsigned> build_num = 0;
static std::atomic<uint> build_num{0};
options->setBuildNo(build_num++);
}
buildLog_.clear();
+2 -1
Просмотреть файл
@@ -37,6 +37,7 @@
#include "device/gpu/gpusettings.hpp"
#include "device/gpu/gpuappprofile.hpp"
#include <atomic>
#include "acl.h"
#include "vaminterface.h"
@@ -316,7 +317,7 @@ class Device : public NullDevice, public CALGSLDevice {
Resource::MemoryType type_; //!< The buffer's type
size_t bufSize_; //!< Staged buffer size
std::list<Memory*> freeBuffers_; //!< The list of free buffers
amd::Atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
std::atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
amd::Monitor lock_; //!< Staged buffer acquire/release lock
const Device& gpuDevice_; //!< GPU device object
};
-1
Просмотреть файл
@@ -22,7 +22,6 @@
#define GPUMEMORY_HPP_
#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/gpu/gpuresource.hpp"
#include <map>
-1
Просмотреть файл
@@ -34,7 +34,6 @@
#include "device/gpu/gpudevice.hpp"
#include "device/gpu/gpublit.hpp"
#include "device/gpu/gputimestamp.hpp"
#include "thread/atomic.hpp"
#include "hsa_ext_image.h"
#include <string>
+3 -1
Просмотреть файл
@@ -25,6 +25,8 @@
#include "platform/program.hpp"
#include "device/gpu/gpudefs.hpp"
#include <atomic>
//! \namespace gpu GPU Resource Implementation
namespace gpu {
@@ -412,7 +414,7 @@ class Resource : public amd::HeapObject {
const Device& gpuDevice_; //!< GPU device
CalResourceDesc cal_; //!< CAL descriptor for this resource
amd::Atomic<int> mapCount_; //!< Total number of maps
std::atomic<int> mapCount_; //!< Total number of maps
void* address_; //!< Physical address of this resource
size_t offset_; //!< Resource offset
size_t curRename_; //!< Current active rename in the list
+2 -1
Просмотреть файл
@@ -39,6 +39,7 @@
#include "acl.h"
#include "memory"
#include <atomic>
#include <unordered_set>
/*! \addtogroup PAL
@@ -258,7 +259,7 @@ class Device : public NullDevice {
Resource::MemoryType type_; //!< The buffer's type
size_t bufSize_; //!< Staged buffer size
std::list<Memory*> freeBuffers_; //!< The list of free buffers
amd::Atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
std:atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
amd::Monitor lock_; //!< Stgaed buffer acquire/release lock
const Device& gpuDevice_; //!< GPU device object
};
-1
Просмотреть файл
@@ -21,7 +21,6 @@
#pragma once
#include "top.hpp"
#include "thread/atomic.hpp"
#include "device/pal/palresource.hpp"
#include <map>
-1
Просмотреть файл
@@ -28,7 +28,6 @@
#include "device/pal/paldevice.hpp"
#include "device/pal/palblit.hpp"
#include "device/pal/paltimestamp.hpp"
#include "thread/atomic.hpp"
#include "hsa_ext_image.h"
#ifdef _WIN32
#include <d3d10_1.h>
+2 -1
Просмотреть файл
@@ -25,6 +25,7 @@
#include "device/pal/paldefs.hpp"
#include "util/palBuddyAllocatorImpl.h"
#include <atomic>
#include <unordered_map>
//! \namespace pal PAL Resource Implementation
@@ -479,7 +480,7 @@ class Resource : public amd::HeapObject {
const Device& gpuDevice_; //!< GPU device
Descriptor desc_; //!< Descriptor for this resource
amd::Atomic<int> mapCount_; //!< Total number of maps
std::atomic<int> mapCount_; //!< Total number of maps
void* address_; //!< Physical address of this resource
size_t offset_; //!< Resource offset
GpuMemoryReference* memRef_; //!< PAL resource reference
+3 -2
Просмотреть файл
@@ -45,6 +45,7 @@
#include "hsa_ext_amd.h"
#include "hsa_ven_amd_loader.h"
#include <atomic>
#include <iostream>
#include <vector>
#include <memory>
@@ -281,7 +282,7 @@ class Device : public NullDevice {
size_t bufSize_; //!< Staged buffer size
std::list<Memory*> freeBuffers_; //!< The list of free buffers
amd::Atomic<uint> acquiredCnt_; //!< The total number of acquired buffers
std::atomic_uint acquiredCnt_; //!< The total number of acquired buffers
amd::Monitor lock_; //!< Stgaed buffer acquire/release lock
const Device& gpuDevice_; //!< GPU device object
};
@@ -535,7 +536,7 @@ class Device : public NullDevice {
std::vector<LinkAttrType>* link_attr);
public:
amd::Atomic<uint> numOfVgpus_; //!< Virtual gpu unique index
std::atomic<uint> numOfVgpus_; //!< Virtual gpu unique index
//! enum for keeping the total and available queue priorities
enum QueuePriority : uint { Low = 0, Normal = 1, High = 2, Total = 3};
+3 -2
Просмотреть файл
@@ -45,6 +45,7 @@
#include <xmmintrin.h>
#endif /*!ATI_ARCH_ARM*/
#include <atomic>
#include <cstdint>
#include <cstddef>
#include <new>
@@ -169,7 +170,7 @@ class HeapObject {
/*! \brief For all reference counted objects.
*/
class ReferenceCountedObject {
volatile uint referenceCount_;
std::atomic<uint> referenceCount_;
protected:
virtual ~ReferenceCountedObject() {}
@@ -185,7 +186,7 @@ class ReferenceCountedObject {
};
void operator delete(void* obj, size_t extSize) { ReferenceCountedObject::operator delete(obj); }
uint referenceCount() const { return referenceCount_; }
uint referenceCount() const { return referenceCount_.load(std::memory_order_relaxed); }
uint retain();
uint release();
+1
Просмотреть файл
@@ -29,6 +29,7 @@
#include <time.h>
#include <intrin.h>
#include <atomic>
#include <vector>
#include <string>
#include <sstream>
+2 -2
Просмотреть файл
@@ -20,12 +20,12 @@
#pragma once
#include "thread/monitor.hpp"
#include <atomic>
#include <mutex>
#include <thread>
#include "thread/monitor.hpp"
#define USE_PROF_API 1
#if USE_PROF_API
+9 -8
Просмотреть файл
@@ -36,6 +36,7 @@
#include "platform/agent.hpp"
#include "os/alloc.hpp"
#include <atomic>
#include <cstring>
#include <algorithm>
@@ -91,7 +92,7 @@ uint64_t epoch = 0;
bool Event::setStatus(int32_t status, uint64_t timeStamp) {
assert(status <= CL_QUEUED && "invalid status");
int32_t currentStatus = status_;
int32_t currentStatus = this->status();
if (currentStatus <= CL_COMPLETE || currentStatus <= status) {
// We can only move forward in the execution status.
return false;
@@ -104,7 +105,7 @@ bool Event::setStatus(int32_t status, uint64_t timeStamp) {
}
}
if (!make_atomic(status_).compareAndSet(currentStatus, status)) {
if (!status_.compare_exchange_strong(currentStatus, status, std::memory_order_relaxed)) {
// Somebody else beat us to it, let them deal with the release/signal.
return false;
}
@@ -154,7 +155,7 @@ bool Event::setCallback(int32_t status, Event::CallBackFunction callback, void*
; // Someone else is also updating the head of the linked list! reload.
// Check if the event has already reached 'status'
if (status_ <= status && entry->callback_ != CallBackFunction(0)) {
if (this->status() <= status && entry->callback_ != CallBackFunction(0)) {
if (entry->callback_.exchange(NULL) != NULL) {
callback(as_cl(this), status, entry->data_);
}
@@ -183,30 +184,30 @@ void Event::processCallbacks(int32_t status) const {
}
bool Event::awaitCompletion() {
if (status_ > CL_COMPLETE) {
if (status() > CL_COMPLETE) {
// Notifies current command queue about waiting
if (!notifyCmdQueue()) {
return false;
}
ClPrint(LOG_DEBUG, LOG_WAIT, "waiting for event %p to complete, current status %d", this, status_);
ClPrint(LOG_DEBUG, LOG_WAIT, "waiting for event %p to complete, current status %d", this, status());
auto* queue = command().queue();
if ((queue != nullptr) && queue->vdev()->ActiveWait()) {
while (status_ > CL_COMPLETE) {
while (status() > CL_COMPLETE) {
amd::Os::yield();
}
} else {
ScopedLock lock(lock_);
// Wait until the status becomes CL_COMPLETE or negative.
while (status_ > CL_COMPLETE) {
while (status() > CL_COMPLETE) {
lock_.wait();
}
}
ClPrint(LOG_DEBUG, LOG_WAIT, "event %p wait completed", this);
}
return status_ == CL_COMPLETE;
return status() == CL_COMPLETE;
}
bool Event::notifyCmdQueue() {
+2 -2
Просмотреть файл
@@ -90,7 +90,7 @@ class Event : public RuntimeObject {
Monitor lock_;
std::atomic<CallBackEntry*> callbacks_; //!< linked list of callback entries.
volatile int32_t status_; //!< current execution status.
std::atomic<int32_t> status_; //!< current execution status.
std::atomic_flag notified_; //!< Command queue was notified
protected:
@@ -163,7 +163,7 @@ class Event : public RuntimeObject {
const ProfilingInfo& profilingInfo() const { return profilingInfo_; }
//! Return this command's execution status.
int32_t status() const { return status_; }
int32_t status() const { return status_.load(std::memory_order_relaxed); }
//! Insert the given \a callback into the callback stack.
bool setCallback(int32_t status, CallBackFunction callback, void* data);
+9 -7
Просмотреть файл
@@ -26,6 +26,8 @@
#include "platform/memory.hpp"
#include "device/device.hpp"
#include <atomic>
namespace amd {
bool BufferRect::create(const size_t* bufferOrigin, const size_t* region, size_t bufferRowPitch,
@@ -277,7 +279,7 @@ bool Memory::create(void* initFrom, bool sysMemAlloc, bool skipAlloc, bool force
// Create memory on all available devices
for (size_t i = 0; i < devices.size(); i++) {
deviceAlloced_[devices[i]] = AllocInit;
deviceAlloced_[devices[i]].store(AllocInit, std::memory_order_relaxed);
deviceMemories_[i].ref_ = devices[i];
deviceMemories_[i].value_ = NULL;
@@ -301,11 +303,11 @@ bool Memory::addDeviceMemory(const Device* dev) {
AllocState create = AllocCreate;
AllocState init = AllocInit;
if (make_atomic(deviceAlloced_[dev]).compareAndSet(init, create)) {
if (deviceAlloced_[dev].compare_exchange_strong(init, create, std::memory_order_acq_rel)) {
// Check if runtime already allocated all available slots for device memory
if (numDevices() == NumDevicesWithP2P()) {
// Mark the allocation as an empty
deviceAlloced_[dev] = AllocInit;
deviceAlloced_[dev].store(AllocInit, std::memory_order_release);
return false;
}
device::Memory* dm = dev->createMemory(*this);
@@ -325,17 +327,17 @@ bool Memory::addDeviceMemory(const Device* dev) {
} else {
LogError("Video memory allocation failed!");
// Mark the allocation as an empty
deviceAlloced_[dev] = AllocInit;
deviceAlloced_[dev].store(AllocInit, std::memory_order_release);
}
}
// Make sure runtime finished memory allocation.
// Loop if in the create state
while (deviceAlloced_[dev] == AllocCreate) {
while (deviceAlloced_[dev].load(std::memory_order_acquire) == AllocCreate) {
Os::yield();
}
if (deviceAlloced_[dev] == AllocComplete) {
if (deviceAlloced_[dev].load(std::memory_order_acquire) == AllocComplete) {
result = true;
}
@@ -357,7 +359,7 @@ void Memory::replaceDeviceMemory(const Device* dev, device::Memory* dm) {
}
deviceMemories_[i].value_ = dm;
deviceAlloced_[dev] = AllocRealloced;
deviceAlloced_[dev].store(AllocRealloced, std::memory_order_release);
}
device::Memory* Memory::getDeviceMemory(const Device& dev, bool alloc) {
+1 -1
Просмотреть файл
@@ -146,7 +146,7 @@ class Memory : public amd::RuntimeObject {
DeviceMemory* deviceMemories_;
//! The device alloced state
std::unordered_map<const Device*, AllocState> deviceAlloced_;
std::unordered_map<const Device*, std::atomic<AllocState>> deviceAlloced_;
//! Linked list of destructor callbacks.
std::atomic<DestructorCallBackEntry*> destructorCallbacks_;
+4 -2
Просмотреть файл
@@ -102,10 +102,12 @@ public:
~RuntimeTearDown() { /*Runtime::tearDown();*/ }
} runtime_tear_down;
uint ReferenceCountedObject::retain() { return ++make_atomic(referenceCount_); }
uint ReferenceCountedObject::retain() {
return referenceCount_.fetch_add(1, std::memory_order_relaxed) + 1;
}
uint ReferenceCountedObject::release() {
uint newCount = --make_atomic(referenceCount_);
uint newCount = referenceCount_.fetch_sub(1, std::memory_order_relaxed) - 1;
if (newCount == 0) {
if (terminate()) {
delete this;
-457
Просмотреть файл
@@ -1,457 +0,0 @@
/* Copyright (c) 2009-present Advanced Micro Devices, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. */
/*! \file atomic.hpp
* \brief Declarations for Memory order access and Atomic operations.
*
* \author Laurent Morichetti
* \date October 2008
*/
#ifndef ATOMIC_HPP_
#define ATOMIC_HPP_
#include "top.hpp"
#include <type_traits>
#ifdef _WIN32
#include <intrin.h>
#elif defined(ATI_ARCH_X86)
#include <emmintrin.h>
#include <xmmintrin.h>
#endif // !_WIN32
#include <atomic>
#include <utility>
namespace amd {
/*! \addtogroup Threads
* @{
*
* \addtogroup Atomic Atomic Operations
* @{
*/
/*! \brief Static functions for atomic operations.
*/
class AtomicOperation : AllStatic {
private:
//! Template to specialize atomic intrinsics on register size.
template <int N> struct Intrinsics {
/*! \brief %Atomic add.
*
* Atomically add \a inc to \a *dest and return the prior value.
*/
template <typename T> static inline T add(T increment, volatile T* dest);
/*! \brief %Atomic exchange.
*
* Atomically exchange value with *dest and return the prior value.
*/
template <typename T> static inline T swap(T value, volatile T* dest);
/*! \brief %Atomic compare and exchange.
*
* Atomically compare and xchge value with *dest if *dest == compare.
* Return the prior value.
*/
template <typename T> static inline T compareAndSwap(T compare, volatile T* dest, T value);
/*! \brief %Atomic increment.
*
* Atomically increment *dest and return the prior value.
*/
template <typename T> static inline T increment(volatile T* dest);
/*! \brief %Atomic exchange.
*
* Atomically decrement *dest and return the prior value.
*/
template <typename T> static inline T decrement(volatile T* dest);
/*! \brief %Atomic or.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T> static inline T _or(T mask, volatile T* dest);
/*! \brief %Atomic and.
*
* Atomically and \a mask to \a *dest and return the prior value.
*/
template <typename T> static inline T _and(T mask, volatile T* dest);
};
public:
/*! \brief %Atomic add.
*
* Atomically add \a inc to \a *dest and return the prior value.
*/
template <typename T> static T add(T inc, volatile T* dest) {
return Intrinsics<sizeof(T)>::add((T)inc, dest);
}
/*! \brief %Atomic exchange.
*
* Atomically exchange value with *dest and return the prior value.
*/
template <typename T> static T swap(T value, volatile T* dest) {
return Intrinsics<sizeof(T)>::swap(value, dest);
}
/*! \brief %Atomic compare and exchange.
*
* Atomically compare and exchange value with *dest if *dest == compare.
* Return the prior value.
*/
template <typename T> static T compareAndSwap(T compare, volatile T* dest, T value) {
return Intrinsics<sizeof(T)>::compareAndSwap(compare, dest, value);
}
/*! \brief %Atomic increment.
*
* Atomically increment *dest and return the prior value.
*/
template <typename T> static T increment(volatile T* dest) {
return Intrinsics<sizeof(T)>::increment(dest);
}
/*! \brief %Atomic decrement.
*
* Atomically decrement *dest and return the prior value.
*/
template <typename T> static T decrement(volatile T* dest) {
return Intrinsics<sizeof(T)>::decrement(dest);
}
/*! \brief %Atomic or.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T> static T _or(T mask, volatile T* dest) {
return Intrinsics<sizeof(T)>::_or((T)mask, dest);
}
/*! \brief %Atomic and.
*
* Atomically or \a mask to \a *dest and return the prior value.
*/
template <typename T> static T _and(T mask, volatile T* dest) {
return Intrinsics<sizeof(T)>::_and((T)mask, dest);
}
};
/*@}*/
#if defined(_MSC_VER)
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::add(T increment, volatile T* dest) {
return (T)_InterlockedExchangeAdd((volatile long*)dest, (long)increment);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::swap(T value, volatile T* dest) {
return (T)_InterlockedExchange((volatile long*)dest, (long)value);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::compareAndSwap(T compare, volatile T* dest, T value) {
return (T)_InterlockedCompareExchange((volatile long*)dest, (long)value, (long)compare);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::increment(volatile T* dest) {
return (T)(_InterlockedIncrement((volatile long*)dest) - 1L);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::decrement(volatile T* dest) {
return (T)(_InterlockedDecrement((volatile long*)dest) + 1L);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::_or(T mask, volatile T* dest) {
return (T)_InterlockedOr((volatile long*)dest, (long)mask);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<4>::_and(T mask, volatile T* dest) {
return (T)_InterlockedAnd((volatile long*)dest, (long)mask);
}
#ifdef _WIN64
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::add(T increment, volatile T* dest) {
return (T)_InterlockedExchangeAdd64((volatile __int64*)dest, (__int64)increment);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::swap(T value, volatile T* dest) {
return (T)_InterlockedExchange64((volatile __int64*)dest, (__int64)value);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::compareAndSwap(T compare, volatile T* dest, T value) {
return (T)_InterlockedCompareExchange64((volatile __int64*)dest, (__int64)value,
(__int64)compare);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::increment(volatile T* dest) {
return (T)(_InterlockedIncrement64((volatile __int64*)dest) - 1LL);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::decrement(volatile T* dest) {
return (T)(_InterlockedDecrement64((volatile __int64*)dest) + 1LL);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::_or(T mask, volatile T* dest) {
return (T)_InterlockedOr64((volatile long*)dest, (long)mask);
}
template <>
template <typename T>
inline T AtomicOperation::Intrinsics<8>::_and(T mask, volatile T* dest) {
return (T)_InterlockedAnd64((volatile long*)dest, (long)mask);
}
#endif // _LP64
#elif defined(__GNUC__)
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::add(T inc, volatile T* dest) {
return __sync_fetch_and_add(dest, inc);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::swap(T value, volatile T* dest) {
return __sync_lock_test_and_set(dest, value);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::compareAndSwap(T compare, volatile T* dest, T value) {
return __sync_val_compare_and_swap(dest, compare, value);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::increment(volatile T* dest) {
return add(T(1), dest);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::decrement(volatile T* dest) {
return add(T(-1), dest);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::_or(T mask, volatile T* dest) {
return __sync_fetch_and_or(dest, mask);
}
template <int N>
template <typename T>
inline T AtomicOperation::Intrinsics<N>::_and(T mask, volatile T* dest) {
return __sync_fetch_and_and(dest, mask);
}
#else
#error Unimplemented
#endif
/*! \addtogroup Atomic Atomic Operations
* @{
*/
/*! \brief A variable of type T with atomic properties.
*/
template <typename T> class Atomic {
private:
typedef typename std::remove_volatile<
typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type value_type;
typename std::add_volatile<T>::type value_; //!< \brief The variable.
public:
//! Construct a new %Atomic variable of type T.
Atomic() : value_(T(0)) {}
//! Construct a new %Atomic variable of type T from \a value.
Atomic(T value) : value_(value) {}
//! Construct a new %Atomic variable of type T from another %Atomic.
Atomic(const Atomic<T>& atomic) : value_(atomic.value_) {}
//! Copy value into this %Atomic variable.
Atomic<T>& operator=(T value) {
value_ = value;
return *this;
}
//! Return the %Atomic variable value.
operator T() const { return T(value_); }
//! Return the %Atomic variable value.
T operator->() const { return T(value_); }
//! Return the %Atomic variable's address.
typename std::add_pointer<typename std::add_volatile<value_type>::type>::type operator&() {
return &value_;
}
//! Atomically add \a inc to this variable.
Atomic<T>& operator+=(value_type inc) {
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(inc, &value_);
return *this;
}
//! Atomically subtract \a inc to this variable.
Atomic<T>& operator-=(value_type inc) {
value_type modifier = 0;
if (std::is_pointer<T>::value) {
inc *= sizeof(typename std::remove_pointer<T>::type);
}
AtomicOperation::add(modifier - inc, &value_);
return *this;
}
//! Atomically OR \a value to this variable.
Atomic<T>& operator|=(value_type mask) {
AtomicOperation::_or(mask, &value_);
return *this;
}
//! Atomically AND \a value to this variable.
Atomic<T>& operator&=(value_type mask) {
AtomicOperation::_and(mask, &value_);
return *this;
}
//! Atomically increment this variable and return its new value.
typename std::remove_reference<T>::type operator++() {
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_) + 1;
} else {
return AtomicOperation::increment(&value_) + 1;
}
}
//! Atomically decrement this variable and return its new value.
typename std::remove_reference<T>::type operator--() {
if (std::is_pointer<T>::value) {
value_type inc =
static_cast<value_type>(-static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_) - 1;
} else {
return AtomicOperation::decrement(&value_) - 1;
}
}
//! Atomically increment this variable and return its previous value.
typename std::remove_reference<T>::type operator++(int) {
if (std::is_pointer<T>::value) {
value_type inc = static_cast<value_type>(sizeof(typename std::remove_pointer<T>::type));
return AtomicOperation::add(inc, &value_);
} else {
return AtomicOperation::increment(&value_);
}
}
//! Atomically decrement this variable and return its previous value.
T operator--(int) {
if (std::is_pointer<T>::value) {
value_type inc =
static_cast<value_type>(-static_cast<typename std::make_signed<value_type>::type>(
sizeof(typename std::remove_pointer<T>::type)));
return AtomicOperation::add(inc, &value_);
} else {
return AtomicOperation::decrement(&value_);
}
}
/*! \brief Atomically compare this variable with \a compare and set
* to value if equals
*/
bool compareAndSet(T compare, T value) {
return compare == AtomicOperation::compareAndSwap(compare, &value_, value);
}
//! Atomically set this variable to \a value and return its previous value.
T swap(T value) { return AtomicOperation::swap(value, &value_); }
/*! \brief Execute a stores fence followed by a store to this variable.
*
* This storeRelease operation ensures that all store to memory operations
* preceding this function will be globally visible before the update to
* this variable's value.
*/
void storeRelease(T value) {
std::atomic_thread_fence(std::memory_order_release);
value_ = value;
}
/*! \brief Execute a load from this variable followed by a loads fence.
*
* This loadAcquire operation ensures that all load from memory operations
* following this function will be globally visible after the read from
* this variable's value.
*/
T loadAcquire() const {
T value = value_;
std::atomic_thread_fence(std::memory_order_acquire);
return value;
}
};
//! Helper function to tie an Atomic<T&> to a variable of type T.
template <typename T> inline Atomic<T&> make_atomic(T& t) { return Atomic<T&>(t); }
/*! @}
* @}
*/
} // namespace amd
#endif /*ATOMIC_HPP_*/
+1 -1
Просмотреть файл
@@ -19,11 +19,11 @@
THE SOFTWARE. */
#include "thread/monitor.hpp"
#include "thread/atomic.hpp"
#include "thread/semaphore.hpp"
#include "thread/thread.hpp"
#include "utils/util.hpp"
#include <atomic>
#include <cstring>
#include <tuple>
#include <utility>
-1
Просмотреть файл
@@ -22,7 +22,6 @@
#define MONITOR_HPP_
#include "top.hpp"
#include "thread/atomic.hpp"
#include "thread/semaphore.hpp"
#include "thread/thread.hpp"