vtk-m/vtkm/cont/internal/ArrayTransfer.h
hschroot 20c1a04894 CopyInto function for ArrayHandles
ArrayHandles in DAX have a CopyInto function which allows the user to copy an array handle's data into a compatible STL type iterator. Originally this was fairly straight forward to implement since array handles in DAX are templated on the DeviceAdapterTag. In contrast, VTKm array handles use a polymorphic ArrayHandleExecutionManager under the hood allowing a single array handle to interface with multiple devices at runtime. To achieve this virtual functions are used. This makes implementing the CopyInto function difficult since it is templated on the IteratorType and virtual functions cannot be templated.

To work around this, I've implemented a concrete templated CopyInto function in the class derived from ArrayHandleExecutionManagerBase. In the ArrayHandle class, CopyInto dynamically casts the base class into the derived class, then calls the CopyInto function defined in the derived class.

The drawback to this approach is that, should the user define their own class that inherits from ArrayHandleExectionManagerBase, they are not forced to implement the CopyInto function, unlike the other virtual functions.
2015-09-17 14:26:19 -04:00

177 lines
6.4 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// 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_ArrayTransfer_h
#define vtk_m_cont_internal_ArrayTransfer_h
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/internal/ArrayManagerExecution.h>
namespace vtkm {
namespace cont {
namespace internal {
/// \brief Class that manages the transfer of data between control and execution.
///
/// This templated class provides a mechanism (used by the ArrayHandle) to
/// transfer data from the control environment to the execution environment and
/// back. The interface for ArrayTransfer is nearly identical to that of
/// ArrayManagerExecution and the default implementation simply delegates all
/// calls to that class.
///
/// The primary motivation for having a separate class is that the
/// ArrayManagerExecution is meant to be specialized for each device adapter
/// whereas the ArrayTransfer is meant to be specialized for each storage type
/// (or specific combination of storage and device adapter). Thus, transfers
/// for most storage tyeps will be delegated through the ArrayManagerExecution,
/// but some storage types, like implicit storage, will be specialized to
/// transfer through a different path.
///
template<typename T, class StorageTag, class DeviceAdapterTag>
class ArrayTransfer
{
private:
typedef vtkm::cont::internal::Storage<T,StorageTag> StorageType;
typedef vtkm::cont::internal::ArrayManagerExecution<
T,StorageTag,DeviceAdapterTag> ArrayManagerType;
public:
/// The type of value held in the array (vtkm::FloatDefault, vtkm::Vec, etc.)
///
typedef T ValueType;
/// An array portal that can be used in the control environment.
///
typedef typename StorageType::PortalType PortalControl;
typedef typename StorageType::PortalConstType PortalConstControl;
/// An array portal that can be used in the execution environment.
///
typedef typename ArrayManagerType::PortalType PortalExecution;
typedef typename ArrayManagerType::PortalConstType PortalConstExecution;
VTKM_CONT_EXPORT
ArrayTransfer(StorageType *storage) : ArrayManager(storage) { }
/// Returns the number of values stored in the array. Results are undefined
/// if data has not been loaded or allocated.
///
VTKM_CONT_EXPORT
vtkm::Id GetNumberOfValues() const
{
return this->ArrayManager.GetNumberOfValues();
}
/// Prepares the data for use as input in the execution environment. If the
/// flag \c updateData is true, then data is transferred to the execution
/// environment. Otherwise, this transfer is (or may be) skipped.
///
/// Returns a constant array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalConstExecution PrepareForInput(bool updateData)
{
return this->ArrayManager.PrepareForInput(updateData);
}
/// Prepares the data for use as both input and output in the execution
/// environment. If the flag \c updateData is true, then data is transferred
/// to the execution environment. Otherwise, this transfer is (or may be)
/// skipped.
///
/// Returns a read-write array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalExecution PrepareForInPlace(bool updateData)
{
return this->ArrayManager.PrepareForInPlace(updateData);
}
/// Allocates an array in the execution environment of the specified size. If
/// control and execution share arrays, then this class can allocate data
/// using the given Storage it can be used directly in the execution
/// environment.
///
/// Returns a writable array portal valid in the execution environment.
///
VTKM_CONT_EXPORT
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
{
return this->ArrayManager.PrepareForOutput(numberOfValues);
}
/// Allocates data in the given Storage and copies data held in the execution
/// environment (managed by this class) into the storage object. The
/// reference to the storage given is the same as that passed to the
/// constructor. If control and execution share arrays, this can be no
/// operation. This method should only be called after PrepareForOutput is
/// called.
///
VTKM_CONT_EXPORT
void RetrieveOutputData(StorageType *storage) const
{
this->ArrayManager.RetrieveOutputData(storage);
}
/// Similar to RetrieveOutputData except that instead of writing to the
/// controlArray itself, it writes to the given control environment
/// iterator. This allows the user to retrieve data without necessarily
/// allocating an array in the ArrayContainerControl (assuming that control
/// and exeuction have seperate memory spaces).
///
template <class IteratorTypeControl>
VTKM_CONT_EXPORT void CopyInto(IteratorTypeControl dest) const
{
this->ArrayManager.CopyInto(dest);
}
/// \brief Reduces the size of the array without changing its values.
///
/// This method allows you to resize the array without reallocating it. The
/// number of entries in the array is changed to \c numberOfValues. The data
/// in the array (from indices 0 to \c numberOfValues - 1) are the same, but
/// \c numberOfValues must be equal or less than the preexisting size
/// (returned from GetNumberOfValues). That is, this method can only be used
/// to shorten the array, not lengthen.
///
VTKM_CONT_EXPORT
void Shrink(vtkm::Id numberOfValues)
{
this->ArrayManager.Shrink(numberOfValues);
}
/// Frees any resources (i.e. memory) allocated for the exeuction
/// environment, if any.
///
VTKM_CONT_EXPORT
void ReleaseResources()
{
this->ArrayManager.ReleaseResources();
}
private:
ArrayManagerType ArrayManager;
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_internal_ArrayTransfer_h