Deprecate AtomicInterfaceControl and AtomicInterfaceExecution

Now that we have the functions in `vtkm/Atomic.h`, we can deprecate (and
eventually remove) the more cumbersome classes `AtomicInterfaceControl`
and `AtomicInterfaceExecution`.

Also reversed the order of the `expected` and `desired` parameters of
`vtkm::AtomicCompareAndSwap`. I think the former order makes more sense
and matches more other implementations (such as `std::atomic` and the
GCC `__atomic` built ins). However, there are still some non-deprecated
classes with similar methods that cannot easily be switched. Thus, it's
better to be inconsistent with most other libraries and consistent with
ourself than to be inconsitent with ourself.
This commit is contained in:
Kenneth Moreland 2020-08-19 15:44:11 -06:00
parent 82d6ca9854
commit 13056b3af5
11 changed files with 84 additions and 98 deletions

@ -87,7 +87,7 @@ VTKM_EXEC_CONT inline T AtomicNotImpl(T* addr)
}
template <typename T>
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T expected, T desired)
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T desired, T expected)
{
return Kokkos::atomic_compare_exchange(addr, expected, desired);
}
@ -163,7 +163,7 @@ VTKM_EXEC_CONT inline T AtomicNotImpl(T* addr)
}
template <typename T>
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T expected, T desired)
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T desired, T expected)
{
__threadfence();
auto result = atomicCAS(addr, expected, desired);
@ -300,7 +300,7 @@ VTKM_EXEC_CONT inline void AtomicStoreImpl(vtkm::UInt64* addr, vtkm::UInt64 val)
return AtomicXorImpl(addr, static_cast<vtkmType>(~vtkmType{ 0u })); \
} \
VTKM_EXEC_CONT inline vtkmType AtomicCompareAndSwapImpl( \
vtkmType* addr, vtkmType expected, vtkmType desired) \
vtkmType* addr, vtkmType desired, vtkmType expected) \
{ \
return BitCast<vtkmType>( \
_InterlockedCompareExchange##suffix(reinterpret_cast<volatile winType*>(addr), \
@ -373,7 +373,7 @@ VTKM_EXEC_CONT inline T AtomicNotImpl(T* addr)
}
template <typename T>
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T expected, T desired)
VTKM_EXEC_CONT inline T AtomicCompareAndSwapImpl(T* addr, T desired, T expected)
{
__atomic_compare_exchange_n(addr, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
@ -512,7 +512,7 @@ VTKM_EXEC_CONT inline T AtomicNot(T* pointer)
/// \brief Atomic function that replaces a value given a condition.
///
/// Given a pointer, an expected value, and a new desired value, replaces the value at the
/// Given a pointer, a new desired value, and an expected value, replaces the value at the
/// pointer if it is the same as the expected value with the new desired value. If the original
/// value in the pointer does not equal the expected value, then the memory at the pointer
/// remains unchanged. In either case, the function returns the _old_ original value that
@ -523,10 +523,10 @@ VTKM_EXEC_CONT inline T AtomicNot(T* pointer)
/// first).
///
template <typename T, typename U, typename V>
VTKM_EXEC_CONT inline T AtomicCompareAndSwap(T* pointer, U expected, V desired)
VTKM_EXEC_CONT inline T AtomicCompareAndSwap(T* pointer, V desired, U expected)
{
return detail::AtomicCompareAndSwapImpl(
pointer, static_cast<T>(expected), static_cast<V>(desired));
pointer, static_cast<V>(desired), static_cast<T>(expected));
}
} // namespace vtkm

@ -65,9 +65,8 @@ struct VTKM_ALWAYS_EXPORT StorageTagBitField
template <>
class Storage<bool, StorageTagBitField>
{
using BitPortalType = vtkm::cont::detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
using BitPortalConstType =
vtkm::cont::detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
using BitPortalType = vtkm::cont::detail::BitPortal;
using BitPortalConstType = vtkm::cont::detail::BitPortalConst;
public:
using ValueType = bool;
@ -107,10 +106,9 @@ private:
template <typename Device>
class ArrayTransfer<bool, StorageTagBitField, Device>
{
using AtomicInterface = AtomicInterfaceExecution<Device>;
using StorageType = Storage<bool, StorageTagBitField>;
using BitPortalExecution = vtkm::cont::detail::BitPortal<AtomicInterface>;
using BitPortalConstExecution = vtkm::cont::detail::BitPortalConst<AtomicInterface>;
using BitPortalExecution = vtkm::cont::detail::BitPortal;
using BitPortalConstExecution = vtkm::cont::detail::BitPortalConst;
public:
using ValueType = bool;

@ -11,12 +11,10 @@
#ifndef vtk_m_cont_BitField_h
#define vtk_m_cont_BitField_h
#include <vtkm/cont/internal/AtomicInterfaceControl.h>
#include <vtkm/cont/internal/AtomicInterfaceExecution.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/Atomic.h>
#include <vtkm/Deprecated.h>
#include <vtkm/List.h>
#include <vtkm/Types.h>
@ -61,7 +59,7 @@ struct BitFieldTraits
/// Require an unsigned integral type that is <= BlockSize bytes, and is
/// is supported by the specified AtomicInterface.
template <typename WordType, typename AtomicInterface>
template <typename WordType>
using IsValidWordTypeAtomic =
std::integral_constant<bool,
/* is unsigned */
@ -71,7 +69,7 @@ struct BitFieldTraits
/* BlockSize is a multiple of WordType */
static_cast<size_t>(BlockSize) % sizeof(WordType) == 0 &&
/* Supported by atomic interface */
vtkm::ListHas<typename AtomicInterface::WordTypes, WordType>::value>;
vtkm::ListHas<vtkm::AtomicTypesSupported, WordType>::value>;
};
/// Identifies a bit in a BitField by Word and BitOffset. Note that these
@ -88,7 +86,7 @@ struct BitCoordinate
/// Portal for performing bit or word operations on a BitField.
///
/// This is the implementation used by BitPortal and BitPortalConst.
template <typename AtomicInterface_, bool IsConst>
template <bool IsConst>
class BitPortalBase
{
// Checks if PortalType has a GetIteratorBegin() method that returns a
@ -105,12 +103,8 @@ class BitPortalBase
using BufferType = MaybeConstPointer<void>; // void* or void const*, as appropriate
public:
/// The atomic interface used to carry out atomic operations. See
/// AtomicInterfaceExecution<Device> and AtomicInterfaceControl
using AtomicInterface = AtomicInterface_;
/// The fastest word type for performing bitwise operations through AtomicInterface.
using WordTypePreferred = typename AtomicInterface::WordTypePreferred;
using WordTypePreferred = vtkm::AtomicTypePreferred;
/// MPL check for whether a WordType may be used for non-atomic operations.
template <typename WordType>
@ -118,7 +112,7 @@ public:
/// MPL check for whether a WordType may be used for atomic operations.
template <typename WordType>
using IsValidWordTypeAtomic = BitFieldTraits::IsValidWordTypeAtomic<WordType, AtomicInterface>;
using IsValidWordTypeAtomic = BitFieldTraits::IsValidWordTypeAtomic<WordType>;
VTKM_STATIC_ASSERT_MSG(IsValidWordType<WordTypeDefault>::value,
"Internal error: Default word type is invalid.");
@ -281,7 +275,7 @@ public:
VTKM_STATIC_ASSERT_MSG(IsValidWordTypeAtomic<WordType>::value,
"Requested WordType does not support atomic"
" operations on target execution platform.");
AtomicInterface::Store(this->GetWordAddress<WordType>(wordIdx), word);
vtkm::AtomicStore(this->GetWordAddress<WordType>(wordIdx), word);
}
/// Get the word (of type @a WordType) at @a wordIdx using non-atomic
@ -300,7 +294,7 @@ public:
VTKM_STATIC_ASSERT_MSG(IsValidWordTypeAtomic<WordType>::value,
"Requested WordType does not support atomic"
" operations on target execution platform.");
return AtomicInterface::Load(this->GetWordAddress<WordType>(wordIdx));
return vtkm::AtomicLoad(this->GetWordAddress<WordType>(wordIdx));
}
/// Toggle the bit at @a bitIdx, returning the original value. This method
@ -326,7 +320,7 @@ public:
"Requested WordType does not support atomic"
" operations on target execution platform.");
WordType* addr = this->GetWordAddress<WordType>(wordIdx);
return AtomicInterface::Not(addr);
return vtkm::AtomicNot(addr);
}
/// Perform an "and" operation between the bit at @a bitIdx and @a val,
@ -356,7 +350,7 @@ public:
"Requested WordType does not support atomic"
" operations on target execution platform.");
WordType* addr = this->GetWordAddress<WordType>(wordIdx);
return AtomicInterface::And(addr, wordmask);
return vtkm::AtomicAnd(addr, wordmask);
}
/// Perform an "of" operation between the bit at @a bitIdx and @a val,
@ -386,7 +380,7 @@ public:
"Requested WordType does not support atomic"
" operations on target execution platform.");
WordType* addr = this->GetWordAddress<WordType>(wordIdx);
return AtomicInterface::Or(addr, wordmask);
return vtkm::AtomicOr(addr, wordmask);
}
/// Perform an "xor" operation between the bit at @a bitIdx and @a val,
@ -416,7 +410,7 @@ public:
"Requested WordType does not support atomic"
" operations on target execution platform.");
WordType* addr = this->GetWordAddress<WordType>(wordIdx);
return AtomicInterface::Xor(addr, wordmask);
return vtkm::AtomicXor(addr, wordmask);
}
/// Perform an atomic compare-and-swap operation on the bit at @a bitIdx.
@ -469,7 +463,7 @@ public:
"Requested WordType does not support atomic"
" operations on target execution platform.");
WordType* addr = this->GetWordAddress<WordType>(wordIdx);
return AtomicInterface::CompareAndSwap(addr, newWord, expected);
return vtkm::AtomicCompareAndSwap(addr, newWord, expected);
}
private:
@ -484,11 +478,24 @@ private:
vtkm::Id NumberOfBits{ 0 };
};
template <typename AtomicOps>
using BitPortal = BitPortalBase<AtomicOps, false>;
using BitPortal = BitPortalBase<false>;
template <typename AtomicOps>
using BitPortalConst = BitPortalBase<AtomicOps, true>;
using BitPortalConst = BitPortalBase<true>;
template <typename WordType, typename Device>
struct IsValidWordTypeDeprecated
{
using type VTKM_DEPRECATED(
1.6,
"BitField::IsValidWordTypeAtomic no longer takes a second Device parameter.") =
detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
};
template <typename WordType>
struct IsValidWordTypeDeprecated<WordType, void>
{
using type = detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
};
} // end namespace detail
@ -501,48 +508,42 @@ public:
using ArrayHandleType = ArrayHandle<WordTypeDefault, StorageTagBasic>;
/// The BitPortal used in the control environment.
using WritePortalType = detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
using WritePortalType = detail::BitPortal;
/// A read-only BitPortal used in the control environment.
using ReadPortalType = detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
using ReadPortalType = detail::BitPortalConst;
using PortalControl VTKM_DEPRECATED(1.6, "Use BitField::WritePortalType instead.") =
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>;
using PortalControl VTKM_DEPRECATED(1.6,
"Use BitField::WritePortalType instead.") = detail::BitPortal;
using PortalConstControl VTKM_DEPRECATED(1.6, "Use ArrayBitField::ReadPortalType instead.") =
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>;
detail::BitPortalConst;
template <typename Device>
struct ExecutionTypes
{
/// The AtomicInterfaceExecution implementation used by the specified device.
using AtomicInterface = vtkm::cont::internal::AtomicInterfaceExecution<Device>;
/// The preferred word type used by the specified device.
using WordTypePreferred = typename AtomicInterface::WordTypePreferred;
using WordTypePreferred = vtkm::AtomicTypePreferred;
/// A BitPortal that is usable on the specified device.
using Portal = detail::BitPortal<AtomicInterface>;
using Portal = detail::BitPortal;
/// A read-only BitPortal that is usable on the specified device.
using PortalConst = detail::BitPortalConst<AtomicInterface>;
using PortalConst = detail::BitPortalConst;
};
/// Check whether a word type is valid for non-atomic operations.
template <typename WordType>
using IsValidWordType = detail::BitFieldTraits::IsValidWordType<WordType>;
/// Check whether a word type is valid for atomic operations on a specific
/// device.
template <typename WordType, typename Device>
using IsValidWordTypeAtomic = detail::BitFieldTraits::
IsValidWordTypeAtomic<WordType, vtkm::cont::internal::AtomicInterfaceExecution<Device>>;
/// Check whether a word type is valid for atomic operations.
template <typename WordType, typename Device = void>
using IsValidWordTypeAtomic = detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
/// Check whether a word type is valid for atomic operations from the control
/// environment.
template <typename WordType>
using IsValidWordTypeAtomicControl =
detail::BitFieldTraits::IsValidWordTypeAtomic<WordType,
vtkm::cont::internal::AtomicInterfaceControl>;
using IsValidWordTypeAtomicControl VTKM_DEPRECATED(1.6, "Use IsValidWordTypeAtomic instead.") =
detail::BitFieldTraits::IsValidWordTypeAtomic<WordType>;
VTKM_CONT BitField()
: Internals{ std::make_shared<InternalStruct>() }
@ -652,11 +653,9 @@ public:
VTKM_DEPRECATED(1.6,
"Use BitField::WritePortal() instead. "
"Note that the returned portal will lock the array while it is in scope.")
detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl> GetPortalControl()
detail::BitPortal GetPortalControl()
{
return detail::BitPortal<vtkm::cont::internal::AtomicInterfaceControl>{
this->Internals->Data.WritePortal(), this->Internals->NumberOfBits
};
return detail::BitPortal{ this->Internals->Data.WritePortal(), this->Internals->NumberOfBits };
}
/// Get a read-only portal to the data that is usable from the control
@ -665,11 +664,10 @@ public:
VTKM_DEPRECATED(1.6,
"Use BitField::ReadPortal() instead. "
"Note that the returned portal will lock the array while it is in scope.")
detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl> GetPortalConstControl() const
detail::BitPortalConst GetPortalConstControl() const
{
return detail::BitPortalConst<vtkm::cont::internal::AtomicInterfaceControl>{
this->Internals->Data.ReadPortal(), this->Internals->NumberOfBits
};
return detail::BitPortalConst{ this->Internals->Data.ReadPortal(),
this->Internals->NumberOfBits };
}
/// Prepares this BitField to be used as an input to an operation in the

@ -245,8 +245,7 @@ private:
//Using typename BitsPortal::WordTypePreferred causes dependent type errors using GCC 4.8.5
//which is the GCC required compiler for CUDA 9.2 on summit/power9
using Word = typename vtkm::cont::internal::AtomicInterfaceExecution<
DeviceAdapterTagCuda>::WordTypePreferred;
using Word = vtkm::AtomicTypePreferred;
VTKM_STATIC_ASSERT(
VTKM_PASS_COMMAS(std::is_same<typename IndicesPortal::ValueType, vtkm::Id>::value));
@ -458,8 +457,7 @@ private:
//Using typename BitsPortal::WordTypePreferred causes dependent type errors using GCC 4.8.5
//which is the GCC required compiler for CUDA 9.2 on summit/power9
using Word = typename vtkm::cont::internal::AtomicInterfaceExecution<
DeviceAdapterTagCuda>::WordTypePreferred;
using Word = vtkm::AtomicTypePreferred;
VTKM_CONT
CountSetBitsFunctor(const BitsPortal& portal, GlobalPopCountType* globalPopCount)

@ -11,6 +11,7 @@
#define vtk_m_cont_internal_AtomicInterfaceControl_h
#include <vtkm/Atomic.h>
#include <vtkm/Deprecated.h>
namespace vtkm
{
@ -19,7 +20,7 @@ namespace cont
namespace internal
{
struct AtomicInterfaceControl
struct VTKM_DEPRECATED(1.6, "Use the functions in vtkm/Atomic.h.") AtomicInterfaceControl
{
using WordTypes = vtkm::AtomicTypesSupported;
using WordTypePreferred = vtkm::AtomicTypePreferred;
@ -69,7 +70,7 @@ struct AtomicInterfaceControl
template <typename T>
VTKM_EXEC_CONT static T CompareAndSwap(T* addr, T newWord, T expected)
{
return vtkm::AtomicCompareAndSwap(addr, expected, newWord);
return vtkm::AtomicCompareAndSwap(addr, newWord, expected);
}
};
}

@ -11,6 +11,7 @@
#define vtk_m_cont_internal_AtomicInterfaceExecution_h
#include <vtkm/Atomic.h>
#include <vtkm/Deprecated.h>
namespace vtkm
{
@ -20,7 +21,7 @@ namespace internal
{
template <typename DeviceTag>
struct AtomicInterfaceExecution
struct VTKM_DEPRECATED(1.6, "Use the functions in vtkm/Atomic.h.") AtomicInterfaceExecution
{
using WordTypes = vtkm::AtomicTypesSupported;
using WordTypePreferred = vtkm::AtomicTypePreferred;
@ -70,7 +71,7 @@ struct AtomicInterfaceExecution
template <typename T>
VTKM_EXEC_CONT static T CompareAndSwap(T* addr, T newWord, T expected)
{
return vtkm::AtomicCompareAndSwap(addr, expected, newWord);
return vtkm::AtomicCompareAndSwap(addr, newWord, expected);
}
};
}

@ -15,7 +15,6 @@
#include <vtkm/TypeTraits.h>
#include <vtkm/UnaryPredicates.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/internal/AtomicInterfaceExecution.h>
#include <vtkm/exec/FunctorBase.h>

@ -100,10 +100,8 @@ template <class DeviceAdapterTag>
struct TestingBitField
{
using Algo = vtkm::cont::DeviceAdapterAlgorithm<DeviceAdapterTag>;
using AtomicInterface = vtkm::cont::internal::AtomicInterfaceExecution<DeviceAdapterTag>;
using Traits = vtkm::cont::detail::BitFieldTraits;
using WordTypes = typename AtomicInterface::WordTypes;
using WordTypesControl = vtkm::cont::internal::AtomicInterfaceControl::WordTypes;
using WordTypes = vtkm::AtomicTypesSupported;
VTKM_EXEC_CONT
static bool RandomBitFromIndex(vtkm::Id idx) noexcept
@ -314,7 +312,7 @@ struct TestingBitField
}
HelpTestWordOpsControl<Portal> test(portal);
vtkm::ListForEach(test, typename Portal::AtomicInterface::WordTypes{});
vtkm::ListForEach(test, vtkm::AtomicTypesSupported{});
}
VTKM_CONT
@ -423,7 +421,7 @@ struct TestingBitField
HelpTestWordOpsExecution<Portal> test(portal);
vtkm::ListForEach(test, typename Portal::AtomicInterface::WordTypes{});
vtkm::ListForEach(test, vtkm::AtomicTypesSupported{});
}
VTKM_CONT

@ -17,8 +17,6 @@
// this one.
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/internal/AtomicInterfaceControl.h>
#include <vtkm/cont/internal/AtomicInterfaceExecution.h>
#include <vtkm/cont/internal/DeviceAdapterAlgorithmGeneral.h>
#include <vtkm/cont/internal/VirtualObjectTransferShareWithControl.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>

@ -10,10 +10,10 @@
#ifndef vtk_m_exec_AtomicArrayExecutionObject_h
#define vtk_m_exec_AtomicArrayExecutionObject_h
#include <vtkm/Atomic.h>
#include <vtkm/List.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/internal/AtomicInterfaceExecution.h>
#include <type_traits>
@ -25,7 +25,7 @@ namespace exec
namespace detail
{
// Clang-7 as host compiler under nvcc returns types from std::make_unsigned
// that are not compatible with the AtomicInterface API, so we define our own
// that are not compatible with the vtkm::Atomic API, so we define our own
// mapping. This must exist for every entry in vtkm::cont::AtomicArrayTypeList.
template <typename>
struct MakeUnsigned;
@ -54,8 +54,6 @@ struct MakeUnsigned<vtkm::Int64>
template <typename T, typename Device>
class AtomicArrayExecutionObject
{
using AtomicInterface = vtkm::cont::internal::AtomicInterfaceExecution<Device>;
// Checks if PortalType has a GetIteratorBegin() method that returns a
// pointer.
template <typename PortalType,
@ -103,13 +101,12 @@ public:
VTKM_EXEC
ValueType Get(vtkm::Id index) const
{
// We only support 32/64 bit signed/unsigned ints, and AtomicInterface
// We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
// currently only provides API for unsigned types.
// We'll cast the signed types to unsigned to work around this.
using APIType = typename detail::MakeUnsigned<ValueType>::type;
return static_cast<T>(
AtomicInterface::Load(reinterpret_cast<const APIType*>(this->Data + index)));
return static_cast<T>(vtkm::AtomicLoad(reinterpret_cast<const APIType*>(this->Data + index)));
}
/// \brief Peform an atomic addition with sequentially consistent memory
@ -123,7 +120,7 @@ public:
VTKM_EXEC
ValueType Add(vtkm::Id index, const ValueType& value) const
{
// We only support 32/64 bit signed/unsigned ints, and AtomicInterface
// We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
// currently only provides API for unsigned types.
// We'll cast the signed types to unsigned to work around this.
// This is safe, since the only difference between signed/unsigned types
@ -131,8 +128,8 @@ public:
// document that overflow is undefined for this operation.
using APIType = typename detail::MakeUnsigned<ValueType>::type;
return static_cast<T>(AtomicInterface::Add(reinterpret_cast<APIType*>(this->Data + index),
static_cast<APIType>(value)));
return static_cast<T>(
vtkm::AtomicAdd(reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value)));
}
/// \brief Peform an atomic store to memory while enforcing, at minimum, "release"
@ -150,7 +147,7 @@ public:
VTKM_EXEC
void Set(vtkm::Id index, const ValueType& value) const
{
// We only support 32/64 bit signed/unsigned ints, and AtomicInterface
// We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
// currently only provides API for unsigned types.
// We'll cast the signed types to unsigned to work around this.
// This is safe, since the only difference between signed/unsigned types
@ -158,8 +155,7 @@ public:
// document that overflow is undefined for this operation.
using APIType = typename detail::MakeUnsigned<ValueType>::type;
AtomicInterface::Store(reinterpret_cast<APIType*>(this->Data + index),
static_cast<APIType>(value));
vtkm::AtomicStore(reinterpret_cast<APIType*>(this->Data + index), static_cast<APIType>(value));
}
/// \brief Perform an atomic CAS operation with sequentially consistent
@ -204,17 +200,16 @@ public:
const ValueType& newValue,
const ValueType& oldValue) const
{
// We only support 32/64 bit signed/unsigned ints, and AtomicInterface
// We only support 32/64 bit signed/unsigned ints, and vtkm::Atomic
// currently only provides API for unsigned types.
// We'll cast the signed types to unsigned to work around this.
// This is safe, since the only difference between signed/unsigned types
// is how overflow works, and signed overflow is already undefined.
using APIType = typename detail::MakeUnsigned<ValueType>::type;
return static_cast<T>(
AtomicInterface::CompareAndSwap(reinterpret_cast<APIType*>(this->Data + index),
static_cast<APIType>(newValue),
static_cast<APIType>(oldValue)));
return static_cast<T>(vtkm::AtomicCompareAndSwap(reinterpret_cast<APIType*>(this->Data + index),
static_cast<APIType>(newValue),
static_cast<APIType>(oldValue)));
}
private:

@ -288,7 +288,7 @@ struct AtomicTests
bool success = false;
for (T overlapIndex = 0; overlapIndex < static_cast<T>(OVERLAP); ++overlapIndex)
{
T oldValue = vtkm::AtomicCompareAndSwap(data + arrayIndex, overlapIndex, overlapIndex + 1);
T oldValue = vtkm::AtomicCompareAndSwap(data + arrayIndex, overlapIndex + 1, overlapIndex);
if (oldValue == overlapIndex)
{
success = true;