Merge topic 'switch-to-new-arrayhandle'

3228752b2 Fix error message when using deprecated storage
5ef4e7eee Make new style of ArrayHandle the expected style

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Robert Maynard <robert.maynard@kitware.com>
Merge-request: !2375
This commit is contained in:
Kenneth Moreland 2021-01-14 15:14:05 +00:00 committed by Kitware Robot
commit 7a3f20560a
42 changed files with 1458 additions and 1479 deletions

@ -16,6 +16,8 @@
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
#include <vtkm/cont/vtkm_cont_export.h>
// TODO: When virtual arrays are available, compile the implementation in a .cxx/.cu file. Common
@ -149,11 +151,12 @@ VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>&
"Cannot copy to a read-only array with a different "
"type than the source.");
using IsNewStyle =
std::is_base_of<vtkm::cont::ArrayHandleNewStyle<InValueType, InStorage>, InArrayType>;
using IsOldStyle =
std::is_base_of<vtkm::cont::internal::ArrayHandleDeprecated<InValueType, InStorage>,
InArrayType>;
// Static dispatch cases 1 & 2
detail::ArrayCopyImpl(source, destination, std::integral_constant<bool, IsNewStyle::value>{});
detail::ArrayCopyImpl(source, destination, std::integral_constant<bool, !IsOldStyle::value>{});
}
// Forward declaration

@ -17,7 +17,6 @@
#include <vtkm/Flags.h>
#include <vtkm/Types.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/DeviceAdapterList.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/ErrorInternal.h>
@ -33,10 +32,7 @@
#include <mutex>
#include <vector>
#include <vtkm/cont/internal/ArrayHandleExecutionManager.h>
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
#include <vtkm/cont/internal/Buffer.h>
#include <vtkm/cont/internal/StorageDeprecated.h>
namespace vtkm
{
@ -256,652 +252,6 @@ struct GetTypeInParentheses<void(T)>
#define VTKM_ARRAY_HANDLE_SUBCLASS_NT(classname, superclass) \
VTK_M_ARRAY_HANDLE_SUBCLASS_IMPL(classname, (classname), superclass, )
/// \brief Manages an array-worth of data.
///
/// \c ArrayHandle manages as array of data that can be manipulated by VTKm
/// algorithms. The \c ArrayHandle may have up to two copies of the array, one
/// for the control environment and one for the execution environment, although
/// depending on the device and how the array is being used, the \c ArrayHandle
/// will only have one copy when possible.
///
/// An ArrayHandle can be constructed one of two ways. Its default construction
/// creates an empty, unallocated array that can later be allocated and filled
/// either by the user or a VTKm algorithm. The \c ArrayHandle can also be
/// constructed with iterators to a user's array. In this case the \c
/// ArrayHandle will keep a reference to this array but will throw an exception
/// if asked to re-allocate to a larger size.
///
/// \c ArrayHandle behaves like a shared smart pointer in that when it is copied
/// each copy holds a reference to the same array. These copies are reference
/// counted so that when all copies of the \c ArrayHandle are destroyed, any
/// allocated memory is released.
///
///
template <typename T, typename StorageTag_ = VTKM_DEFAULT_STORAGE_TAG>
class VTKM_ALWAYS_EXPORT ArrayHandle : public internal::ArrayHandleBase
{
private:
// Basic storage is specialized; this template should not be instantiated
// for it. Specialization is in ArrayHandleBasicImpl.h
static_assert(!std::is_same<StorageTag_, StorageTagBasic>::value,
"StorageTagBasic should not use this implementation.");
using ExecutionManagerType =
vtkm::cont::internal::ArrayHandleExecutionManagerBase<T, StorageTag_>;
using MutexType = std::mutex;
using LockType = std::unique_lock<MutexType>;
mutable vtkm::cont::internal::Buffer BufferAsStorageWrapper;
public:
using StorageType = vtkm::cont::internal::Storage<T, StorageTag_>;
using ValueType = T;
using StorageTag = StorageTag_;
using WritePortalType = typename StorageType::PortalType;
using ReadPortalType = typename StorageType::PortalConstType;
template <typename DeviceAdapterTag>
struct ExecutionTypes
{
using Portal = typename ExecutionManagerType::template ExecutionTypes<DeviceAdapterTag>::Portal;
using PortalConst =
typename ExecutionManagerType::template ExecutionTypes<DeviceAdapterTag>::PortalConst;
};
using PortalControl VTKM_DEPRECATED(1.6, "Use ArrayHandle::WritePortalType instead.") =
typename StorageType::PortalType;
using PortalConstControl VTKM_DEPRECATED(1.6, "Use ArrayHandle::ReadPortalType instead.") =
typename StorageType::PortalConstType;
// Handle the fact that the ArrayHandle design has changed.
VTKM_STATIC_ASSERT_MSG((std::is_same<typename StorageType::HasOldBridge, std::true_type>::value),
"ArrayHandle design has changed. To support old-style arrays, have the "
"Storage implementation subclass StorageDeprecated.");
VTKM_CONT static constexpr vtkm::IdComponent GetNumberOfBuffers() { return 1; }
VTKM_CONT vtkm::cont::internal::Buffer* GetBuffers() const
{
this->BufferAsStorageWrapper.SetMetaData(*this);
return &this->BufferAsStorageWrapper;
}
VTKM_CONT ArrayHandle(const vtkm::cont::internal::Buffer* buffers)
{
VTKM_ASSERT(buffers[0].MetaDataIsType<ArrayHandle>());
*this = buffers[0].GetMetaData<ArrayHandle>();
}
/// Constructs an empty ArrayHandle. Typically used for output or
/// intermediate arrays that will be filled by a VTKm algorithm.
///
VTKM_CONT ArrayHandle();
/// Copy constructor.
///
/// Implemented so that it is defined exclusively in the control environment.
/// If there is a separate device for the execution environment (for example,
/// with CUDA), then the automatically generated copy constructor could be
/// created for all devices, and it would not be valid for all devices.
///
ArrayHandle(const vtkm::cont::ArrayHandle<ValueType, StorageTag>& src);
/// Move constructor.
///
/// Implemented so that it is defined exclusively in the control environment.
/// If there is a separate device for the execution environment (for example,
/// with CUDA), then the automatically generated move constructor could be
/// created for all devices, and it would not be valid for all devices.
///
ArrayHandle(vtkm::cont::ArrayHandle<ValueType, StorageTag>&& src) noexcept;
/// Special constructor for subclass specializations that need to set the
/// initial state of the control array. When this constructor is used, it
/// is assumed that the control array is valid.
///
ArrayHandle(const StorageType& storage);
/// Special constructor for subclass specializations that need to set the
/// initial state of the control array. When this constructor is used, it
/// is assumed that the control array is valid.
///
ArrayHandle(StorageType&& storage) noexcept;
/// Destructs an empty ArrayHandle.
///
/// Implemented so that it is defined exclusively in the control environment.
/// If there is a separate device for the execution environment (for example,
/// with CUDA), then the automatically generated destructor could be
/// created for all devices, and it would not be valid for all devices.
///
~ArrayHandle();
/// \brief Copies an ArrayHandle
///
VTKM_CONT
vtkm::cont::ArrayHandle<ValueType, StorageTag>& operator=(
const vtkm::cont::ArrayHandle<ValueType, StorageTag>& src);
/// \brief Move and Assignment of an ArrayHandle
///
VTKM_CONT
vtkm::cont::ArrayHandle<ValueType, StorageTag>& operator=(
vtkm::cont::ArrayHandle<ValueType, StorageTag>&& src) noexcept;
/// Like a pointer, two \c ArrayHandles are considered equal if they point
/// to the same location in memory.
///
VTKM_CONT
bool operator==(const ArrayHandle<ValueType, StorageTag>& rhs) const
{
return (this->Internals == rhs.Internals);
}
VTKM_CONT
bool operator!=(const ArrayHandle<ValueType, StorageTag>& rhs) const
{
return (this->Internals != rhs.Internals);
}
template <typename VT, typename ST>
VTKM_CONT bool operator==(const ArrayHandle<VT, ST>&) const
{
return false; // different valuetype and/or storage
}
template <typename VT, typename ST>
VTKM_CONT bool operator!=(const ArrayHandle<VT, ST>&) const
{
return true; // different valuetype and/or storage
}
/// Get the storage.
///
VTKM_CONT StorageType& GetStorage();
/// Get the storage.
///
VTKM_CONT const StorageType& GetStorage() const;
/// Get the array portal of the control array.
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
/// exceptions maybe thrown for errors from previously executed worklets.
///
/// \deprecated Use `WritePortal` instead. Note that the portal returned from `WritePortal`
/// will disallow any other reads or writes to the array while it is in scope.
///
VTKM_CONT
VTKM_DEPRECATED(1.6,
"Use ArrayHandle::WritePortal() instead. "
"Note that the returned portal will lock the array while it is in scope.")
/// \cond NOPE
typename StorageType::PortalType GetPortalControl();
/// \endcond
/// Get the array portal of the control array.
/// Since worklet invocations are asynchronous and this routine is a synchronization point,
/// exceptions maybe thrown for errors from previously executed worklets.
///
/// \deprecated Use `ReadPortal` instead. Note that the portal returned from `ReadPortal`
/// will disallow any writes to the array while it is in scope.
///
VTKM_CONT
VTKM_DEPRECATED(1.6,
"Use ArrayHandle::ReadPortal() instead. "
"Note that the returned portal will lock the array while it is in scope.")
/// \cond NOPE
typename StorageType::PortalConstType GetPortalConstControl() const;
/// \endcond
/// \@{
/// \brief Get an array portal that can be used in the control environment.
///
/// The returned array can be used in the control environment to read values from the array. (It
/// is not possible to write to the returned portal. That is `Get` will work on the portal, but
/// `Set` will not.)
///
/// **Note:** The returned portal cannot be used in the execution environment. This is because
/// the portal will not work on some devices like GPUs. To get a portal that will work in the
/// execution environment, use `PrepareForInput`.
///
VTKM_CONT ReadPortalType ReadPortal() const;
/// \@}
/// \@{
/// \brief Get an array portal that can be used in the control environment.
///
/// The returned array can be used in the control environment to reand and write values to the
/// array.
///
///
/// **Note:** The returned portal cannot be used in the execution environment. This is because
/// the portal will not work on some devices like GPUs. To get a portal that will work in the
/// execution environment, use `PrepareForInput`.
///
VTKM_CONT WritePortalType WritePortal() const;
/// \@}
/// Returns the number of entries in the array.
///
VTKM_CONT vtkm::Id GetNumberOfValues() const
{
LockType lock = this->GetLock();
return this->GetNumberOfValues(lock);
}
/// \brief Allocates an array large enough to hold the given number of values.
///
/// The allocation may be done on an already existing array, but can wipe out
/// any data already in the array. This method can throw
/// ErrorBadAllocation if the array cannot be allocated or
/// ErrorBadValue if the allocation is not feasible (for example, the
/// array storage is read-only).
///
VTKM_CONT
void Allocate(vtkm::Id numberOfValues)
{
vtkm::cont::Token token;
this->Allocate(numberOfValues, token);
}
VTKM_CONT void Allocate(vtkm::Id numberOfValues, vtkm::cont::Token& token)
{
LockType lock = this->GetLock();
this->WaitToWrite(lock, token);
this->ReleaseResourcesExecutionInternal(lock, token);
this->Internals->GetControlArray(lock)->Allocate(numberOfValues);
// Set to false and then to true to ensure anything pointing to an array before the allocate
// is invalidated.
this->Internals->SetControlArrayValid(lock, false);
this->Internals->SetControlArrayValid(lock, true);
}
/// \brief Reduces the size of the array without changing its values.
///
/// This method allows you to resize the array without reallocating it. The
/// number of entries in the array is changed to \c numberOfValues. The data
/// in the array (from indices 0 to \c numberOfValues - 1) are the same, but
/// \c numberOfValues must be equal or less than the preexisting size
/// (returned from GetNumberOfValues). That is, this method can only be used
/// to shorten the array, not lengthen.
VTKM_CONT void Shrink(vtkm::Id numberOfValues)
{
vtkm::cont::Token token;
this->Shrink(numberOfValues, token);
}
VTKM_CONT void Shrink(vtkm::Id numberOfValues, vtkm::cont::Token& token);
/// Releases any resources being used in the execution environment (that are
/// not being shared by the control environment).
///
VTKM_CONT void ReleaseResourcesExecution()
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->WaitToWrite(lock, token);
// Save any data in the execution environment by making sure it is synced
// with the control environment.
this->SyncControlArray(lock, token);
this->ReleaseResourcesExecutionInternal(lock, token);
}
}
/// Releases all resources in both the control and execution environments.
///
VTKM_CONT void ReleaseResources()
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->ReleaseResourcesExecutionInternal(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
this->Internals->GetControlArray(lock)->ReleaseResources();
this->Internals->SetControlArrayValid(lock, false);
}
}
}
/// Prepares this array to be used as an input to an operation in the
/// execution environment. If necessary, copies data to the execution
/// environment. Can throw an exception if this array does not yet contain
/// any data. Returns a portal that can be used in code running in the
/// execution environment.
///
/// The `Token` object provided will be attached to this `ArrayHandle`.
/// The returned portal is guaranteed to be valid while the `Token` is
/// still attached and in scope. Other operations on this `ArrayHandle`
/// that would invalidate the returned portal will block until the `Token`
/// is released. Likewise, this method will block if another `Token` is
/// already attached. This can potentially lead to deadlocks.
///
template <typename DeviceAdapterTag>
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(
DeviceAdapterTag,
vtkm::cont::Token& token) const;
/// Prepares (allocates) this array to be used as an output from an operation
/// in the execution environment. The internal state of this class is set to
/// have valid data in the execution array with the assumption that the array
/// will be filled soon (i.e. before any other methods of this object are
/// called). Returns a portal that can be used in code running in the
/// execution environment.
///
/// The `Token` object provided will be attached to this `ArrayHandle`.
/// The returned portal is guaranteed to be valid while the `Token` is
/// still attached and in scope. Other operations on this `ArrayHandle`
/// that would invalidate the returned portal will block until the `Token`
/// is released. Likewise, this method will block if another `Token` is
/// already attached. This can potentially lead to deadlocks.
///
template <typename DeviceAdapterTag>
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal
PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag, vtkm::cont::Token& token);
/// Prepares this array to be used in an in-place operation (both as input
/// and output) in the execution environment. If necessary, copies data to
/// the execution environment. Can throw an exception if this array does not
/// yet contain any data. Returns a portal that can be used in code running
/// in the execution environment.
///
/// The `Token` object provided will be attached to this `ArrayHandle`.
/// The returned portal is guaranteed to be valid while the `Token` is
/// still attached and in scope. Other operations on this `ArrayHandle`
/// that would invalidate the returned portal will block until the `Token`
/// is released. Likewise, this method will block if another `Token` is
/// already attached. This can potentially lead to deadlocks.
///
template <typename DeviceAdapterTag>
VTKM_CONT typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(
DeviceAdapterTag,
vtkm::cont::Token& token);
template <typename DeviceAdapterTag>
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInput now requires a vtkm::cont::Token object.")
typename ExecutionTypes<DeviceAdapterTag>::PortalConst PrepareForInput(DeviceAdapterTag) const
{
vtkm::cont::Token token;
return this->PrepareForInput(DeviceAdapterTag{}, token);
}
template <typename DeviceAdapterTag>
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForOutput now requires a vtkm::cont::Token object.")
typename ExecutionTypes<DeviceAdapterTag>::Portal
PrepareForOutput(vtkm::Id numberOfValues, DeviceAdapterTag)
{
vtkm::cont::Token token;
return this->PrepareForOutput(numberOfValues, DeviceAdapterTag{}, token);
}
template <typename DeviceAdapterTag>
VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForInPlace now requires a vtkm::cont::Token object.")
typename ExecutionTypes<DeviceAdapterTag>::Portal PrepareForInPlace(DeviceAdapterTag)
{
vtkm::cont::Token token;
return this->PrepareForInPlace(DeviceAdapterTag{}, token);
}
/// Returns the DeviceAdapterId for the current device. If there is no device
/// with an up-to-date copy of the data, VTKM_DEVICE_ADAPTER_UNDEFINED is
/// returned.
///
/// Note that in a multithreaded environment the validity of this result can
/// change.
VTKM_CONT
DeviceAdapterId GetDeviceAdapterId() const
{
LockType lock = this->GetLock();
return this->Internals->IsExecutionArrayValid(lock)
? this->Internals->GetExecutionArray(lock)->GetDeviceAdapterId()
: DeviceAdapterTagUndefined{};
}
/// Synchronizes the control array with the execution array. If either the
/// user array or control array is already valid, this method does nothing
/// (because the data is already available in the control environment).
/// Although the internal state of this class can change, the method is
/// declared const because logically the data does not.
///
VTKM_CONT void SyncControlArray() const
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->SyncControlArray(lock, token);
}
}
/// \brief Enqueue a token for access to this ArrayHandle.
///
/// This method places the given `Token` into the queue of `Token`s waiting for
/// access to this `ArrayHandle` and then returns immediately. When this token
/// is later used to get data from this `ArrayHandle` (for example, in a call to
/// `PrepareForInput`), it will use this place in the queue while waiting for
/// access.
///
/// This method is to be used to ensure that a set of accesses to an `ArrayHandle`
/// that happen on multiple threads occur in a specified order. For example, if
/// you spawn of a job to modify data in an `ArrayHandle` and then spawn off a job
/// that reads that same data, you need to make sure that the first job gets
/// access to the `ArrayHandle` before the second. If they both just attempt to call
/// their respective `Prepare` methods, there is no guarantee which order they
/// will occur. Having the spawning thread first call this method will ensure the order.
///
/// \warning After calling this method it is required to subsequently
/// call a method like one of the `Prepare` methods that attaches the token
/// to this `ArrayHandle`. Otherwise, the enqueued token will block any subsequent
/// access to the `ArrayHandle`, even if the `Token` is destroyed.
///
VTKM_CONT void Enqueue(const vtkm::cont::Token& token) const;
private:
/// Acquires a lock on the internals of this `ArrayHandle`. The calling
/// function should keep the returned lock and let it go out of scope
/// when the lock is no longer needed.
///
LockType GetLock() const { return LockType(this->Internals->Mutex); }
/// Returns true if read operations can currently be performed.
///
VTKM_CONT bool CanRead(const LockType& lock, const vtkm::cont::Token& token) const;
//// Returns true if write operations can currently be performed.
///
VTKM_CONT bool CanWrite(const LockType& lock, const vtkm::cont::Token& token) const;
//// Will block the current thread until a read can be performed.
///
VTKM_CONT void WaitToRead(LockType& lock, vtkm::cont::Token& token) const;
//// Will block the current thread until a write can be performed.
///
VTKM_CONT void WaitToWrite(LockType& lock, vtkm::cont::Token& token, bool fakeRead = false) const;
/// Gets this array handle ready to interact with the given device. If the
/// array handle has already interacted with this device, then this method
/// does nothing. Although the internal state of this class can change, the
/// method is declared const because logically the data does not.
///
template <typename DeviceAdapterTag>
VTKM_CONT void PrepareForDevice(LockType& lock, vtkm::cont::Token& token, DeviceAdapterTag) const;
/// Synchronizes the control array with the execution array. If either the
/// user array or control array is already valid, this method does nothing
/// (because the data is already available in the control environment).
/// Although the internal state of this class can change, the method is
/// declared const because logically the data does not.
///
VTKM_CONT void SyncControlArray(LockType& lock, vtkm::cont::Token& token) const;
vtkm::Id GetNumberOfValues(LockType& lock) const;
VTKM_CONT
void ReleaseResourcesExecutionInternal(LockType& lock, vtkm::cont::Token& token) const
{
if (this->Internals->IsExecutionArrayValid(lock))
{
this->WaitToWrite(lock, token);
// Note that it is possible that while waiting someone else deleted the execution array.
// That is why we check again.
}
if (this->Internals->IsExecutionArrayValid(lock))
{
this->Internals->GetExecutionArray(lock)->ReleaseResources();
this->Internals->SetExecutionArrayValid(lock, false);
}
}
VTKM_CONT void Enqueue(const LockType& lock, const vtkm::cont::Token& token) const;
class VTKM_ALWAYS_EXPORT InternalStruct
{
mutable StorageType ControlArray;
mutable std::shared_ptr<bool> ControlArrayValid;
mutable std::unique_ptr<ExecutionManagerType> ExecutionArray;
mutable bool ExecutionArrayValid = false;
mutable vtkm::cont::Token::ReferenceCount ReadCount = 0;
mutable vtkm::cont::Token::ReferenceCount WriteCount = 0;
mutable std::deque<vtkm::cont::Token::Reference> Queue;
VTKM_CONT void CheckLock(const LockType& lock) const
{
VTKM_ASSERT((lock.mutex() == &this->Mutex) && (lock.owns_lock()));
}
public:
MutexType Mutex;
std::condition_variable ConditionVariable;
InternalStruct() = default;
InternalStruct(const StorageType& storage);
InternalStruct(StorageType&& storage);
~InternalStruct()
{
// It should not be possible to destroy this array if any tokens are still attached to it.
LockType lock(this->Mutex);
VTKM_ASSERT((*this->GetReadCount(lock) == 0) && (*this->GetWriteCount(lock) == 0));
this->SetControlArrayValid(lock, false);
}
// To access any feature in InternalStruct, you must have locked the mutex. You have
// to prove it by passing in a reference to a std::unique_lock.
VTKM_CONT bool IsControlArrayValid(const LockType& lock) const
{
this->CheckLock(lock);
if (!this->ControlArrayValid)
{
return false;
}
else
{
return *this->ControlArrayValid;
}
}
VTKM_CONT void SetControlArrayValid(const LockType& lock, bool value)
{
this->CheckLock(lock);
if (IsControlArrayValid(lock) == value)
{
return;
}
if (value) // ControlArrayValid == false or nullptr
{
// If we are changing the valid flag from false to true, then refresh the pointer.
// There may be array portals that already have a reference to the flag. Those portals
// will stay in an invalid state whereas new portals will go to a valid state. To
// handle both conditions, drop the old reference and create a new one.
this->ControlArrayValid.reset(new bool(true));
}
else // value == false and ControlArrayValid == true
{
*this->ControlArrayValid = false;
}
}
VTKM_CONT std::shared_ptr<bool> GetControlArrayValidPointer(const LockType& lock) const
{
this->CheckLock(lock);
return this->ControlArrayValid;
}
VTKM_CONT StorageType* GetControlArray(const LockType& lock) const
{
this->CheckLock(lock);
return &this->ControlArray;
}
VTKM_CONT bool IsExecutionArrayValid(const LockType& lock) const
{
this->CheckLock(lock);
return this->ExecutionArrayValid;
}
VTKM_CONT void SetExecutionArrayValid(const LockType& lock, bool value)
{
this->CheckLock(lock);
this->ExecutionArrayValid = value;
}
VTKM_CONT ExecutionManagerType* GetExecutionArray(const LockType& lock) const
{
this->CheckLock(lock);
return this->ExecutionArray.get();
}
VTKM_CONT void DeleteExecutionArray(const LockType& lock)
{
this->CheckLock(lock);
this->ExecutionArray.reset();
this->ExecutionArrayValid = false;
}
template <typename DeviceAdapterTag>
VTKM_CONT void NewExecutionArray(const LockType& lock, DeviceAdapterTag)
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
this->CheckLock(lock);
VTKM_ASSERT(this->ExecutionArray == nullptr);
VTKM_ASSERT(!this->ExecutionArrayValid);
this->ExecutionArray.reset(
new vtkm::cont::internal::ArrayHandleExecutionManager<T, StorageTag, DeviceAdapterTag>(
&this->ControlArray));
}
VTKM_CONT vtkm::cont::Token::ReferenceCount* GetReadCount(const LockType& lock) const
{
this->CheckLock(lock);
return &this->ReadCount;
}
VTKM_CONT vtkm::cont::Token::ReferenceCount* GetWriteCount(const LockType& lock) const
{
this->CheckLock(lock);
return &this->WriteCount;
}
VTKM_CONT std::deque<vtkm::cont::Token::Reference>& GetQueue(const LockType& lock) const
{
this->CheckLock(lock);
return this->Queue;
}
};
VTKM_CONT
ArrayHandle(const std::shared_ptr<InternalStruct>& i)
: Internals(i)
{
}
std::shared_ptr<InternalStruct> Internals;
};
namespace detail
{
@ -917,90 +267,26 @@ VTKM_CONT_EXPORT VTKM_CONT vtkm::cont::DeviceAdapterId ArrayHandleGetDeviceAdapt
} // namespace detail
// This macro is used to declare an ArrayHandle that uses the new style of Storage
// that leverages Buffer objects. This macro will go away once ArrayHandle
// is replaced with ArrayHandleNewStyle. To use this macro, first have a declaration
// of the template and then put the macro like this:
//
// template <typename T>
// VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagFoo);
//
// Don't forget to use VTKM_PASS_COMMAS if one of the macro arguments contains
// a template with multiple parameters.
#define VTKM_ARRAY_HANDLE_NEW_STYLE(ValueType_, StorageType_) \
class VTKM_ALWAYS_EXPORT ArrayHandle<ValueType_, StorageType_> \
: public ArrayHandleNewStyle<ValueType_, StorageType_> \
{ \
using Superclass = ArrayHandleNewStyle<ValueType_, StorageType_>; \
\
public: \
VTKM_CONT \
ArrayHandle() \
: Superclass() \
{ \
} \
\
VTKM_CONT \
ArrayHandle(const ArrayHandle<ValueType_, StorageType_>& src) \
: Superclass(src) \
{ \
} \
\
VTKM_CONT \
ArrayHandle(ArrayHandle<ValueType_, StorageType_>&& src) noexcept \
: Superclass(std::move(src)) \
{ \
} \
\
VTKM_CONT \
ArrayHandle(const ArrayHandleNewStyle<ValueType_, StorageType_>& src) \
: Superclass(src) \
{ \
} \
\
VTKM_CONT \
ArrayHandle(ArrayHandleNewStyle<ValueType_, StorageType_>&& src) noexcept \
: Superclass(std::move(src)) \
{ \
} \
\
VTKM_CONT ArrayHandle(const vtkm::cont::internal::Buffer* buffers) \
: Superclass(buffers) \
{ \
} \
\
VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers) \
: Superclass(buffers) \
{ \
} \
\
VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) \
: Superclass(std::move(buffers)) \
{ \
} \
\
VTKM_CONT \
ArrayHandle<ValueType_, StorageType_>& operator=( \
const ArrayHandle<ValueType_, StorageType_>& src) \
{ \
this->Superclass::operator=(src); \
return *this; \
} \
\
VTKM_CONT \
ArrayHandle<ValueType_, StorageType_>& operator=( \
ArrayHandle<ValueType_, StorageType_>&& src) noexcept \
{ \
this->Superclass::operator=(std::move(src)); \
return *this; \
} \
\
VTKM_CONT ~ArrayHandle() {} \
}
/// This new style of ArrayHandle will eventually replace the classic ArrayHandle
/// \brief Manages an array-worth of data.
///
/// `ArrayHandle` manages as array of data that can be manipulated by VTKm
/// algorithms. The `ArrayHandle` may have up to two copies of the array, one
/// for the control environment and one for the execution environment, although
/// depending on the device and how the array is being used, the `ArrayHandle`
/// will only have one copy when possible.
///
/// An `ArrayHandle` is often constructed by instantiating one of the `ArrayHandle`
/// subclasses. Several basic `ArrayHandle` types can also be constructed directly
/// and then allocated. The `ArrayHandleBasic` subclass provides mechanisms for
/// importing user arrays into an `ArrayHandle`.
///
/// `ArrayHandle` behaves like a shared smart pointer in that when it is copied
/// each copy holds a reference to the same array. These copies are reference
/// counted so that when all copies of the `ArrayHandle` are destroyed, any
/// allocated memory is released.
///
template <typename T, typename StorageTag_ = VTKM_DEFAULT_STORAGE_TAG>
class VTKM_ALWAYS_EXPORT ArrayHandleNewStyle : public internal::ArrayHandleBase
class VTKM_ALWAYS_EXPORT ArrayHandle : public internal::ArrayHandleBase
{
public:
using ValueType = T;
@ -1025,7 +311,7 @@ public:
/// Constructs an empty ArrayHandle.
///
VTKM_CONT ArrayHandleNewStyle()
VTKM_CONT ArrayHandle()
: Buffers(static_cast<std::size_t>(StorageType::GetNumberOfBuffers()))
{
}
@ -1037,7 +323,7 @@ public:
/// with CUDA), then the automatically generated copy constructor could be
/// created for all devices, and it would not be valid for all devices.
///
VTKM_CONT ArrayHandleNewStyle(const vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>& src)
VTKM_CONT ArrayHandle(const vtkm::cont::ArrayHandle<ValueType, StorageTag>& src)
: Buffers(src.Buffers)
{
}
@ -1049,8 +335,7 @@ public:
/// with CUDA), then the automatically generated move constructor could be
/// created for all devices, and it would not be valid for all devices.
///
VTKM_CONT ArrayHandleNewStyle(
vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>&& src) noexcept
VTKM_CONT ArrayHandle(vtkm::cont::ArrayHandle<ValueType, StorageTag>&& src) noexcept
: Buffers(std::move(src.Buffers))
{
}
@ -1059,19 +344,19 @@ public:
/// Special constructor for subclass specializations that need to set the
/// initial state array. Used when pulling data from other sources.
///
VTKM_CONT ArrayHandleNewStyle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
VTKM_CONT ArrayHandle(const std::vector<vtkm::cont::internal::Buffer>& buffers)
: Buffers(buffers)
{
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
}
VTKM_CONT ArrayHandleNewStyle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
VTKM_CONT ArrayHandle(std::vector<vtkm::cont::internal::Buffer>&& buffers) noexcept
: Buffers(std::move(buffers))
{
VTKM_ASSERT(static_cast<vtkm::IdComponent>(this->Buffers.size()) == this->GetNumberOfBuffers());
}
VTKM_CONT ArrayHandleNewStyle(const vtkm::cont::internal::Buffer* buffers)
VTKM_CONT ArrayHandle(const vtkm::cont::internal::Buffer* buffers)
: Buffers(buffers, buffers + StorageType::GetNumberOfBuffers())
{
}
@ -1084,13 +369,13 @@ public:
/// with CUDA), then the automatically generated destructor could be
/// created for all devices, and it would not be valid for all devices.
///
VTKM_CONT ~ArrayHandleNewStyle() {}
VTKM_CONT ~ArrayHandle() {}
/// \brief Copies an ArrayHandle
///
VTKM_CONT
vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>& operator=(
const vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>& src)
vtkm::cont::ArrayHandle<ValueType, StorageTag>& operator=(
const vtkm::cont::ArrayHandle<ValueType, StorageTag>& src)
{
this->Buffers = src.Buffers;
return *this;
@ -1099,8 +384,8 @@ public:
/// \brief Move and Assignment of an ArrayHandle
///
VTKM_CONT
vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>& operator=(
vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>&& src) noexcept
vtkm::cont::ArrayHandle<ValueType, StorageTag>& operator=(
vtkm::cont::ArrayHandle<ValueType, StorageTag>&& src) noexcept
{
this->Buffers = std::move(src.Buffers);
return *this;
@ -1411,8 +696,7 @@ public:
///
/// Takes the data that is in \a source and copies that data into this array.
///
VTKM_CONT void DeepCopyFrom(
const vtkm::cont::ArrayHandleNewStyle<ValueType, StorageTag>& source) const
VTKM_CONT void DeepCopyFrom(const vtkm::cont::ArrayHandle<ValueType, StorageTag>& source) const
{
VTKM_ASSERT(this->Buffers.size() == source.Buffers.size());
@ -1667,8 +951,4 @@ VTKM_CONT inline std::vector<vtkm::cont::internal::Buffer> CreateBuffers(const A
#include <vtkm/cont/ArrayHandleBasic.h>
#endif
#ifndef vtk_m_cont_ArrayHandle_hxx
#include <vtkm/cont/ArrayHandle.hxx>
#endif
#endif //vtk_m_cont_ArrayHandle_h

@ -1,596 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_cont_ArrayHandle_hxx
#define vtk_m_cont_ArrayHandle_hxx
#include <vtkm/cont/ArrayHandle.h>
namespace vtkm
{
namespace cont
{
template <typename T, typename S>
ArrayHandle<T, S>::InternalStruct::InternalStruct(
const typename ArrayHandle<T, S>::StorageType& storage)
: ControlArray(storage)
, ControlArrayValid(new bool(true))
, ExecutionArrayValid(false)
{
}
template <typename T, typename S>
ArrayHandle<T, S>::InternalStruct::InternalStruct(typename ArrayHandle<T, S>::StorageType&& storage)
: ControlArray(std::move(storage))
, ControlArrayValid(new bool(true))
, ExecutionArrayValid(false)
{
}
template <typename T, typename S>
ArrayHandle<T, S>::ArrayHandle()
: Internals(std::make_shared<InternalStruct>())
{
}
template <typename T, typename S>
ArrayHandle<T, S>::ArrayHandle(const ArrayHandle<T, S>& src)
: Internals(src.Internals)
{
}
template <typename T, typename S>
ArrayHandle<T, S>::ArrayHandle(ArrayHandle<T, S>&& src) noexcept
: Internals(std::move(src.Internals))
{
}
template <typename T, typename S>
ArrayHandle<T, S>::ArrayHandle(const typename ArrayHandle<T, S>::StorageType& storage)
: Internals(std::make_shared<InternalStruct>(storage))
{
}
template <typename T, typename S>
ArrayHandle<T, S>::ArrayHandle(typename ArrayHandle<T, S>::StorageType&& storage) noexcept
: Internals(std::make_shared<InternalStruct>(std::move(storage)))
{
}
template <typename T, typename S>
ArrayHandle<T, S>::~ArrayHandle()
{
}
template <typename T, typename S>
ArrayHandle<T, S>& ArrayHandle<T, S>::operator=(const ArrayHandle<T, S>& src)
{
this->Internals = src.Internals;
return *this;
}
template <typename T, typename S>
ArrayHandle<T, S>& ArrayHandle<T, S>::operator=(ArrayHandle<T, S>&& src) noexcept
{
this->Internals = std::move(src.Internals);
return *this;
}
template <typename T, typename S>
typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage()
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
return *this->Internals->GetControlArray(lock);
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
const typename ArrayHandle<T, S>::StorageType& ArrayHandle<T, S>::GetStorage() const
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
return *this->Internals->GetControlArray(lock);
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
typename ArrayHandle<T, S>::StorageType::PortalType ArrayHandle<T, S>::GetPortalControl()
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
// If the user writes into the iterator we return, then the execution
// array will become invalid. Play it safe and release the execution
// resources. (Use the const version to preserve the execution array.)
this->ReleaseResourcesExecutionInternal(lock, token);
return this->Internals->GetControlArray(lock)->GetPortal();
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
typename ArrayHandle<T, S>::StorageType::PortalConstType ArrayHandle<T, S>::GetPortalConstControl()
const
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
return this->Internals->GetControlArray(lock)->GetPortalConst();
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
typename ArrayHandle<T, S>::ReadPortalType ArrayHandle<T, S>::ReadPortal() const
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->WaitToRead(lock, token);
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
return ReadPortalType(this->Internals->GetControlArray(lock)->GetPortalConst());
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
typename ArrayHandle<T, S>::WritePortalType ArrayHandle<T, S>::WritePortal() const
{
// A Token should not be declared within the scope of a lock. when the token goes out of scope
// it will attempt to aquire the lock, which is undefined behavior of the thread already has
// the lock.
vtkm::cont::Token token;
{
LockType lock = this->GetLock();
this->WaitToWrite(lock, token);
this->SyncControlArray(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
// If the user writes into the iterator we return, then the execution
// array will become invalid. Play it safe and release the execution
// resources. (Use the const version to preserve the execution array.)
this->ReleaseResourcesExecutionInternal(lock, token);
return WritePortalType(this->Internals->GetControlArray(lock)->GetPortal());
}
else
{
throw vtkm::cont::ErrorInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
}
template <typename T, typename S>
vtkm::Id ArrayHandle<T, S>::GetNumberOfValues(LockType& lock) const
{
if (this->Internals->IsControlArrayValid(lock))
{
return this->Internals->GetControlArray(lock)->GetNumberOfValues();
}
else if (this->Internals->IsExecutionArrayValid(lock))
{
return this->Internals->GetExecutionArray(lock)->GetNumberOfValues();
}
else
{
return 0;
}
}
template <typename T, typename S>
void ArrayHandle<T, S>::Shrink(vtkm::Id numberOfValues, vtkm::cont::Token& token)
{
VTKM_ASSERT(numberOfValues >= 0);
if (numberOfValues > 0)
{
LockType lock = this->GetLock();
vtkm::Id originalNumberOfValues = this->GetNumberOfValues(lock);
if (numberOfValues < originalNumberOfValues)
{
this->WaitToWrite(lock, token);
if (this->Internals->IsControlArrayValid(lock))
{
this->Internals->GetControlArray(lock)->Shrink(numberOfValues);
}
if (this->Internals->IsExecutionArrayValid(lock))
{
this->Internals->GetExecutionArray(lock)->Shrink(numberOfValues);
}
}
else if (numberOfValues == originalNumberOfValues)
{
// Nothing to do.
}
else // numberOfValues > originalNumberOfValues
{
throw vtkm::cont::ErrorBadValue("ArrayHandle::Shrink cannot be used to grow array.");
}
VTKM_ASSERT(this->GetNumberOfValues(lock) == numberOfValues);
}
else // numberOfValues == 0
{
// If we are shrinking to 0, there is nothing to save and we might as well
// free up memory. Plus, some storage classes expect that data will be
// deallocated when the size goes to zero.
this->Allocate(0, token);
}
}
template <typename T, typename S>
template <typename DeviceAdapterTag>
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::PortalConst
ArrayHandle<T, S>::PrepareForInput(DeviceAdapterTag device, vtkm::cont::Token& token) const
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
LockType lock = this->GetLock();
this->WaitToRead(lock, token);
if (!this->Internals->IsControlArrayValid(lock) && !this->Internals->IsExecutionArrayValid(lock))
{
// Want to use an empty array.
// Set up ArrayHandle state so this actually works.
this->Internals->GetControlArray(lock)->Allocate(0);
this->Internals->SetControlArrayValid(lock, true);
}
this->PrepareForDevice(lock, token, device);
auto portal = this->Internals->GetExecutionArray(lock)->PrepareForInput(
!this->Internals->IsExecutionArrayValid(lock), device, token);
this->Internals->SetExecutionArrayValid(lock, true);
return portal;
}
template <typename T, typename S>
template <typename DeviceAdapterTag>
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::Portal
ArrayHandle<T, S>::PrepareForOutput(vtkm::Id numberOfValues,
DeviceAdapterTag device,
vtkm::cont::Token& token)
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
LockType lock = this->GetLock();
this->WaitToWrite(lock, token);
// Invalidate any control arrays.
// Should the control array resource be released? Probably not a good
// idea when shared with execution.
this->Internals->SetControlArrayValid(lock, false);
this->PrepareForDevice(lock, token, device);
auto portal =
this->Internals->GetExecutionArray(lock)->PrepareForOutput(numberOfValues, device, token);
// We are assuming that the calling code will fill the array using the
// iterators we are returning, so go ahead and mark the execution array as
// having valid data. (A previous version of this class had a separate call
// to mark the array as filled, but that was onerous to call at the the
// right time and rather pointless since it is basically always the case
// that the array is going to be filled before anything else. In this
// implementation the only access to the array is through the iterators
// returned from this method, so you would have to work to invalidate this
// assumption anyway.)
this->Internals->SetExecutionArrayValid(lock, true);
return portal;
}
template <typename T, typename S>
template <typename DeviceAdapterTag>
typename ArrayHandle<T, S>::template ExecutionTypes<DeviceAdapterTag>::Portal
ArrayHandle<T, S>::PrepareForInPlace(DeviceAdapterTag device, vtkm::cont::Token& token)
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
LockType lock = this->GetLock();
this->WaitToWrite(lock, token);
if (!this->Internals->IsControlArrayValid(lock) && !this->Internals->IsExecutionArrayValid(lock))
{
// Want to use an empty array.
// Set up ArrayHandle state so this actually works.
this->Internals->GetControlArray(lock)->Allocate(0);
this->Internals->SetControlArrayValid(lock, true);
}
this->PrepareForDevice(lock, token, device);
auto portal = this->Internals->GetExecutionArray(lock)->PrepareForInPlace(
!this->Internals->IsExecutionArrayValid(lock), device, token);
this->Internals->SetExecutionArrayValid(lock, true);
// Invalidate any control arrays since their data will become invalid when
// the execution data is overwritten. Don't actually release the control
// array. It may be shared as the execution array.
this->Internals->SetControlArrayValid(lock, false);
return portal;
}
template <typename T, typename S>
template <typename DeviceAdapterTag>
void ArrayHandle<T, S>::PrepareForDevice(LockType& lock,
vtkm::cont::Token& token,
DeviceAdapterTag device) const
{
if (this->Internals->GetExecutionArray(lock) != nullptr)
{
if (this->Internals->GetExecutionArray(lock)->IsDeviceAdapter(DeviceAdapterTag()))
{
// Already have manager for correct device adapter. Nothing to do.
return;
}
else
{
// Have the wrong manager. Delete the old one and create a new one
// of the right type. (TODO: it would be possible for the array handle
// to hold references to execution arrays on multiple devices. When data
// are written on one devices, all the other devices should get cleared.)
// BUG: There is a non-zero chance that while waiting for the write lock, another thread
// could change the ExecutionInterface, which would cause problems. In the future we should
// support multiple devices, in which case we would not have to delete one execution array
// to load another.
// BUG: The current implementation does not allow the ArrayHandle to be on two devices
// at the same time. Thus, it is not possible for two simultaneously read from the same
// ArrayHandle on two different devices. This might cause unexpected deadlocks.
this->WaitToWrite(lock, token, true); // Make sure no one is reading device array
this->SyncControlArray(lock, token);
// Need to change some state that does not change the logical state from
// an external point of view.
this->Internals->DeleteExecutionArray(lock);
}
}
// Need to change some state that does not change the logical state from
// an external point of view.
this->Internals->NewExecutionArray(lock, device);
}
template <typename T, typename S>
void ArrayHandle<T, S>::SyncControlArray(LockType& lock, vtkm::cont::Token& token) const
{
if (!this->Internals->IsControlArrayValid(lock))
{
// It may be the case that `SyncControlArray` is called from a method that has a `Token`.
// However, if we are here, that `Token` should not already be attached to this array.
// If it were, then there should be no reason to move data arround (unless the `Token`
// was used when preparing for multiple devices, which it should not be used like that).
this->WaitToRead(lock, token);
// Need to change some state that does not change the logical state from
// an external point of view.
if (this->Internals->IsExecutionArrayValid(lock))
{
this->Internals->GetExecutionArray(lock)->RetrieveOutputData(
this->Internals->GetControlArray(lock));
this->Internals->SetControlArrayValid(lock, true);
}
else
{
// This array is in the null state (there is nothing allocated), but
// the calling function wants to do something with the array. Put this
// class into a valid state by allocating an array of size 0.
this->Internals->GetControlArray(lock)->Allocate(0);
this->Internals->SetControlArrayValid(lock, true);
}
}
}
template <typename T, typename S>
bool ArrayHandle<T, S>::CanRead(const LockType& lock, const vtkm::cont::Token& token) const
{
// If the token is already attached to this array, then we allow reading.
if (token.IsAttached(this->Internals->GetWriteCount(lock)) ||
token.IsAttached(this->Internals->GetReadCount(lock)))
{
return true;
}
// If there is anyone else waiting at the top of the queue, we cannot access this array.
auto& queue = this->Internals->GetQueue(lock);
if (!queue.empty() && (queue.front() != token))
{
return false;
}
// No one else is waiting, so we can read the array as long as no one else is writing.
return (*this->Internals->GetWriteCount(lock) < 1);
}
template <typename T, typename S>
bool ArrayHandle<T, S>::CanWrite(const LockType& lock, const vtkm::cont::Token& token) const
{
// If the token is already attached to this array, then we allow writing.
if (token.IsAttached(this->Internals->GetWriteCount(lock)) ||
token.IsAttached(this->Internals->GetReadCount(lock)))
{
return true;
}
// If there is anyone else waiting at the top of the queue, we cannot access this array.
auto& queue = this->Internals->GetQueue(lock);
if (!queue.empty() && (queue.front() != token))
{
return false;
}
// No one else is waiting, so we can write the array as long as no one else is reading or writing.
return ((*this->Internals->GetWriteCount(lock) < 1) &&
(*this->Internals->GetReadCount(lock) < 1));
}
template <typename T, typename S>
void ArrayHandle<T, S>::WaitToRead(LockType& lock, vtkm::cont::Token& token) const
{
this->Enqueue(lock, token);
// Note that if you deadlocked here, that means that you are trying to do a read operation on an
// array where an object is writing to it.
this->Internals->ConditionVariable.wait(
lock, [&lock, &token, this] { return this->CanRead(lock, token); });
token.Attach(this->Internals,
this->Internals->GetReadCount(lock),
lock,
&this->Internals->ConditionVariable);
// We successfully attached the token. Pop it off the queue.
auto& queue = this->Internals->GetQueue(lock);
if (!queue.empty() && queue.front() == token)
{
queue.pop_front();
}
}
template <typename T, typename S>
void ArrayHandle<T, S>::WaitToWrite(LockType& lock, vtkm::cont::Token& token, bool fakeRead) const
{
this->Enqueue(lock, token);
// Note that if you deadlocked here, that means that you are trying to do a write operation on an
// array where an object is reading or writing to it.
this->Internals->ConditionVariable.wait(
lock, [&lock, &token, this] { return this->CanWrite(lock, token); });
if (!fakeRead)
{
token.Attach(this->Internals,
this->Internals->GetWriteCount(lock),
lock,
&this->Internals->ConditionVariable);
}
else
{
// A current feature limitation of ArrayHandle is that it can only exist on one device at
// a time. Thus, if a read request comes in for a different device, the prepare has to
// get satisfy a write lock to boot the array off the existing device. However, we don't
// want to attach the Token as a write lock because the resulting state is for reading only
// and others might also want to read. So, we have to pretend that this is a read lock even
// though we have to make a change to the array.
//
// The main point is, this condition is a hack that should go away once ArrayHandle supports
// multiple devices at once.
token.Attach(this->Internals,
this->Internals->GetReadCount(lock),
lock,
&this->Internals->ConditionVariable);
}
// We successfully attached the token. Pop it off the queue.
auto& queue = this->Internals->GetQueue(lock);
if (!queue.empty() && queue.front() == token)
{
queue.pop_front();
}
}
template <typename T, typename S>
void ArrayHandle<T, S>::Enqueue(const vtkm::cont::Token& token) const
{
LockType lock = this->GetLock();
this->Enqueue(lock, token);
}
template <typename T, typename S>
void ArrayHandle<T, S>::Enqueue(const LockType& lock, const vtkm::cont::Token& token) const
{
if (token.IsAttached(this->Internals->GetWriteCount(lock)) ||
token.IsAttached(this->Internals->GetReadCount(lock)))
{
// Do not need to enqueue if we are already attached.
return;
}
auto& queue = this->Internals->GetQueue(lock);
if (std::find(queue.begin(), queue.end(), token.GetReference()) != queue.end())
{
// This token is already in the queue.
return;
}
this->Internals->GetQueue(lock).push_back(token.GetReference());
}
}
} // vtkm::cont
#endif //vtk_m_cont_ArrayHandle_hxx

@ -41,11 +41,11 @@ VTKM_STORAGE_INSTANTIATE(vtkm::Float64)
} // namespace internal
#define VTKM_ARRAYHANDLE_INSTANTIATE(Type) \
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<Type, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Vec<Type, 4>, StorageTagBasic>;
#define VTKM_ARRAYHANDLE_INSTANTIATE(Type) \
template class VTKM_CONT_EXPORT ArrayHandle<Type, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagBasic>;
VTKM_ARRAYHANDLE_INSTANTIATE(char)
VTKM_ARRAYHANDLE_INSTANTIATE(vtkm::Int8)

@ -11,6 +11,7 @@
#define vtk_m_cont_ArrayHandleBasic_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/SerializableTypeString.h>
#include <vtkm/cont/Serialization.h>
#include <vtkm/cont/Storage.h>
@ -70,9 +71,6 @@ public:
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagBasic);
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleBasic : public ArrayHandle<T, vtkm::cont::StorageTagBasic>
{
@ -383,14 +381,13 @@ VTKM_STORAGE_EXPORT(vtkm::Float64)
} // namespace internal
#define VTKM_ARRAYHANDLE_EXPORT(Type) \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<Type, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT \
ArrayHandleNewStyle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT \
ArrayHandleNewStyle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT \
ArrayHandleNewStyle<vtkm::Vec<Type, 4>, StorageTagBasic>;
#define VTKM_ARRAYHANDLE_EXPORT(Type) \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<Type, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT \
ArrayHandle<vtkm::Vec<Type, 2>, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT \
ArrayHandle<vtkm::Vec<Type, 3>, StorageTagBasic>; \
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Vec<Type, 4>, StorageTagBasic>;
VTKM_ARRAYHANDLE_EXPORT(char)
VTKM_ARRAYHANDLE_EXPORT(vtkm::Int8)

@ -136,9 +136,6 @@ public:
} // end namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::internal::StorageTagBitField);
/// The ArrayHandleBitField class is a boolean-valued ArrayHandle that is backed
/// by a BitField.
///

@ -284,11 +284,6 @@ public:
};
} // namespace internal
template <typename T, typename ST1, typename ST2, typename ST3>
VTKM_ARRAY_HANDLE_NEW_STYLE(
T,
VTKM_PASS_COMMAS(vtkm::cont::StorageTagCartesianProduct<ST1, ST2, ST3>));
/// ArrayHandleCartesianProduct is a specialization of ArrayHandle. It takes two delegate
/// array handle and makes a new handle that access the corresponding entries
/// in these arrays as a pair.

@ -131,9 +131,6 @@ struct Storage<TargetT, vtkm::cont::StorageTagCast<SourceT, SourceStorage_>>
} // namespace internal
template <typename T1, typename T2, typename S>
VTKM_ARRAY_HANDLE_NEW_STYLE(T1, VTKM_PASS_COMMAS(vtkm::cont::StorageTagCast<T2, S>));
/// \brief Cast the values of an array to the specified type, on demand.
///
/// ArrayHandleCast is a specialization of ArrayHandleTransform. Given an ArrayHandle

@ -402,9 +402,6 @@ struct Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : Storage<T, S
} // namespace internal
template <typename T, typename... Ss>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagCompositeVec<Ss...>);
/// \brief An \c ArrayHandle that combines components from other arrays.
///
/// \c ArrayHandleCompositeVector is a specialization of \c ArrayHandle that

@ -245,9 +245,6 @@ namespace vtkm
namespace cont
{
template <typename T, typename S1, typename S2>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, VTKM_PASS_COMMAS(StorageTagConcatenate<S1, S2>));
template <typename ArrayHandleType1, typename ArrayHandleType2>
class ArrayHandleConcatenate
: public vtkm::cont::ArrayHandle<typename ArrayHandleType1::ValueType,

@ -51,9 +51,6 @@ struct Storage<T, vtkm::cont::StorageTagConstant> : Storage<T, StorageTagConstan
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagConstant);
/// \brief An array handle with a constant value.
///
/// ArrayHandleConstant is an implicit array handle with a constant value. A

@ -120,9 +120,6 @@ struct Storage<T, typename std::enable_if<CanCount<T>::value, vtkm::cont::Storag
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagCounting);
/// ArrayHandleCounting is a specialization of ArrayHandle. By default it
/// contains a increment value, that is increment for each step between zero
/// and the passed in length

@ -590,11 +590,6 @@ struct DecoratorHandleTraits
} // namespace internal
template <typename T, typename DecoratorImplT, typename... ArrayTs>
VTKM_ARRAY_HANDLE_NEW_STYLE(
T,
VTKM_PASS_COMMAS(internal::StorageTagDecorator<DecoratorImplT, ArrayTs...>));
/// \brief A fancy ArrayHandle that can be used to modify the results from one
/// or more source ArrayHandle.
///

@ -144,10 +144,6 @@ struct ArrayHandleDiscardTraits
} // end namespace internal
// This can go away once ArrayHandle is replaced with ArrayHandleNewStyle
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::internal::StorageTagDiscard);
/// ArrayHandleDiscard is a write-only array that discards all data written to
/// it. This can be used to save memory when a filter provides optional outputs
/// that are not needed.

@ -170,9 +170,6 @@ namespace vtkm
namespace cont
{
template <typename T, typename ArrayT>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagExtractComponent<ArrayT>);
/// \brief A fancy ArrayHandle that turns a vector array into a scalar array by
/// slicing out a single component of each vector.
///

@ -14,11 +14,17 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
namespace vtkm
{
namespace cont
{
template <typename T>
VTKM_ARRAY_HANDLE_DEPRECATED(VTKM_PASS_COMMAS(vtkm::Vec<T, 3>),
vtkm::cont::internal::StorageTagExtrude);
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleExtrudeCoords
: public vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>, internal::StorageTagExtrude>

@ -13,11 +13,16 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/StorageExtrude.h>
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
namespace vtkm
{
namespace cont
{
template <typename T>
VTKM_ARRAY_HANDLE_DEPRECATED(T, vtkm::cont::internal::StorageTagExtrude);
template <typename T>
class VTKM_ALWAYS_EXPORT ArrayHandleExtrudeField
: public vtkm::cont::ArrayHandle<T, internal::StorageTagExtrude>

@ -174,9 +174,6 @@ public:
} // namespace internal
template <typename T, vtkm::IdComponent N, typename S>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, VTKM_PASS_COMMAS(vtkm::cont::StorageTagGroupVec<S, N>));
/// \brief Fancy array handle that groups values into vectors.
///
/// It is sometimes the case that an array is stored such that consecutive

@ -211,9 +211,6 @@ public:
} // namespace internal
template <typename T, typename S1, typename S2>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, VTKM_PASS_COMMAS(vtkm::cont::StorageTagGroupVecVariable<S1, S2>));
/// \brief Fancy array handle that groups values into vectors of different sizes.
///
/// It is sometimes the case that you need to run a worklet with an input or

@ -160,11 +160,6 @@ struct ArrayHandleImplicitTraits
} // namespace detail
// This can go away once ArrayHandle is replaced with ArrayHandleNewStyle
template <typename PortalType>
VTKM_ARRAY_HANDLE_NEW_STYLE(typename PortalType::ValueType,
vtkm::cont::StorageTagImplicit<PortalType>);
/// \brief An \c ArrayHandle that computes values on the fly.
///
/// \c ArrayHandleImplicit is a specialization of ArrayHandle.

@ -45,9 +45,6 @@ struct Storage<vtkm::Id, vtkm::cont::StorageTagIndex> : Storage<vtkm::Id, Storag
} // namespace internal
template <>
VTKM_ARRAY_HANDLE_NEW_STYLE(vtkm::Id, vtkm::cont::StorageTagIndex);
/// \brief An implicit array handle containing the its own indices.
///
/// \c ArrayHandleIndex is an implicit array handle containing the values

@ -353,9 +353,6 @@ struct ArrayHandleMultiplexerTraits
};
} // namespace detail
template <typename T, typename... Ss>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagMultiplexer<Ss...>);
/// \brief An ArrayHandle that can behave like several other handles.
///
/// An \c ArrayHandleMultiplexer simply redirects its calls to another \c ArrayHandle. However

@ -172,9 +172,6 @@ public:
} // namespace internal
template <typename T, typename IS, typename VS>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, VTKM_PASS_COMMAS(vtkm::cont::StorageTagPermutation<IS, VS>));
/// \brief Implicitly permutes the values in an array.
///
/// ArrayHandlePermutation is a specialization of ArrayHandle. It takes two

@ -529,9 +529,6 @@ public:
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::internal::StorageTagRecombineVec);
/// \brief A grouping of `ArrayHandleStride`s into an `ArrayHandle` of `Vec`s.
///
/// The main intention of `ArrayHandleStride` is to pull out a component of an

@ -163,9 +163,6 @@ public:
} // namespace internal
template <typename T, typename S>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagReverse<S>);
/// \brief Reverse the order of an array, on demand.
///
/// ArrayHandleReverse is a specialization of ArrayHandle. Given an ArrayHandle,

@ -204,9 +204,6 @@ public:
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagSOA);
/// \brief An `ArrayHandle` that for Vecs stores each component in a separate physical array.
///
/// `ArrayHandleSOA` behaves like a regular `ArrayHandle` (with a basic storage) except that

@ -33,17 +33,17 @@ template class VTKM_CONT_EXPORT Storage<vtkm::Float64, StorageTagStride>;
} // namespace internal
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<char, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Int8, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::UInt8, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Int16, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::UInt16, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Int32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::UInt32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Int64, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::UInt64, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Float32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandleNewStyle<vtkm::Float64, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<char, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Int8, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::UInt8, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Int16, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::UInt16, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Int32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::UInt32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Int64, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::UInt64, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Float32, StorageTagStride>;
template class VTKM_CONT_EXPORT ArrayHandle<vtkm::Float64, StorageTagStride>;
}
} // namespace vtkm::cont

@ -205,9 +205,6 @@ public:
} // namespace internal
template <typename T>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagStride);
/// \brief An `ArrayHandle` that accesses a basic array with strides and offsets.
///
/// `ArrayHandleStride` is a simple `ArrayHandle` that accesses data with a prescribed
@ -393,19 +390,17 @@ extern template class VTKM_CONT_TEMPLATE_EXPORT Storage<vtkm::Float64, StorageTa
} // namespace internal
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<char, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::Int8, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::UInt8, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::Int16, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::UInt16, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::Int32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::UInt32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::Int64, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandleNewStyle<vtkm::UInt64, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT
ArrayHandleNewStyle<vtkm::Float32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT
ArrayHandleNewStyle<vtkm::Float64, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<char, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Int8, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::UInt8, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Int16, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::UInt16, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Int32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::UInt32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Int64, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::UInt64, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Float32, StorageTagStride>;
extern template class VTKM_CONT_TEMPLATE_EXPORT ArrayHandle<vtkm::Float64, StorageTagStride>;
}
} // namespace vtkm::cont

@ -416,9 +416,6 @@ public:
} // namespace internal
template <typename T, typename A, typename F, typename IF>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, VTKM_PASS_COMMAS(internal::StorageTagTransform<A, F, IF>));
/// \brief Implicitly transform values of one array to another with a functor.
///
/// ArrayHandleTransforms is a specialization of ArrayHandle. It takes a

@ -37,9 +37,6 @@ struct Storage<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>
} // namespace internal
template <>
VTKM_ARRAY_HANDLE_NEW_STYLE(vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints);
/// ArrayHandleUniformPointCoordinates is a specialization of ArrayHandle. It
/// contains the information necessary to compute the point coordinates in a
/// uniform orthogonal grid (extent, origin, and spacing) and implicitly

@ -196,10 +196,6 @@ public:
} // namespace internal
// This can go away once ArrayHandle is replaced with ArrayHandleNewStyle
template <typename T, typename S>
VTKM_ARRAY_HANDLE_NEW_STYLE(T, vtkm::cont::StorageTagView<S>);
template <typename ArrayHandleType>
class ArrayHandleView
: public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,

@ -15,9 +15,10 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/cont/StorageVirtual.h>
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
#include <memory>
#ifdef VTKM_NO_DEPRECATED_VIRTUAL
@ -29,8 +30,11 @@ namespace vtkm
namespace cont
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <typename T>
VTKM_ARRAY_HANDLE_DEPRECATED(T, vtkm::cont::StorageTagVirtual);
template <typename T>
class VTKM_ALWAYS_EXPORT VTKM_DEPRECATED(1.6) ArrayHandleVirtual
: public vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>

@ -201,10 +201,6 @@ public:
};
} // namespace internal
template <typename T1, typename S1, typename T2, typename S2>
VTKM_ARRAY_HANDLE_NEW_STYLE(VTKM_PASS_COMMAS(vtkm::Pair<T1, T2>),
VTKM_PASS_COMMAS(vtkm::cont::StorageTagZip<S1, S2>));
/// ArrayHandleZip is a specialization of ArrayHandle. It takes two delegate
/// array handle and makes a new handle that access the corresponding entries
/// in these arrays as a pair.

@ -127,7 +127,6 @@ set(headers
)
set(template_sources
ArrayHandle.hxx
ArrayRangeCompute.hxx # Deprecated, replaced with ArrayRangeComputeTemplate.h
CellSetExplicit.hxx
CellSetExtrude.hxx

@ -16,6 +16,9 @@
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/internal/ArrayTransfer.h>
#include <vtkm/cont/internal/StorageDeprecated.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>

@ -15,6 +15,8 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
#include <vtkm/cont/internal/StorageDeprecated.h>
#include <vtkm/cont/internal/TransferInfo.h>
#include <vtkm/internal/ArrayPortalVirtual.h>

@ -12,8 +12,9 @@
#include <vtkm/cont/StorageVirtual.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/TransferInfo.h>
#include <vtkm/cont/internal/ArrayTransfer.h>
#include <vtkm/cont/internal/TransferInfo.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <vtkm/cont/internal/VirtualObjectTransferShareWithControl.h>

File diff suppressed because it is too large Load Diff

@ -9,6 +9,7 @@
##============================================================================
set(headers
ArrayHandleDeprecated.h
ArrayHandleExecutionManager.h
ArrayPortalFromIterators.h
ArrayTransfer.h

@ -25,12 +25,12 @@ namespace vtkm
namespace cont
{
template <typename T, typename S>
class ArrayHandle;
namespace internal
{
template <typename T, typename S>
class ArrayHandleDeprecated;
namespace detail
{
@ -98,7 +98,7 @@ class StorageDeprecated
using T = typename detail::StorageTemplateParams<StorageType>::ValueType;
using StorageTag = typename detail::StorageTemplateParams<StorageType>::StorageTag;
using ArrayType = vtkm::cont::ArrayHandle<T, StorageTag>;
using ArrayType = vtkm::cont::internal::ArrayHandleDeprecated<T, StorageTag>;
VTKM_CONT static ArrayType GetArray(const vtkm::cont::internal::Buffer* buffers)
{

@ -8,6 +8,7 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
#include <vtkm/cont/internal/Buffer.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>

@ -29,6 +29,7 @@
#include <vtkm/cont/RuntimeDeviceInformation.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/cont/internal/ArrayPortalFromIterators.h>
#include <vtkm/cont/internal/VirtualObjectTransfer.h>
#include <vtkm/cont/testing/Testing.h>