% -*- latex -*-

\chapter{Basic Array Handles}
\label{chap:BasicArrayHandles}

\index{array handle|(}

Chapter \ref{chap:DataSet} describes the basic data sets used by \VTKm.
This chapter dives deeper into how \VTKm represents data.
Ultimately, data structures like \vtkmcont{DataSet} can be broken down into arrays of numbers.
Arrays in \VTKm are managed by a unit called an \keyterm{array handle}.

An array handle, which is implemented with the \vtkmcont{ArrayHandle} class, manages an array of data that can be accessed or manipulated by \VTKm algorithms.
It is typical to construct an array handle in the control environment to pass data to an algorithm running in the execution environment.
It is also typical for an algorithm running in the execution environment to populate an array handle, which can then be read back in the control environment.
It is also possible for an array handle to manage data created by one \VTKm algorithm and passed to another, remaining in the execution environment the whole time and never copied to the control environment.

\begin{didyouknow}
  The array handle may have up to two copies of the array, one for the control environment and one for the execution environment.
  However, depending on the device and how the array is being used, the array handle will only have one copy when possible.
  Copies between the environments are implicit and lazy.
  They are copied only when an operation needs data in an environment where the data is not.
\end{didyouknow}

\vtkmcont{ArrayHandle} behaves like a shared smart pointer in that when the C++ object is copied, each copy holds a reference to the same array.
These copies are reference counted so that when all copies of the \vtkmcont{ArrayHandle} are destroyed, any allocated memory is released.

An \textidentifier{ArrayHandle} defines the following methods.
Note, however, that the brief overview of this chapter will not cover the use of most of these methods.
Further descriptions are given in later chapters that explore even further the features of \textidentifier{ArrayHandle}s.

\begin{description}
\item[{\classmember*{ArrayHandle}{GetNumberOfValues}}]
  Returns the number of entries in the array.
\item[{\classmember*{ArrayHandle}{Allocate}}]
  Resizes the array to include the number of entries given.
  Any previously stored data might be discarded.
\item[{\classmember*{ArrayHandle}{Shrink}}]
  Resizes the array to the number of entries given.
  Any data stored in the array is preserved.
  The number of entries must be less than those given in the last call to \classmember*{ArrayHandle}{Allocate}.
\item[{\classmember*{ArrayHandle}{ReleaseResourcesExecution}}]
  If the \textidentifier{ArrayHandle} is holding any data on a device (such as a GPU), that memory is released to be used elsewhere.
  No data is lost from this call.
  Any data on the released resources is copied to the control environment (the local CPU) before the memory is released.
\item[{\classmember*{ArrayHandle}{ReleaseResources}}]
  Releases all memory managed by this \textidentifier{ArrayHandle}.
  Any data in this memory is lost.
\item[{\classmember*{ArrayHandle}{SyncControlArray}}]
  Makes sure any data in the execution environment is also available in the control environment.
  This method is useful when timing parallel algorithms and you want to include the time to transfer data between parallel devices and their hosts.
\item[{\classmember*{ArrayHandle}{GetPortalControl}}]
  Returns an array portal that can be used to access the data in the array handle in the control environment.
  Array portals are described in Section~\ref{sec:ArrayPortals}.
\item[{\classmember*{ArrayHandle}{GetPortalConstControl}}]
  Like \classmember{ArrayHandle}{GetPortalControl} but returns a read-only array portal rather than a read/write array portal.
\item[{\classmember*{ArrayHandle}{PrepareForInput}}]
  Readies the data as input to a parallel algorithm.
  See Section~\ref{sec:ArrayHandle:InterfaceToExecutionEnvironment} for more details.
\item[{\classmember*{ArrayHandle}{PrepareForOutput}}]
  Readies the data as output to a parallel algorithm.
  See Section~\ref{sec:ArrayHandle:InterfaceToExecutionEnvironment} for more details.
\item[{\classmember*{ArrayHandle}{PrepareForInPlace}}]
  Readies the data as input and output to a parallel algorithm.
  See Section~\ref{sec:ArrayHandle:InterfaceToExecutionEnvironment} for more details.
\item[{\classmember*{ArrayHandle}{GetDeviceAdapterId}}]
  Returns a \vtkmcont{DeviceAdapterId} describing on which device adapter, if any, the array handle's data is available.
  Device adapter ids are described in Section~\ref{sec:DeviceAdapterId}.
\item[{\classmember*{ArrayHandle}{GetStorage}}]
  Returns the \vtkmcont{Storage} object that manages the data.
  The type of the storage object is defined by the storage tag template parameter of the \textidentifier{ArrayHandle}.
  Storage objects are described in detail in Chapter~\ref{chap:Storage}.
\end{description}


\section{Creating Array Handles}
\label{sec:CreatingArrayHandles}

\vtkmcont{ArrayHandle} is templated on the type of values being stored in the array.
There are multiple ways to create and populate an array handle.
The default \vtkmcont{ArrayHandle} constructor will create an empty array with nothing allocated in either the control or execution environment.
This is convenient for creating arrays used as the output for algorithms.

\vtkmlisting{Creating an \textidentifier{ArrayHandle} for output data.}{CreateArrayHandle.cxx}

Constructing an \textidentifier{ArrayHandle} that points to a provided C array or \textcode{std::vector} is straightforward with the \vtkmcont{make\_ArrayHandle} functions.
These functions will make an array handle that points to the array data that you provide.

\vtkmlisting{Creating an \textidentifier{ArrayHandle} that points to a provided C array.}{ArrayHandleFromCArray.cxx}

\vtkmlisting[ex:ArrayHandleFromVector]{Creating an \textidentifier{ArrayHandle} that points to a provided \textcode{std::vector}.}{ArrayHandleFromVector.cxx}

\fix{Will this default behavior change?}
\emph{Be aware} that \vtkmcont{make\_ArrayHandle} by default makes a shallow pointer copy.
This means that if you change or delete the data provided, the internal state of \textidentifier{ArrayHandle} becomes invalid and undefined behavior can ensue.
The most common manifestation of this error happens when a \textcode{std::vector} goes out of scope.
This subtle interaction will cause the \vtkmcont{ArrayHandle} to point to an unallocated portion of the memory heap.
For example, if the code in Example~\ref{ex:ArrayHandleFromVector} were to be placed within a callable function or method, it could cause the \vtkmcont{ArrayHandle} to become invalid.

\vtkmlisting[ex:ArrayOutOfScope]{Invalidating an \textidentifier{ArrayHandle} by letting the source \textcode{std::vector} leave scope.}{ArrayOutOfScope.cxx}

An easy way around the problem of having an \textidentifier{ArrayHandle}'s data going out of scope is to copy the data into the \textidentifier{ArrayHandle}.
To make this easy, the \textidentifier{make\_ArrayHandle} function takes an optional second argument of type \vtkm{CopyFlag}.
If the second argument is \classmember{CopyFlag}{Off} (the default), then the data is only shallow copied and errors will happen if the memory gets deallocated.
However, if the second argument is \classmember{CopyFlag}{On}, then the data are copied into the \textidentifier{ArrayHandle}.
This solution is shown on line \ref{ex:ArrayOutOfScope.cxx:CopyFlagOn} of Example \ref{ex:ArrayOutOfScope}.


\section{Deep Array Copies}
\label{sec:DeepArrayCopies}

\index{deep array copy|(}
\index{array handle!deep copy|(}

As stated previously, an \textidentifier{ArrayHandle} object behaves as a smart pointer that copies references to the data without copying the data itself.
This is clearly faster and more memory efficient than making copies of the data itself and usually the behavior desired.
However, it is sometimes the case that you need to make a separate copy of the data.

To simplify copying the data, \VTKm comes with the \vtkmcont{ArrayCopy} convenience function defined in \vtkmheader{vtkm/cont}{ArrayCopy.h}.
\textidentifier{ArrayCopy} takes the array to copy from (the source) as its first argument and the array to copy to (the destination) as its second argument.
The destination array will be properly reallocated to the correct size.

\vtkmlisting[ex:ArrayCopy]{Using \textidentifier{ArrayCopy}.}{ArrayCopy.cxx}

\begin{didyouknow}
  \textidentifier{ArrayCopy} will copy data in parallel.
  If desired, you can specify the device as the third argument to \textidentifier{ArrayCopy} using either a device adapter tag or a runtime device tracker.
  Both the tags and tracker are described in Chapter \ref{chap:ManagingDevices}.
\end{didyouknow}

\index{array handle!deep copy|)}
\index{deep array copy|)}


\section{The Hidden Second Template Parameter}

\index{array handle!storage|(}
\index{storage|(}

We have already seen that \vtkmcont{ArrayHandle} is a templated class with the template parameter indicating the type of values stored in the array.
However, \textidentifier{ArrayHandle} has a second hidden parameter that indicates the \keyterm{storage} of the array.
We have so far been able to ignore this second template parameter because \VTKm will assign a default storage for us that will store the data in a basic array.

\begin{vtkmexample}{Declaration of the \protect\vtkmcont{ArrayHandle} templated class.}
template<
    typename T,
    typename StorageTag = VTKM_DEFAULT_STORAGE_TAG>
class ArrayHandle;
\end{vtkmexample}

Changing the storage of an \textidentifier{ArrayHandle} lets us do many weird and wonderful things.
We will explore these options in later chapters, but for now we can ignore this second storage template parameter.
However, there are a couple of things to note concerning the storage.

First, if the compiler gives an error concerning your use of \textidentifier{ArrayHandle}, the compiler will report the \textidentifier{ArrayHandle} type with not one but two template parameters.
A second template parameter of \vtkmcont{StorageTagBasic} can be ignored.

Second, if you write a function, method, or class that is templated based on an \textidentifier{ArrayHandle} type, it is good practice to accept \textidentifier{ArrayHandle}s with non-default storage types.
There are two ways to do this.
The first way is to template both the value type and the storage type.

\vtkmlisting{Templating a function on an \textidentifier{ArrayHandle}'s parameters}{ArrayHandleParameterTemplate.cxx}

The second way is to template the whole array type rather than the sub types.
If you create a template where you expect one of the parameters to be an \textidentifier{ArrayHandle}, you should use the \vtkmmacro{VTKM\_IS\_ARRAY\_HANDLE} macro to verify that the type is indeed an \textidentifier{ArrayHandle}.

\vtkmlisting{A template parameter that should be an \textidentifier{ArrayHandle}.}{ArrayHandleFullTemplate.cxx}

\index{storage|)}
\index{array handle!storage|)}

\index{array handle|)}
