c123796949
Previously memory that was allocated outside of VTK-m was impossible to transfer to VTK-m as we didn't know how to free it. By extending the ArrayHandle constructors to support a Storage object that is being moved, we can clearly express that the ArrayHandle now owns memory it didn't allocate. Here is an example of how this is done: ```cpp T* buffer = new T[100]; auto user_free_function = [](void* ptr) { delete[] static_cast<T*>(ptr); }; vtkm::cont::internal::Storage<T, vtkm::cont::StorageTagBasic> storage(buffer, 100, user_free_function); vtkm::cont::ArrayHandle<T> arrayHandle(std::move(storage)); ```
265 lines
8.0 KiB
C++
265 lines
8.0 KiB
C++
//============================================================================
|
|
// 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.
|
|
//
|
|
// Copyright 2017 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
|
// Copyright 2017 UT-Battelle, LLC.
|
|
// Copyright 2017 Los Alamos National Security.
|
|
//
|
|
// Under the terms of Contract DE-NA0003525 with NTESS,
|
|
// the U.S. Government retains certain rights in this software.
|
|
//
|
|
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
|
|
// Laboratory (LANL), the U.S. Government retains certain rights in
|
|
// this software.
|
|
//============================================================================
|
|
|
|
#ifndef vtk_m_cont_internal_ArrayHandleBasicImpl_hxx
|
|
#define vtk_m_cont_internal_ArrayHandleBasicImpl_hxx
|
|
|
|
#include <vtkm/cont/internal/ArrayHandleBasicImpl.h>
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace cont
|
|
{
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::ArrayHandle()
|
|
: Internals(new internal::ArrayHandleImpl(T{}))
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::ArrayHandle(const Thisclass& src)
|
|
: Internals(src.Internals)
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::ArrayHandle(Thisclass&& src)
|
|
: Internals(std::move(src.Internals))
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::ArrayHandle(const StorageType& storage)
|
|
: Internals(new internal::ArrayHandleImpl(storage))
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::ArrayHandle(StorageType&& storage)
|
|
: Internals(new internal::ArrayHandleImpl(std::move(storage)))
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>::~ArrayHandle()
|
|
{
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>& ArrayHandle<T, StorageTagBasic>::operator=(const Thisclass& src)
|
|
{
|
|
this->Internals = src.Internals;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
ArrayHandle<T, StorageTagBasic>& ArrayHandle<T, StorageTagBasic>::operator=(Thisclass&& src)
|
|
{
|
|
this->Internals = std::move(src.Internals);
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ArrayHandle<T, StorageTagBasic>::operator==(const Thisclass& rhs) const
|
|
{
|
|
return this->Internals == rhs.Internals;
|
|
}
|
|
|
|
template <typename T>
|
|
bool ArrayHandle<T, StorageTagBasic>::operator!=(const Thisclass& rhs) const
|
|
{
|
|
return this->Internals != rhs.Internals;
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename VT, typename ST>
|
|
VTKM_CONT bool ArrayHandle<T, StorageTagBasic>::operator==(const ArrayHandle<VT, ST>&) const
|
|
{
|
|
return false; // different valuetype and/or storage
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename VT, typename ST>
|
|
VTKM_CONT bool ArrayHandle<T, StorageTagBasic>::operator!=(const ArrayHandle<VT, ST>&) const
|
|
{
|
|
return true; // different valuetype and/or storage
|
|
}
|
|
|
|
template <typename T>
|
|
typename ArrayHandle<T, StorageTagBasic>::StorageType& ArrayHandle<T, StorageTagBasic>::GetStorage()
|
|
{
|
|
this->SyncControlArray();
|
|
this->Internals->CheckControlArrayValid();
|
|
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
|
|
//is not valid
|
|
|
|
return *(static_cast<StorageType*>(this->Internals->ControlArray));
|
|
}
|
|
|
|
template <typename T>
|
|
const typename ArrayHandle<T, StorageTagBasic>::StorageType&
|
|
ArrayHandle<T, StorageTagBasic>::GetStorage() const
|
|
{
|
|
this->SyncControlArray();
|
|
this->Internals->CheckControlArrayValid();
|
|
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
|
|
//is not valid
|
|
|
|
return *(static_cast<const StorageType*>(this->Internals->ControlArray));
|
|
}
|
|
|
|
template <typename T>
|
|
typename ArrayHandle<T, StorageTagBasic>::PortalControl
|
|
ArrayHandle<T, StorageTagBasic>::GetPortalControl()
|
|
{
|
|
this->SyncControlArray();
|
|
this->Internals->CheckControlArrayValid();
|
|
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
|
|
//is not valid
|
|
|
|
|
|
// 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();
|
|
StorageType* privStorage = static_cast<StorageType*>(this->Internals->ControlArray);
|
|
return privStorage->GetPortal();
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
typename ArrayHandle<T, StorageTagBasic>::PortalConstControl
|
|
ArrayHandle<T, StorageTagBasic>::GetPortalConstControl() const
|
|
{
|
|
this->SyncControlArray();
|
|
this->Internals->CheckControlArrayValid();
|
|
//CheckControlArrayValid will throw an exception if this->Internals->ControlArrayValid
|
|
//is not valid
|
|
|
|
StorageType* privStorage = static_cast<StorageType*>(this->Internals->ControlArray);
|
|
return privStorage->GetPortalConst();
|
|
}
|
|
|
|
template <typename T>
|
|
vtkm::Id ArrayHandle<T, StorageTagBasic>::GetNumberOfValues() const
|
|
{
|
|
return this->Internals->GetNumberOfValues(sizeof(T));
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::Allocate(vtkm::Id numberOfValues)
|
|
{
|
|
this->Internals->Allocate(numberOfValues, sizeof(T));
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::Shrink(vtkm::Id numberOfValues)
|
|
{
|
|
this->Internals->Shrink(numberOfValues, sizeof(T));
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::ReleaseResourcesExecution()
|
|
{
|
|
// Save any data in the execution environment by making sure it is synced
|
|
// with the control environment.
|
|
this->SyncControlArray();
|
|
this->Internals->ReleaseResourcesExecutionInternal();
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::ReleaseResources()
|
|
{
|
|
this->Internals->ReleaseResources();
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename DeviceAdapterTag>
|
|
typename ArrayHandle<T, StorageTagBasic>::template ExecutionTypes<DeviceAdapterTag>::PortalConst
|
|
ArrayHandle<T, StorageTagBasic>::PrepareForInput(DeviceAdapterTag device) const
|
|
{
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
|
this->PrepareForDevice(device);
|
|
|
|
this->Internals->PrepareForInput(sizeof(T));
|
|
return PortalFactory<DeviceAdapterTag>::CreatePortalConst(
|
|
static_cast<T*>(this->Internals->ExecutionArray),
|
|
static_cast<T*>(this->Internals->ExecutionArrayEnd));
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename DeviceAdapterTag>
|
|
typename ArrayHandle<T, StorageTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal
|
|
ArrayHandle<T, StorageTagBasic>::PrepareForOutput(vtkm::Id numVals, DeviceAdapterTag device)
|
|
{
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
|
this->PrepareForDevice(device);
|
|
|
|
this->Internals->PrepareForOutput(numVals, sizeof(T));
|
|
return PortalFactory<DeviceAdapterTag>::CreatePortal(
|
|
static_cast<T*>(this->Internals->ExecutionArray),
|
|
static_cast<T*>(this->Internals->ExecutionArrayEnd));
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename DeviceAdapterTag>
|
|
typename ArrayHandle<T, StorageTagBasic>::template ExecutionTypes<DeviceAdapterTag>::Portal
|
|
ArrayHandle<T, StorageTagBasic>::PrepareForInPlace(DeviceAdapterTag device)
|
|
{
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(DeviceAdapterTag);
|
|
this->PrepareForDevice(device);
|
|
|
|
this->Internals->PrepareForInPlace(sizeof(T));
|
|
return PortalFactory<DeviceAdapterTag>::CreatePortal(
|
|
static_cast<T*>(this->Internals->ExecutionArray),
|
|
static_cast<T*>(this->Internals->ExecutionArrayEnd));
|
|
}
|
|
|
|
template <typename T>
|
|
template <typename DeviceAdapterTag>
|
|
void ArrayHandle<T, StorageTagBasic>::PrepareForDevice(DeviceAdapterTag) const
|
|
{
|
|
DeviceAdapterId devId = DeviceAdapterTraits<DeviceAdapterTag>::GetId();
|
|
this->Internals->PrepareForDevice(devId, sizeof(T));
|
|
}
|
|
|
|
template <typename T>
|
|
DeviceAdapterId ArrayHandle<T, StorageTagBasic>::GetDeviceAdapterId() const
|
|
{
|
|
return this->Internals->GetDeviceAdapterId();
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::SyncControlArray() const
|
|
{
|
|
this->Internals->SyncControlArray(sizeof(T));
|
|
}
|
|
|
|
template <typename T>
|
|
void ArrayHandle<T, StorageTagBasic>::ReleaseResourcesExecutionInternal()
|
|
{
|
|
this->Internals->ReleaseResourcesExecutionInternal();
|
|
}
|
|
}
|
|
} // end namespace vtkm::cont
|
|
|
|
|
|
#endif // not vtk_m_cont_internal_ArrayHandleBasicImpl_hxx
|