% -*- latex -*-

\chapter{Try Execute}
\label{chap:TryExecute}

\index{try execute|(}
\index{device adapter!try execute|(}

Most operations in \VTKm do not require specifying on which device to run.
For example, you may have noticed that when using \vtkmcont{Invoker} to execute a worklet, you do not need to specify a device; it chooses a device for you.
Internally, the \textidentifier{Invoker} has a mechanism to automatically select a device, try it, and fall back to other devices if the first one fails.
We saw this at work in the implementation of filters in Chapter \ref{chap:FilterTypeReference}.

The \textidentifier{Invoker} is internally using a function named \vtkmcont{TryExecute} to choose a device.
This \textidentifier{TryExecute} function can be also be used in other instances where a specific device needs to be chosen.

\textidentifier{TryExecute} is a simple, generic mechanism to run an algorithm that requires a device adapter without directly specifying a device adapter.
\vtkmcont{TryExecute} is a templated function.
The first argument is a functor object whose parenthesis operator takes a device adapter tag and returns a \textcode{bool} that is true if the call succeeds on the given device.
If any further arguments are given to \textidentifier{TryExecute}, they are passed on to the functor.
Thus, the parenthesis operator on the functor should take a device adapter tag as its first argument and any remaining arguments must match those passed to \textidentifier{TryExecute}.

To demonstrate the operation of \textidentifier{TryExecute}, consider an operation to find the average value of an array.
Doing so with a given device adapter is a straightforward use of the reduction operator.

\vtkmlisting[ex:ArrayAverageImpl]{A function to find the average value of an array in parallel.}{ArrayAverageImpl.cxx}

The function in Example~\ref{ex:ArrayAverageImpl} requires a device adapter.
We want to make an alternate version of this function that does not need a specific device adapter but rather finds one to use.
To do this, we first make a functor as described earlier.
It takes a device adapter tag as an argument, calls the version of the function shown in Example~\ref{ex:ArrayAverageImpl}, and returns true when the operation succeeds.
We then create a new version of the array average function that does not need a specific device adapter tag and calls \textidentifier{TryExecute} with the aforementioned functor.

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

\begin{commonerrors}
  When \textidentifier{TryExecute} calls the operation of your functor, it will catch any exceptions that the functor might throw.
  \textidentifier{TryExecute} will interpret any thrown exception as a failure on that device and try another device.
  If all devices fail, \textidentifier{TryExecute} will return a false value rather than throw its own exception.
  This means if you want to have an exception thrown from a call to \textidentifier{TryExecute}, you will need to check the return value and throw the exception yourself.
\end{commonerrors}

\index{device adapter!try execute|)}
\index{try execute|)}
