Remove UserPortal from ArrayHandle.

The UserPortal in ArrayHandle was used to copy a pointer the user
created into an ArrayHandle to use in VTK-m algorithms. However, this is
only really valid for a basic storage, so the functionality has been
moved there, and you have to construct an ArrayHandle with a storage
instead of an array portal.
This commit is contained in:
Kenneth Moreland 2015-04-27 20:01:05 -04:00
parent f089f0f0cf
commit a2c280993c
8 changed files with 152 additions and 167 deletions

@ -26,9 +26,9 @@
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/ErrorControlInternal.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/StorageBasic.h>
#include <vtkm/cont/internal/ArrayHandleExecutionManager.h>
#include <vtkm/cont/internal/ArrayTransfer.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <boost/concept_check.hpp>
@ -142,20 +142,19 @@ public:
///
VTKM_CONT_EXPORT ArrayHandle() : Internals(new InternalStruct)
{
this->Internals->UserPortalValid = false;
this->Internals->ControlArrayValid = false;
this->Internals->ExecutionArrayValid = false;
}
/// Constructs an ArrayHandle pointing to the data in the given array portal.
/// 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.
///
VTKM_CONT_EXPORT ArrayHandle(const PortalConstControl& userData)
ArrayHandle(const StorageType &storage)
: Internals(new InternalStruct)
{
this->Internals->UserPortal = userData;
this->Internals->UserPortalValid = true;
this->Internals->ControlArrayValid = false;
this->Internals->ControlArray = storage;
this->Internals->ControlArrayValid = true;
this->Internals->ExecutionArrayValid = false;
}
@ -164,12 +163,7 @@ public:
VTKM_CONT_EXPORT PortalControl GetPortalControl()
{
this->SyncControlArray();
if (this->Internals->UserPortalValid)
{
throw vtkm::cont::ErrorControlBadValue(
"ArrayHandle has a read-only control portal.");
}
else if (this->Internals->ControlArrayValid)
if (this->Internals->ControlArrayValid)
{
// If the user writes into the iterator we return, then the execution
// array will become invalid. Play it safe and release the execution
@ -189,11 +183,7 @@ public:
VTKM_CONT_EXPORT PortalConstControl GetPortalConstControl() const
{
this->SyncControlArray();
if (this->Internals->UserPortalValid)
{
return this->Internals->UserPortal;
}
else if (this->Internals->ControlArrayValid)
if (this->Internals->ControlArrayValid)
{
return this->Internals->ControlArray.GetPortalConst();
}
@ -208,18 +198,13 @@ public:
///
VTKM_CONT_EXPORT vtkm::Id GetNumberOfValues() const
{
if (this->Internals->UserPortalValid)
{
return this->Internals->UserPortal.GetNumberOfValues();
}
else if (this->Internals->ControlArrayValid)
if (this->Internals->ControlArrayValid)
{
return this->Internals->ControlArray.GetNumberOfValues();
}
else if (this->Internals->ExecutionArrayValid)
{
return
this->Internals->ExecutionArray->GetNumberOfValues();
return this->Internals->ExecutionArray->GetNumberOfValues();
}
else
{
@ -239,7 +224,6 @@ public:
void Allocate(vtkm::Id numberOfValues)
{
this->ReleaseResourcesExecutionInternal();
this->Internals->UserPortalValid = false;
this->Internals->ControlArray.Allocate(numberOfValues);
this->Internals->ControlArrayValid = true;
}
@ -258,11 +242,6 @@ public:
if (numberOfValues < originalNumberOfValues)
{
if (this->Internals->UserPortalValid)
{
throw vtkm::cont::ErrorControlBadValue(
"ArrayHandle has a read-only control portal.");
}
if (this->Internals->ControlArrayValid)
{
this->Internals->ControlArray.Shrink(numberOfValues);
@ -303,9 +282,6 @@ public:
{
this->ReleaseResourcesExecutionInternal();
// Forget about any user iterators.
this->Internals->UserPortalValid = false;
if (this->Internals->ControlArrayValid)
{
this->Internals->ControlArray.ReleaseResources();
@ -330,14 +306,6 @@ public:
{
// Nothing to do, data already loaded.
}
else if (this->Internals->UserPortalValid)
{
VTKM_ASSERT_CONT(!this->Internals->ControlArrayValid);
this->PrepareForDevice(DeviceAdapterTag());
this->Internals->ExecutionArray->LoadDataForInput(
this->Internals->UserPortal);
this->Internals->ExecutionArrayValid = true;
}
else if (this->Internals->ControlArrayValid)
{
this->PrepareForDevice(DeviceAdapterTag());
@ -371,7 +339,6 @@ public:
// Invalidate any control arrays.
// Should the control array resource be released? Probably not a good
// idea when shared with execution.
this->Internals->UserPortalValid = false;
this->Internals->ControlArrayValid = false;
this->PrepareForDevice(DeviceAdapterTag());
@ -405,14 +372,6 @@ public:
{
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
if (this->Internals->UserPortalValid)
{
throw vtkm::cont::ErrorControlBadValue(
"In place execution cannot be used with an ArrayHandle that has "
"user arrays because this might write data back into user space "
"unexpectedly. Copy the data to a new array first.");
}
// This code is similar to PrepareForInput except that we have to give a
// writable portal instead of the const portal to the execution array
// manager so that the data can (potentially) be written to.
@ -441,26 +400,9 @@ public:
return this->Internals->ExecutionArray->GetPortalExecution(DeviceAdapterTag());
}
// protected:
/// 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)
: Internals(new InternalStruct)
{
this->Internals->UserPortalValid = false;
this->Internals->ControlArray = storage;
this->Internals->ControlArrayValid = true;
this->Internals->ExecutionArrayValid = false;
}
// private:
// private:
struct InternalStruct
{
PortalConstControl UserPortal;
bool UserPortalValid;
StorageType ControlArray;
bool ControlArrayValid;
@ -527,8 +469,7 @@ public:
///
VTKM_CONT_EXPORT void SyncControlArray() const
{
if (!this->Internals->UserPortalValid
&& !this->Internals->ControlArrayValid)
if (!this->Internals->ControlArrayValid)
{
// Need to change some state that does not change the logical state from
// an external point of view.
@ -548,14 +489,6 @@ public:
internals->ControlArrayValid = true;
}
}
else
{
// It should never be the case that both the user and control array are
// valid.
VTKM_ASSERT_CONT(!this->Internals->UserPortalValid
|| !this->Internals->ControlArrayValid);
// Nothing to do.
}
}
VTKM_CONT_EXPORT
@ -572,54 +505,29 @@ public:
};
/// A convenience function for creating an ArrayHandle from a standard C array.
/// Unless properly specialized, this only works with storage types that use an
/// array portal that accepts a pair of pointers to signify the beginning and
/// end of the array.
///
template<typename T, typename StorageTag>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<T, StorageTag>
make_ArrayHandle(const T *array,
vtkm::Id length,
StorageTag)
{
typedef vtkm::cont::ArrayHandle<T, StorageTag> ArrayHandleType;
typedef typename ArrayHandleType::PortalConstControl PortalType;
return ArrayHandleType(PortalType(array, array+length));
}
template<typename T>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<T, VTKM_DEFAULT_STORAGE_TAG>
make_ArrayHandle(const T *array, vtkm::Id length)
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>
make_ArrayHandle(const T *array,
vtkm::Id length)
{
return make_ArrayHandle(array,
length,
VTKM_DEFAULT_STORAGE_TAG());
typedef vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>
ArrayHandleType;
typedef vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic>
StorageType;
return ArrayHandleType(StorageType(array, length));
}
/// A convenience function for creating an ArrayHandle from an std::vector.
/// Unless properly specialized, this only works with storage types that use an
/// array portal that accepts a pair of pointers to signify the beginning and
/// end of the array.
///
template<typename T,
typename Allocator,
typename StorageTag>
typename Allocator>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<T, StorageTag>
make_ArrayHandle(const std::vector<T,Allocator> &array,
StorageTag)
{
typedef vtkm::cont::ArrayHandle<T, StorageTag> ArrayHandleType;
typedef typename ArrayHandleType::PortalConstControl PortalType;
return ArrayHandleType(PortalType(&array.front(), &array.back() + 1));
}
template<typename T, typename Allocator>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<T, VTKM_DEFAULT_STORAGE_TAG>
vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagBasic>
make_ArrayHandle(const std::vector<T,Allocator> &array)
{
return make_ArrayHandle(array, VTKM_DEFAULT_STORAGE_TAG());
return make_ArrayHandle(&array.front(), array.size());
}
}

@ -123,10 +123,12 @@ public:
typedef vtkm::Vec<vtkm::FloatDefault,3> ValueType;
private:
typedef vtkm::cont::ArrayHandle<
ValueType,
vtkm::cont::StorageTagImplicit<
internal::ArrayPortalUniformPointCoordinates> > Superclass;
typedef vtkm::cont::StorageTagImplicit<
internal::ArrayPortalUniformPointCoordinates> StorageTag;
typedef vtkm::cont::internal::Storage<ValueType, StorageTag> StorageType;
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> Superclass;
public:
VTKM_CONT_EXPORT
@ -137,7 +139,9 @@ public:
ValueType origin,
ValueType spacing)
: Superclass(
internal::ArrayPortalUniformPointCoordinates(extent, origin, spacing))
StorageType(internal::ArrayPortalUniformPointCoordinates(extent,
origin,
spacing)))
{ }
};

@ -63,20 +63,67 @@ public:
public:
Storage() : Array(NULL), NumberOfValues(0), AllocatedSize(0) { }
VTKM_CONT_EXPORT
Storage(const ValueType *array = NULL, vtkm::Id numberOfValues = 0)
: Array(const_cast<ValueType *>(array)),
NumberOfValues(numberOfValues),
AllocatedSize(numberOfValues),
DeallocateOnRelease(false),
ReadOnly(true) { }
VTKM_CONT_EXPORT
~Storage()
{
this->ReleaseResources();
}
VTKM_CONT_EXPORT
Storage(const Storage<ValueType, StorageTagBasic> &src)
: Array(src.Array),
NumberOfValues(src.NumberOfValues),
AllocatedSize(src.AllocatedSize),
DeallocateOnRelease(false),
ReadOnly(src.ReadOnly)
{
if (src.DeallocateOnRelease)
{
throw vtkm::cont::ErrorControlBadValue(
"Attempted to copy a storage array that needs deallocation. "
"This is disallowed to prevent complications with deallocation.");
}
}
VTKM_CONT_EXPORT
Storage &operator=(const Storage<ValueType, StorageTagBasic> &src)
{
if (src.DeallocateOnRelease)
{
throw vtkm::cont::ErrorControlBadValue(
"Attempted to copy a storage array that needs deallocation. "
"This is disallowed to prevent complications with deallocation.");
}
this->ReleaseResources();
this->Array = src.Array;
this->NumberOfValues = src.NumberOfValues;
this->AllocatedSize = src.AllocatedSize;
this->DeallocateOnRelease = src.DeallocateOnRelease;
this->ReadOnly = src.ReadOnly;
return *this;
}
VTKM_CONT_EXPORT
void ReleaseResources()
{
if (this->NumberOfValues > 0)
{
VTKM_ASSERT_CONT(this->Array != NULL);
AllocatorType allocator;
allocator.deallocate(this->Array, this->AllocatedSize);
if (this->DeallocateOnRelease)
{
AllocatorType allocator;
allocator.deallocate(this->Array, this->AllocatedSize);
}
this->Array = NULL;
this->NumberOfValues = 0;
this->AllocatedSize = 0;
@ -87,9 +134,11 @@ public:
}
}
VTKM_CONT_EXPORT
void Allocate(vtkm::Id numberOfValues)
{
if (numberOfValues <= this->AllocatedSize)
if ((numberOfValues <= this->AllocatedSize)
&& !this->ReadOnly)
{
this->NumberOfValues = numberOfValues;
return;
@ -120,15 +169,25 @@ public:
throw vtkm::cont::ErrorControlOutOfMemory(
"Could not allocate basic control array.");
}
this->DeallocateOnRelease = true;
this->ReadOnly = false;
}
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const
{
return this->NumberOfValues;
}
VTKM_CONT_EXPORT
void Shrink(vtkm::Id numberOfValues)
{
if (this->ReadOnly)
{
throw vtkm::cont::ErrorControlBadValue("Cannot shrink read-only array.");
}
if (numberOfValues > this->GetNumberOfValues())
{
throw vtkm::cont::ErrorControlBadValue(
@ -138,11 +197,18 @@ public:
this->NumberOfValues = numberOfValues;
}
VTKM_CONT_EXPORT
PortalType GetPortal()
{
if (this->ReadOnly)
{
throw vtkm::cont::ErrorControlBadValue(
"Tried to access read-only array as read-write.");
}
return PortalType(this->Array, this->Array + this->NumberOfValues);
}
VTKM_CONT_EXPORT
PortalConstType GetPortalConst() const
{
return PortalConstType(this->Array, this->Array + this->NumberOfValues);
@ -157,6 +223,7 @@ public:
/// a VTK-m object around. Obviously the caller becomes responsible for
/// destroying the memory.
///
VTKM_CONT_EXPORT
ValueType *StealArray()
{
ValueType *saveArray = this->Array;
@ -167,13 +234,11 @@ public:
}
private:
// Not implemented.
Storage(const Storage<ValueType, StorageTagBasic> &src);
void operator=(const Storage<ValueType, StorageTagBasic> &src);
ValueType *Array;
vtkm::Id NumberOfValues;
vtkm::Id AllocatedSize;
bool DeallocateOnRelease;
bool ReadOnly;
};
} // namespace internal

@ -66,41 +66,44 @@ public:
typedef void *IteratorType;
};
VTKM_CONT_EXPORT
Storage(const PortalConstType &portal = PortalConstType())
: Portal(portal) { }
// All these methods do nothing but raise errors.
VTKM_CONT_EXPORT
PortalType GetPortal()
{
throw vtkm::cont::ErrorControlBadValue("Implicit arrays are read-only.");
}
VTKM_CONT_EXPORT
PortalConstType GetPortalConst() const
{
// This does not work because the ArrayHandle holds the constant
// ArrayPortal, not the storage.
throw vtkm::cont::ErrorControlBadValue(
"Implicit storage does not store array portal. "
"Perhaps you did not set the ArrayPortal when "
"constructing the ArrayHandle.");
return this->Portal;
}
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const
{
// This does not work because the ArrayHandle holds the constant
// ArrayPortal, not the Storage.
throw vtkm::cont::ErrorControlBadValue(
"Implicit storage does not store array portal. "
"Perhaps you did not set the ArrayPortal when "
"constructing the ArrayHandle.");
return this->Portal.GetNumberOfValues();
}
VTKM_CONT_EXPORT
void Allocate(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue("Implicit arrays are read-only.");
}
VTKM_CONT_EXPORT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue("Implicit arrays are read-only.");
}
VTKM_CONT_EXPORT
void ReleaseResources()
{
throw vtkm::cont::ErrorControlBadValue("Implicit arrays are read-only.");
}
private:
PortalConstType Portal;
};
template<typename T, class ArrayPortalType, class DeviceAdapterTag>
@ -118,24 +121,28 @@ public:
typedef PortalControl PortalExecution;
typedef PortalConstControl PortalConstExecution;
VTKM_CONT_EXPORT
ArrayTransfer() : PortalValid(false) { }
VTKM_CONT_EXPORT vtkm::Id GetNumberOfValues() const
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT_CONT(this->PortalValid);
return this->Portal.GetNumberOfValues();
}
VTKM_CONT_EXPORT void LoadDataForInput(const PortalConstControl& portal)
VTKM_CONT_EXPORT
void LoadDataForInput(const PortalConstControl& portal)
{
this->Portal = portal;
this->PortalValid = true;
}
VTKM_CONT_EXPORT void LoadDataForInput(const StorageType& vtkmNotUsed(controlArray) )
VTKM_CONT_EXPORT
void LoadDataForInput(const StorageType& controlArray)
{
throw vtkm::cont::ErrorControlBadValue(
"Implicit arrays have no storage, you need to load from a portal");
this->Portal = controlArray.GetPortalConst();
this->PortalValid = true;
}
VTKM_CONT_EXPORT
@ -145,37 +152,41 @@ public:
"Implicit arrays cannot be used for output or in place.");
}
VTKM_CONT_EXPORT void AllocateArrayForOutput(
StorageType &vtkmNotUsed(controlArray),
vtkm::Id vtkmNotUsed(numberOfValues))
VTKM_CONT_EXPORT
void AllocateArrayForOutput(StorageType &vtkmNotUsed(controlArray),
vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue(
"Implicit arrays cannot be used for output.");
}
VTKM_CONT_EXPORT void RetrieveOutputData(
StorageType &vtkmNotUsed(controlArray)) const
VTKM_CONT_EXPORT
void RetrieveOutputData(StorageType &vtkmNotUsed(controlArray)) const
{
throw vtkm::cont::ErrorControlBadValue(
"Implicit arrays cannot be used for output.");
}
VTKM_CONT_EXPORT void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
VTKM_CONT_EXPORT
void Shrink(vtkm::Id vtkmNotUsed(numberOfValues))
{
throw vtkm::cont::ErrorControlBadValue("Implicit arrays cannot be resized.");
}
VTKM_CONT_EXPORT PortalExecution GetPortalExecution()
VTKM_CONT_EXPORT
PortalExecution GetPortalExecution()
{
throw vtkm::cont::ErrorControlBadValue(
"Implicit arrays are read-only. (Get the const portal.)");
}
VTKM_CONT_EXPORT PortalConstExecution GetPortalConstExecution() const
VTKM_CONT_EXPORT
PortalConstExecution GetPortalConstExecution() const
{
VTKM_ASSERT_CONT(this->PortalValid);
return this->Portal;
}
VTKM_CONT_EXPORT void ReleaseResources() { }
VTKM_CONT_EXPORT
void ReleaseResources() { }
private:
PortalConstExecution Portal;

@ -53,10 +53,10 @@ struct TryArrayHandleType
array[index] = TestValue(index, T());
}
typename vtkm::cont::ArrayHandle<T>::PortalControl arrayPortal(
&array[0], &array[ARRAY_SIZE]);
vtkm::cont::internal::Storage<T,vtkm::cont::StorageTagBasic>
arrayStorage(array, ARRAY_SIZE);
vtkm::cont::ArrayHandle<T> arrayHandle(arrayPortal);
vtkm::cont::ArrayHandle<T> arrayHandle(arrayStorage);
VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == ARRAY_SIZE,
"ArrayHandle has wrong number of entries.");

@ -70,7 +70,7 @@ MakeInputArray(int arrayId)
// Make an array handle that points to this buffer.
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> ArrayHandleType;
ArrayHandleType bufferHandle =
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE, StorageTag());
vtkm::cont::make_ArrayHandle(buffer, ARRAY_SIZE);
// When this function returns, the array is going to go out of scope, which
// will invalidate the array handle we just created. So copy to a new buffer

@ -102,7 +102,7 @@ struct TestPointCoordinatesArray
std::cout << " Creating and checking array handle" << std::endl;
vtkm::cont::ArrayHandle<Vector3,StorageTag> array =
vtkm::cont::make_ArrayHandle(buffer, StorageTag());
vtkm::cont::make_ArrayHandle(buffer);
CheckArray()(array);
std::cout << " Creating and checking PointCoordinatesArray" << std::endl;

@ -74,13 +74,10 @@ struct TemplatedTests
{
StorageType arrayStorage;
try
{
arrayStorage.GetNumberOfValues();
VTKM_TEST_ASSERT(false == true,
"Implicit Storage GetNumberOfValues method didn't throw error.");
}
catch(vtkm::cont::ErrorControlBadValue e) {}
// The implicit portal defined for this test always returns 1 for the
// number of values. We should get that.
VTKM_TEST_ASSERT(arrayStorage.GetNumberOfValues() == 1,
"Implicit Storage GetNumberOfValues returned wrong size.");
try
{