diff --git a/vtkm/cont/ArrayHandle.h b/vtkm/cont/ArrayHandle.h index f6cdfd90a..33558b904 100644 --- a/vtkm/cont/ArrayHandle.h +++ b/vtkm/cont/ArrayHandle.h @@ -26,9 +26,9 @@ #include #include #include +#include #include -#include #include #include @@ -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 -VTKM_CONT_EXPORT -vtkm::cont::ArrayHandle -make_ArrayHandle(const T *array, - vtkm::Id length, - StorageTag) -{ - typedef vtkm::cont::ArrayHandle ArrayHandleType; - typedef typename ArrayHandleType::PortalConstControl PortalType; - return ArrayHandleType(PortalType(array, array+length)); -} template VTKM_CONT_EXPORT -vtkm::cont::ArrayHandle -make_ArrayHandle(const T *array, vtkm::Id length) +vtkm::cont::ArrayHandle +make_ArrayHandle(const T *array, + vtkm::Id length) { - return make_ArrayHandle(array, - length, - VTKM_DEFAULT_STORAGE_TAG()); + typedef vtkm::cont::ArrayHandle + ArrayHandleType; + typedef vtkm::cont::internal::Storage + 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 Allocator> VTKM_CONT_EXPORT -vtkm::cont::ArrayHandle -make_ArrayHandle(const std::vector &array, - StorageTag) -{ - typedef vtkm::cont::ArrayHandle ArrayHandleType; - typedef typename ArrayHandleType::PortalConstControl PortalType; - return ArrayHandleType(PortalType(&array.front(), &array.back() + 1)); -} -template -VTKM_CONT_EXPORT -vtkm::cont::ArrayHandle +vtkm::cont::ArrayHandle make_ArrayHandle(const std::vector &array) { - return make_ArrayHandle(array, VTKM_DEFAULT_STORAGE_TAG()); + return make_ArrayHandle(&array.front(), array.size()); } } diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.h b/vtkm/cont/ArrayHandleUniformPointCoordinates.h index 35a215418..ec178c9d0 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.h +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.h @@ -123,10 +123,12 @@ public: typedef vtkm::Vec 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 StorageType; + + typedef vtkm::cont::ArrayHandle 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))) { } }; diff --git a/vtkm/cont/StorageBasic.h b/vtkm/cont/StorageBasic.h index 9307c88a2..8d90b17bc 100644 --- a/vtkm/cont/StorageBasic.h +++ b/vtkm/cont/StorageBasic.h @@ -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(array)), + NumberOfValues(numberOfValues), + AllocatedSize(numberOfValues), + DeallocateOnRelease(false), + ReadOnly(true) { } + VTKM_CONT_EXPORT ~Storage() { this->ReleaseResources(); } + VTKM_CONT_EXPORT + Storage(const Storage &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 &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 &src); - void operator=(const Storage &src); - ValueType *Array; vtkm::Id NumberOfValues; vtkm::Id AllocatedSize; + bool DeallocateOnRelease; + bool ReadOnly; }; } // namespace internal diff --git a/vtkm/cont/StorageImplicit.h b/vtkm/cont/StorageImplicit.h index 8902648ab..185ee76ec 100644 --- a/vtkm/cont/StorageImplicit.h +++ b/vtkm/cont/StorageImplicit.h @@ -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 @@ -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; diff --git a/vtkm/cont/testing/UnitTestArrayHandle.cxx b/vtkm/cont/testing/UnitTestArrayHandle.cxx index a8ee60c35..511863efc 100644 --- a/vtkm/cont/testing/UnitTestArrayHandle.cxx +++ b/vtkm/cont/testing/UnitTestArrayHandle.cxx @@ -53,10 +53,10 @@ struct TryArrayHandleType array[index] = TestValue(index, T()); } - typename vtkm::cont::ArrayHandle::PortalControl arrayPortal( - &array[0], &array[ARRAY_SIZE]); + vtkm::cont::internal::Storage + arrayStorage(array, ARRAY_SIZE); - vtkm::cont::ArrayHandle arrayHandle(arrayPortal); + vtkm::cont::ArrayHandle arrayHandle(arrayStorage); VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == ARRAY_SIZE, "ArrayHandle has wrong number of entries."); diff --git a/vtkm/cont/testing/UnitTestArrayHandleCompositeVector.cxx b/vtkm/cont/testing/UnitTestArrayHandleCompositeVector.cxx index 8f771cdd0..f3cd61409 100644 --- a/vtkm/cont/testing/UnitTestArrayHandleCompositeVector.cxx +++ b/vtkm/cont/testing/UnitTestArrayHandleCompositeVector.cxx @@ -70,7 +70,7 @@ MakeInputArray(int arrayId) // Make an array handle that points to this buffer. typedef vtkm::cont::ArrayHandle 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 diff --git a/vtkm/cont/testing/UnitTestPointCoordinates.cxx b/vtkm/cont/testing/UnitTestPointCoordinates.cxx index 63477a720..04c416869 100644 --- a/vtkm/cont/testing/UnitTestPointCoordinates.cxx +++ b/vtkm/cont/testing/UnitTestPointCoordinates.cxx @@ -102,7 +102,7 @@ struct TestPointCoordinatesArray std::cout << " Creating and checking array handle" << std::endl; vtkm::cont::ArrayHandle array = - vtkm::cont::make_ArrayHandle(buffer, StorageTag()); + vtkm::cont::make_ArrayHandle(buffer); CheckArray()(array); std::cout << " Creating and checking PointCoordinatesArray" << std::endl; diff --git a/vtkm/cont/testing/UnitTestStorageImplicit.cxx b/vtkm/cont/testing/UnitTestStorageImplicit.cxx index b0d48c415..486c7eadf 100644 --- a/vtkm/cont/testing/UnitTestStorageImplicit.cxx +++ b/vtkm/cont/testing/UnitTestStorageImplicit.cxx @@ -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 {