Make ArrayHandle work better when uninitialized

Fixed a problem where ArrayHandle would cause a crash if you tried to
get the control portal on an uninitialized array (it was supposed to
throw an exception).

Also changed some methods in ArrayHandle so that they work resonably
without error when used with an uninitialized array. Specifically, the
aforementioned behavior was changed to "allocate" an array of size 0
(that is, call Allocate(0) on the storage object) to return an empty
array portal rather than throw an error. Although this use of
ArrayHandle can be considered erroneous, it is convenient the get an
empty array portal when dealing with a potentially unallocated array
rather than create a special condition.
This commit is contained in:
Kenneth Moreland 2015-02-09 14:54:04 -07:00
parent 3e3596ab7a
commit c224c2b98a
2 changed files with 39 additions and 6 deletions

@ -24,6 +24,7 @@
#include <vtkm/cont/Assert.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/ErrorControlInternal.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/internal/ArrayHandleExecutionManager.h>
@ -178,7 +179,8 @@ public:
}
else
{
throw vtkm::cont::ErrorControlBadValue("ArrayHandle contains no data.");
throw vtkm::cont::ErrorControlInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
@ -197,7 +199,8 @@ public:
}
else
{
throw vtkm::cont::ErrorControlBadValue("ArrayHandle contains no data.");
throw vtkm::cont::ErrorControlInternal(
"ArrayHandle::SyncControlArray did not make control array valid.");
}
}
@ -507,15 +510,26 @@ public:
///
VTKM_CONT_EXPORT void SyncControlArray() const
{
if ( !this->Internals->UserPortalValid
&& !this->Internals->ControlArrayValid)
if (!this->Internals->UserPortalValid
&& !this->Internals->ControlArrayValid)
{
// Need to change some state that does not change the logical state from
// an external point of view.
InternalStruct *internals
= const_cast<InternalStruct*>(this->Internals.get());
internals->ExecutionArray->RetrieveOutputData(internals->ControlArray);
internals->ControlArrayValid = true;
if (this->Internals->ExecutionArrayValid)
{
internals->ExecutionArray->RetrieveOutputData(internals->ControlArray);
internals->ControlArrayValid = 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.
internals->ControlArray.Allocate(0);
internals->ControlArrayValid = true;
}
}
else
{

@ -135,6 +135,25 @@ struct TryArrayHandleType
TestValue(index, T()) + T(1)),
"Did not get result from in place operation.");
}
std::cout << "Try operations on empty arrays." << std::endl;
// After each operation, reinitialize array in case something gets
// allocated.
arrayHandle = vtkm::cont::ArrayHandle<T>();
VTKM_TEST_ASSERT(arrayHandle.GetNumberOfValues() == 0,
"Uninitialized array does not report zero values.");
arrayHandle = vtkm::cont::ArrayHandle<T>();
VTKM_TEST_ASSERT(
arrayHandle.GetPortalConstControl().GetNumberOfValues() == 0,
"Uninitialized array does not give portal with zero values.");
arrayHandle = vtkm::cont::ArrayHandle<T>();
arrayHandle.Shrink(0);
arrayHandle = vtkm::cont::ArrayHandle<T>();
arrayHandle.ReleaseResourcesExecution();
arrayHandle = vtkm::cont::ArrayHandle<T>();
arrayHandle.ReleaseResources();
arrayHandle = vtkm::cont::ArrayHandle<T>();
arrayHandle.PrepareForOutput(ARRAY_SIZE, VTKM_DEFAULT_DEVICE_ADAPTER_TAG());
}
};