StorageBasic is now treated like users memory after being stolen.

Previously once an ArrayHandle was stolen it was placed in an invalid state
where it could not used again by VTK-m. Now instead after being stolen it
is placed into a state where it is identical to memory allocated outside
of VTK-m and passed in.
This commit is contained in:
Robert Maynard 2017-08-17 08:43:39 -04:00
parent 0c435d39f4
commit c385b21acd
4 changed files with 37 additions and 21 deletions

@ -186,8 +186,13 @@ public:
typedef AlignedAllocator<ValueType, VTKM_CACHE_LINE_SIZE> AllocatorType;
public:
/// \brief construct storage that VTK-m is responsible for
VTKM_CONT
Storage(const ValueType* array = nullptr, vtkm::Id numberOfValues = 0);
Storage();
/// \brief construct storage that VTK-m is not responsible for
VTKM_CONT
Storage(const ValueType* array, vtkm::Id numberOfValues = 0);
VTKM_CONT
~Storage();
@ -245,15 +250,22 @@ public:
/// \brief Take the reference away from this object.
///
/// This method returns the pointer to the array held by this array. It then
/// clears the internal array pointer to nullptr, thereby ensuring that the
/// Storage will never deallocate the array. This is helpful for taking a
/// reference for an array created internally by VTK-m and not having to keep
/// a VTK-m object around. Obviously the caller becomes responsible for
/// destroying the memory.
/// clears the internal ownership flags, thereby ensuring that the
/// Storage will never deallocate the array or be able to reallocate it. This
/// is helpful for taking a reference for an array created internally by
/// VTK-m and not having to keep a VTK-m object around. Obviously the caller
/// becomes responsible for destroying the memory.
///
VTKM_CONT
ValueType* StealArray();
/// \brief Returns if vtkm will deallocate this memory. VTK-m StorageBasic
/// is designed that VTK-m will not deallocate user passed memory, or
/// instances that have been stolen (\c StealArray)
VTKM_CONT
bool WillDeallocate() const { return this->DeallocateOnRelease; }
VTKM_CONT
void* GetBasePointer() const final { return static_cast<void*>(this->Array); }
@ -274,7 +286,6 @@ private:
vtkm::Id NumberOfValues;
vtkm::Id AllocatedSize;
bool DeallocateOnRelease;
bool UserProvidedMemory;
};
} // namespace internal

@ -29,13 +29,21 @@ namespace cont
namespace internal
{
template <typename T>
Storage<T, vtkm::cont::StorageTagBasic>::Storage()
: Array(nullptr)
, NumberOfValues(0)
, AllocatedSize(0)
, DeallocateOnRelease(true)
{
}
template <typename T>
Storage<T, vtkm::cont::StorageTagBasic>::Storage(const T* array, vtkm::Id numberOfValues)
: Array(const_cast<T*>(array))
, NumberOfValues(numberOfValues)
, AllocatedSize(numberOfValues)
, DeallocateOnRelease(false)
, UserProvidedMemory(array == nullptr ? false : true)
, DeallocateOnRelease(array == nullptr ? true : false)
{
}
@ -50,8 +58,7 @@ Storage<T, vtkm::cont::StorageTagBasic>::Storage(const Storage<T, StorageTagBasi
: Array(src.Array)
, NumberOfValues(src.NumberOfValues)
, AllocatedSize(src.AllocatedSize)
, DeallocateOnRelease(false)
, UserProvidedMemory(src.UserProvidedMemory)
, DeallocateOnRelease(src.DeallocateOnRelease)
{
if (src.DeallocateOnRelease)
{
@ -77,7 +84,6 @@ Storage<T, vtkm::cont::StorageTagBasic>& Storage<T, vtkm::cont::StorageTagBasic>
this->NumberOfValues = src.NumberOfValues;
this->AllocatedSize = src.AllocatedSize;
this->DeallocateOnRelease = src.DeallocateOnRelease;
this->UserProvidedMemory = src.UserProvidedMemory;
return *this;
}
@ -139,7 +145,7 @@ void Storage<T, vtkm::cont::StorageTagBasic>::AllocateBytes(vtkm::Id numberOfByt
return;
}
if (this->UserProvidedMemory)
if (!this->DeallocateOnRelease)
{
throw vtkm::cont::ErrorBadValue("User allocated arrays cannot be reallocated.");
}
@ -170,7 +176,6 @@ void Storage<T, vtkm::cont::StorageTagBasic>::AllocateBytes(vtkm::Id numberOfByt
}
this->DeallocateOnRelease = true;
this->UserProvidedMemory = false;
}
template <typename T>
@ -193,11 +198,8 @@ void Storage<T, vtkm::cont::StorageTagBasic>::ShrinkBytes(vtkm::Id numberOfBytes
template <typename T>
T* Storage<T, vtkm::cont::StorageTagBasic>::StealArray()
{
T* saveArray = this->Array;
this->Array = nullptr;
this->NumberOfValues = 0;
this->AllocatedSize = 0;
return saveArray;
this->DeallocateOnRelease = false;
return this->Array;
}
} // namespace internal

@ -134,8 +134,11 @@ struct TemplatedTests
VTKM_TEST_ASSERT(stealMyArray.GetNumberOfValues() == ARRAY_SIZE,
"Array not properly allocated.");
// This call steals the array and prevents deallocation.
VTKM_TEST_ASSERT(stealMyArray.WillDeallocate() == true,
"Array to be stolen needs to be owned by VTK-m");
stolenArray = stealMyArray.StealArray();
VTKM_TEST_ASSERT(stealMyArray.GetNumberOfValues() == 0, "StealArray did not let go of array.");
VTKM_TEST_ASSERT(stealMyArray.WillDeallocate() == false,
"Stolen array should not be owned by VTK-m");
return stolenArray;
}

@ -58,7 +58,7 @@ public:
VTKM_CONT
AtomicArray()
: AtomicImplementation(vtkm::cont::make_ArrayHandle((T*)nullptr, 0))
: AtomicImplementation((vtkm::cont::ArrayHandle<T>()))
{
}