Add basic dispatcher functionality.

These changes support the implementation of DispatcherBase. This class
provides the basic functionality for calling an Invoke method in the
control environment, transferring data to the execution environment,
scheduling threads in the execution environment, pulling data for each
calling of the worklet method, and actually calling the worklet.
This commit is contained in:
Kenneth Moreland 2014-10-21 10:51:07 -06:00
parent b78688f4f4
commit 53a454fe77
18 changed files with 2679 additions and 16 deletions

@ -83,7 +83,9 @@ struct FetchArrayDirectInTests
this->TryInvocation(vtkm::internal::make_Invocation<1>(
BaseFunctionInterface().Replace<ParamIndex>(
TestPortal<T>())));
TestPortal<T>()),
NullParam(),
NullParam()));
}
};

@ -94,7 +94,9 @@ struct FetchArrayDirectOutTests
this->TryInvocation(vtkm::internal::make_Invocation<1>(
BaseFunctionInterface().Replace<ParamIndex>(
TestPortal<T>())));
TestPortal<T>()),
NullParam(),
NullParam()));
}
};

@ -78,7 +78,9 @@ void TryParamIndex()
TryInvocation<ParamIndex>(vtkm::internal::make_Invocation<1>(
BaseFunctionInterface().Replace<ParamIndex>(
TestExecutionObject(EXPECTED_NUMBER))));
TestExecutionObject(EXPECTED_NUMBER)),
NullParam(),
NullParam()));
}
void TestExecObjectFetch()

@ -63,7 +63,9 @@ void TestWorkIndexFetch()
void(NullParam,NullParam,NullParam,NullParam,NullParam)>
BaseFunctionInterface;
TryInvocation(vtkm::internal::make_Invocation<1>( BaseFunctionInterface()));
TryInvocation(vtkm::internal::make_Invocation<1>(BaseFunctionInterface(),
NullParam(),
NullParam()));
}
} // anonymous namespace

@ -20,8 +20,12 @@
set(headers
ErrorMessageBuffer.h
WorkletInvokeFunctor.h
WorkletInvokeFunctorDetail.h
)
vtkm_declare_headers(${headers})
vtkm_pyexpander_generated_file(WorkletInvokeFunctorDetail.h)
add_subdirectory(testing)

@ -0,0 +1,67 @@
//============================================================================
// 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_exec_internal_WorkletInvokeFunctor_h
#define vtk_m_exec_internal_WorkletInvokeFunctor_h
#include <vtkm/internal/Invocation.h>
#include <vtkm/exec/FunctorBase.h>
#include <vtkm/exec/arg/Fetch.h>
#include <vtkm/exec/internal/WorkletInvokeFunctorDetail.h>
namespace vtkm {
namespace exec {
namespace internal {
template<typename WorkletType, typename InvocationType>
class WorkletInvokeFunctor : public vtkm::exec::FunctorBase
{
public:
VTKM_CONT_EXPORT
WorkletInvokeFunctor(const WorkletType &worklet,
const InvocationType &invocation)
: Worklet(worklet), Invocation(invocation) { }
VTKM_CONT_EXPORT
void SetErrorMessageBuffer(
const vtkm::exec::internal::ErrorMessageBuffer &buffer)
{
this->FunctorBase::SetErrorMessageBuffer(buffer);
this->Worklet.SetErrorMessageBuffer(buffer);
}
VTKM_EXEC_EXPORT
void operator()(vtkm::Id index) const
{
detail::DoWorkletInvokeFunctor(this->Worklet, this->Invocation, index);
}
private:
WorkletType Worklet;
InvocationType Invocation;
};
}
}
} // vtkm::exec::internal
#endif //vtk_m_exec_internal_WorkletInvokeFunctor_h

File diff suppressed because it is too large Load Diff

@ -0,0 +1,219 @@
//============================================================================
// 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.
//============================================================================
$# This file uses the pyexpander macro processing utility to build the
$# FunctionInterface facilities that use a variable number of arguments.
$# Information, documentation, and downloads for pyexpander can be found at:
$#
$# http://pyexpander.sourceforge.net/
$#
$# To build the source code, execute the following (after installing
$# pyexpander, of course):
$#
$# expander.py WorkletInvokeFunctorDetail.h.in > WorkletInvokeFunctorDetail.h
$#
$# Ignore the following comment. It is meant for the generated file.
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by WorkletInvokeFunctorDetail.h.in
// Technically speaking, we can implement this functionality with some clever
// use of FunctionInterface rather than using pyexpander to make variadic
// code. However, this code is probably more friendly to compilers. I expect
// it to compiler faster and optimize better.
#ifndef vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#define vtk_m_exec_internal_WorkletInvokeFunctorDetail_h
#if !defined(vtk_m_exec_internal_WorkletInvokeFunctor_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error WorkletInvokeFunctorDetail.h must be included from WorkletInvokeFunctor.h
#endif
#include <vtkm/internal/FunctionInterface.h>
#include <vtkm/internal/Invocation.h>
#include <vtkm/exec/arg/Fetch.h>
$# This needs to match the max_parameters in FunctionInterfaceDetailPre.h.in
$py(max_parameters=10)\
#if VTKM_MAX_FUNCTION_PARAMETERS != $(max_parameters)
#error Mismatch of maximum parameters between FunctionInterfaceDatailPre.h.in and WorkletInvokeFunctorDetail.h.in
#endif
$# Python commands used in template expansion.
$py(
def comma_if(flag):
if flag:
return ','
else:
return '';
def ptype(num, name=''):
if num == 0:
return '%sR' % name
else:
return '%sP%d' % (name, num)
def pname(num, name=''):
if num == 0:
return '%sr' % name
else:
return '%sp%d' % (name, num)
def template_params(num_params, start=0, name=''):
if num_params < start:
return ''
result = 'typename %s' % ptype(start, name)
for param in xrange(start+1, num_params+1):
result += ',\n typename %s' % ptype(param, name)
return result
def signature(num_params, return_type=ptype(0), name=''):
result = '%s(' % return_type
if num_params > 0:
result += ptype(1, name)
for param in xrange(2, num_params+1):
result += ',%s' % ptype(param, name)
result += ')'
return result
def arg_list(num_params, name='', start=1):
if num_params < start:
return ''
result = pname(start, name)
for param in xrange(start+1, num_params+1):
result += ',%s' % pname(param, name)
return result
)\
$#
$extend(comma_if, ptype, pname, template_params, signature, arg_list)\
namespace vtkm {
namespace exec {
namespace internal {
namespace detail {
/// A helper class that takes an \c Invocation object and an index to a
/// parameter in the ExecutionSignature and finds the \c Fetch type valid for
/// that parameter.
template<typename Invocation, vtkm::IdComponent ExecutionParameterIndex>
struct InvocationToFetch
{
private:
typedef typename Invocation::ExecutionInterface::
template ParameterType<ExecutionParameterIndex>::type
ExecutionSignatureTag;
// Expected fields from ExecutionSignatureTag. If these do not exist in
// ExecutionSignatureTag, then something that is not really an execution
// signature tag was used in an ExecutionSignature.
static const vtkm::IdComponent ControlParameterIndex =
ExecutionSignatureTag::INDEX;
typedef typename ExecutionSignatureTag::AspectTag AspectTag;
// Find the fetch tag from the control signature tag pointed to by
// ParameterIndex.
typedef typename Invocation::ControlInterface ControlInterface;
typedef typename ControlInterface::
template ParameterType<ControlParameterIndex>::type ControlSignatureTag;
typedef typename ControlSignatureTag::FetchTag FetchTag;
public:
typedef vtkm::exec::arg::Fetch<
FetchTag,AspectTag,Invocation,ControlParameterIndex> type;
};
$for(num_params in range(1, max_parameters+1))\
template<typename WorkletType,
typename ParameterInterface,
typename ControlInterface,
vtkm::IdComponent InputDomainIndex,
$template_params(num_params)>
void DoWorkletInvokeFunctor(
const WorkletType &worklet,
const vtkm::internal::Invocation<
ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params)>,
InputDomainIndex> &invocation,
vtkm::Id index)
{
typedef vtkm::internal::Invocation<
ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params)>,
InputDomainIndex> Invocation;
$for(param_index in range(1, num_params+1))\
typedef typename InvocationToFetch<Invocation,$(param_index)>::type FetchType$(param_index);
FetchType$(param_index) fetch$(param_index);
typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation);
$endfor\
typedef typename InvocationToFetch<Invocation,0>::type ReturnFetchType;
ReturnFetchType returnFetch;
typename ReturnFetchType::ValueType $pname(0) = worklet($arg_list(num_params));
returnFetch.Store(index, invocation, $pname(0));
$for(param_index in range(1, num_params+1))\
fetch$(param_index).Store(index, invocation, $pname(param_index));
$endfor\
}
template<typename WorkletType,
typename ParameterInterface,
typename ControlInterface,
vtkm::IdComponent InputDomainIndex,
$template_params(num_params, start=1)>
void DoWorkletInvokeFunctor(
const WorkletType &worklet,
const vtkm::internal::Invocation<
ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
InputDomainIndex> &invocation,
vtkm::Id index)
{
typedef vtkm::internal::Invocation<
ParameterInterface,
ControlInterface,
vtkm::internal::FunctionInterface<$signature(num_params, return_type='void')>,
InputDomainIndex> Invocation;
$for(param_index in range(1, num_params+1))\
typedef typename InvocationToFetch<Invocation,$(param_index)>::type FetchType$(param_index);
FetchType$(param_index) fetch$(param_index);
typename FetchType$(param_index)::ValueType $pname(param_index) = fetch$(param_index).Load(index, invocation);
$endfor\
worklet($arg_list(num_params));
$for(param_index in range(1, num_params+1))\
fetch$(param_index).Store(index, invocation, $pname(param_index));
$endfor\
}
$endfor\
}
}
}
} // namespace vtkm::exec::internal::detail
#endif //vtk_m_exec_internal_WorkletInvokeFunctorDetail_h

@ -22,5 +22,6 @@
set(unit_tests
UnitTestErrorMessageBuffer.cxx
UnitTestWorkletInvokeFunctor.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,284 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <vtkm/exec/arg/BasicArg.h>
#include <vtkm/internal/FunctionInterface.h>
#include <vtkm/testing/Testing.h>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>
namespace {
struct TestExecObject
{
VTKM_EXEC_CONT_EXPORT
TestExecObject() : Value(NULL) { }
VTKM_EXEC_CONT_EXPORT
TestExecObject(vtkm::Id *value) : Value(value) { }
vtkm::Id *Value;
};
struct TestFetchTagInput { };
struct TestFetchTagOutput { };
// Missing TransportTag, but we are not testing that so we can leave it out.
struct TestControlSignatureTagInput
{
typedef TestFetchTagInput FetchTag;
};
struct TestControlSignatureTagOutput
{
typedef TestFetchTagOutput FetchTag;
};
} // anonymous namespace
namespace vtkm {
namespace exec {
namespace arg {
template<typename Invocation, vtkm::IdComponent ParameterIndex>
struct Fetch<TestFetchTagInput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
{
typedef vtkm::Id ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id index, const Invocation &invocation) const {
return *invocation.Parameters.
template GetParameter<ParameterIndex>().Value + 10*index;
}
VTKM_EXEC_EXPORT
void Store(vtkm::Id, const Invocation &, ValueType) const {
// No-op
}
};
template<typename Invocation, vtkm::IdComponent ParameterIndex>
struct Fetch<TestFetchTagOutput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
{
typedef vtkm::Id ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id, const Invocation &) const {
// No-op
return ValueType();
}
VTKM_EXEC_EXPORT
void Store(vtkm::Id index,
const Invocation &invocation,
ValueType value) const {
*invocation.Parameters.template GetParameter<ParameterIndex>().Value =
value + 20*index;
}
};
}
}
} // vtkm::exec::arg
namespace {
typedef void TestControlSignature(TestControlSignatureTagInput,
TestControlSignatureTagOutput);
typedef vtkm::internal::FunctionInterface<TestControlSignature>
TestControlInterface;
typedef void TestExecutionSignature1(vtkm::exec::arg::BasicArg<1>,
vtkm::exec::arg::BasicArg<2>);
typedef vtkm::internal::FunctionInterface<TestExecutionSignature1>
TestExecutionInterface1;
typedef vtkm::exec::arg::BasicArg<2> TestExecutionSignature2(
vtkm::exec::arg::BasicArg<1>);
typedef vtkm::internal::FunctionInterface<TestExecutionSignature2>
TestExecutionInterface2;
typedef vtkm::internal::FunctionInterface<void(TestExecObject, TestExecObject)>
ExecutionParameterInterface;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface1,
1> InvocationType1;
typedef vtkm::internal::Invocation<
ExecutionParameterInterface,
TestControlInterface,
TestExecutionInterface2,
1> InvocationType2;
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletProxy : vtkm::exec::FunctorBase
{
VTKM_EXEC_EXPORT
void operator()(vtkm::Id input, vtkm::Id &output) const
{
output = input + 100;
}
VTKM_EXEC_EXPORT
vtkm::Id operator()(vtkm::Id input) const
{
return input + 200;
}
};
#define ERROR_MESSAGE "Expected worklet error."
// Not a full worklet, but provides operators that we expect in a worklet.
struct TestWorkletErrorProxy : vtkm::exec::FunctorBase
{
VTKM_EXEC_EXPORT
void operator()(vtkm::Id, vtkm::Id) const
{
this->RaiseError(ERROR_MESSAGE);
}
};
// Check behavior of InvocationToFetch helper class.
BOOST_MPL_ASSERT(( boost::is_same<
vtkm::exec::internal::detail::InvocationToFetch<InvocationType1,1>::type,
vtkm::exec::arg::Fetch<TestFetchTagInput,vtkm::exec::arg::AspectTagDefault,InvocationType1,1> > ));
BOOST_MPL_ASSERT(( boost::is_same<
vtkm::exec::internal::detail::InvocationToFetch<InvocationType1,2>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,InvocationType1,2> > ));
BOOST_MPL_ASSERT(( boost::is_same<
vtkm::exec::internal::detail::InvocationToFetch<InvocationType2,0>::type,
vtkm::exec::arg::Fetch<TestFetchTagOutput,vtkm::exec::arg::AspectTagDefault,InvocationType2,2> > ));
void TestDoWorkletInvoke()
{
std::cout << "Testing internal worklet invoke." << std::endl;
vtkm::Id inputTestValue;
vtkm::Id outputTestValue;
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
std::cout << " Try void return." << std::endl;
inputTestValue = 5;
outputTestValue = 0xDEADDEAD;
vtkm::exec::internal::detail::DoWorkletInvokeFunctor(
TestWorkletProxy(),
vtkm::internal::make_Invocation<1>(execObjects,
TestControlInterface(),
TestExecutionInterface1()),
1);
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
"Output value not set right.");
std::cout << " Try return value." << std::endl;
inputTestValue = 6;
outputTestValue = 0xDEADDEAD;
vtkm::exec::internal::detail::DoWorkletInvokeFunctor(
TestWorkletProxy(),
vtkm::internal::make_Invocation<1>(execObjects,
TestControlInterface(),
TestExecutionInterface2()),
2);
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
"Output value not set right.");
}
void TestNormalFunctorInvoke()
{
std::cout << "Testing normal worklet invoke." << std::endl;
vtkm::Id inputTestValue;
vtkm::Id outputTestValue;
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
std::cout << " Try void return." << std::endl;
inputTestValue = 5;
outputTestValue = 0xDEADDEAD;
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType1> WorkletInvokeFunctor1;
WorkletInvokeFunctor1 workletInvokeFunctor1 =
WorkletInvokeFunctor1(TestWorkletProxy(), InvocationType1(execObjects));
workletInvokeFunctor1(1);
VTKM_TEST_ASSERT(inputTestValue == 5, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 100 + 30,
"Output value not set right.");
std::cout << " Try return value." << std::endl;
inputTestValue = 6;
outputTestValue = 0xDEADDEAD;
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletProxy,InvocationType2> WorkletInvokeFunctor2;
WorkletInvokeFunctor2 workletInvokeFunctor2 =
WorkletInvokeFunctor2(TestWorkletProxy(), InvocationType2(execObjects));
workletInvokeFunctor2(2);
VTKM_TEST_ASSERT(inputTestValue == 6, "Input value changed.");
VTKM_TEST_ASSERT(outputTestValue == inputTestValue + 200 + 30*2,
"Output value not set right.");
}
void TestErrorFunctorInvoke()
{
std::cout << "Testing invoke with an error raised in the worklet." << std::endl;
vtkm::Id inputTestValue = 5;
vtkm::Id outputTestValue = 0xDEADDEAD;
vtkm::internal::FunctionInterface<void(TestExecObject,TestExecObject)> execObjects =
vtkm::internal::make_FunctionInterface<void>(TestExecObject(&inputTestValue),
TestExecObject(&outputTestValue));
typedef vtkm::exec::internal::WorkletInvokeFunctor<TestWorkletErrorProxy,InvocationType1> WorkletInvokeFunctor1;
WorkletInvokeFunctor1 workletInvokeFunctor1 =
WorkletInvokeFunctor1(TestWorkletErrorProxy(), InvocationType1(execObjects));
char message[1024];
vtkm::exec::internal::ErrorMessageBuffer errorMessage(message, 1024);
workletInvokeFunctor1.SetErrorMessageBuffer(errorMessage);
workletInvokeFunctor1(1);
VTKM_TEST_ASSERT(errorMessage.IsErrorRaised(), "Error not raised correctly.");
VTKM_TEST_ASSERT(message == std::string(ERROR_MESSAGE),
"Got wrong error message.");
}
void TestWorkletInvokeFunctor()
{
TestDoWorkletInvoke();
TestNormalFunctorInvoke();
TestErrorFunctorInvoke();
}
} // anonymous namespace
int UnitTestWorkletInvokeFunctor(int, char *[])
{
return vtkm::testing::Testing::Run(TestWorkletInvokeFunctor);
}

@ -625,7 +625,7 @@ public:
template<typename TransformFunctor, typename FinishFunctor>
VTKM_CONT_EXPORT
void DynamicTransformCont(const TransformFunctor &transform,
const FinishFunctor &finish) {
const FinishFunctor &finish) const {
typedef detail::FunctionInterfaceDynamicTransformContContinue<
FunctionSignature,
ResultType(),
@ -637,7 +637,7 @@ public:
ContinueFunctorType(*this, emptyInterface, transform, finish);
continueFunctor.DoNextTransform(emptyInterface);
this->Result = emptyInterface.GetReturnValueSafe();
// this->Result = emptyInterface.GetReturnValueSafe();
}
/// \brief Applies a function to all the parameters.
@ -682,7 +682,7 @@ class FunctionInterfaceDynamicTransformContContinue
{
public:
FunctionInterfaceDynamicTransformContContinue(
vtkm::internal::FunctionInterface<OriginalFunction> &originalInterface,
const vtkm::internal::FunctionInterface<OriginalFunction> &originalInterface,
vtkm::internal::FunctionInterface<NewFunction> &newInterface,
const TransformFunctor &transform,
const FinishFunctor &finish)
@ -740,7 +740,7 @@ public:
}
private:
vtkm::internal::FunctionInterface<OriginalFunction> &OriginalInterface;
const vtkm::internal::FunctionInterface<OriginalFunction> &OriginalInterface;
vtkm::internal::FunctionInterface<NewFunction> &NewInterface;
const TransformFunctor &Transform;
const FinishFunctor &Finish;

@ -32,16 +32,34 @@ namespace internal {
/// worklet. \c Invocation is a class that manages all these types.
///
template<typename _ParameterInterface,
typename _ControlInterface,
typename _ExecutionInterface,
vtkm::IdComponent _InputDomainIndex>
struct Invocation
{
/// \brief The types of the parameters
///
/// \c ParameterInterface is (expected to be) a FunctionInterface class that
/// lists the types of the parameters for the invocation.
/// \c ParameterInterface is (expected to be) a \c FunctionInterface class
/// that lists the types of the parameters for the invocation.
///
typedef _ParameterInterface ParameterInterface;
/// \brief The tags of the \c ControlSignature.
///
/// \c ControlInterface is (expected to be) a \c FunctionInterface class that
/// represents the \c ControlSignature of a worklet (although dispatchers
/// might modify the control signature to provide auxiliary information).
///
typedef _ControlInterface ControlInterface;
/// \brief The tags of the \c ExecutionSignature.
///
/// \c ExecutionInterface is (expected to be) a \c FunctionInterface class that
/// represents the \c ExecutionSignature of a worklet (although dispatchers
/// might modify the execution signature to provide auxiliary information).
///
typedef _ExecutionInterface ExecutionInterface;
/// \brief The index of the input domain.
///
/// When a worklet is invoked, the pool of working threads is based of some
@ -58,11 +76,14 @@ struct Invocation
///
template<typename NewParameterInterface>
struct ChangeParametersType {
typedef Invocation<NewParameterInterface,InputDomainIndex> type;
typedef Invocation<NewParameterInterface,
ControlInterface,
ExecutionInterface,
InputDomainIndex> type;
};
/// Returns a new \c Invocation that is the same as this one except that the
/// \c Parameters type is changed to the type given.
/// \c Parameters are replaced with those provided.
///
template<typename NewParameterInterface>
VTKM_EXEC_CONT_EXPORT
@ -72,12 +93,57 @@ struct Invocation
newParameters);
}
/// Defines a new \c Invocation type that is the same as this type except
/// with the \c ControlInterface replaced.
///
template<typename NewControlInterface>
struct ChangeControlInterfaceType {
typedef Invocation<ParameterInterface,
NewControlInterface,
ExecutionInterface,
InputDomainIndex> type;
};
/// Returns a new \c Invocation that is the same as this one except that the
/// \c ControlInterface type is changed to the type given.
///
template<typename NewControlInterface>
typename ChangeControlInterfaceType<NewControlInterface>::type
ChangeControlInterface(NewControlInterface) const {
return typename ChangeControlInterfaceType<NewControlInterface>::type(
this->Parameters);
}
/// Defines a new \c Invocation type that is the same as this type except
/// with the \c ExecutionInterface replaced.
///
template<typename NewExecutionInterface>
struct ChangeExecutionInterfaceType {
typedef Invocation<ParameterInterface,
NewExecutionInterface,
ExecutionInterface,
InputDomainIndex> type;
};
/// Returns a new \c Invocation that is the same as this one except that the
/// \c ExecutionInterface type is changed to the type given.
///
template<typename NewExecutionInterface>
typename ChangeExecutionInterfaceType<NewExecutionInterface>::type
ChangeExecutionInterface(NewExecutionInterface) const {
return typename ChangeExecutionInterfaceType<NewExecutionInterface>::type(
this->Parameters);
}
/// Defines a new \c Invocation type that is the same as this type except
/// with the \c InputDomainIndex replaced.
///
template<vtkm::IdComponent NewInputDomainIndex>
struct ChangeInputDomainIndexType {
typedef Invocation<ParameterInterface,NewInputDomainIndex> type;
typedef Invocation<ParameterInterface,
ControlInterface,
ExecutionInterface,
NewInputDomainIndex> type;
};
/// Returns a new \c Invocation that is the same as this one except that the
@ -100,12 +166,21 @@ struct Invocation
/// Convenience function for creating an Invocation object.
///
template<vtkm::IdComponent InputDomainIndex,
typename ControlInterface,
typename ExecutionInterface,
typename ParameterInterface>
VTKM_CONT_EXPORT
vtkm::internal::Invocation<ParameterInterface, InputDomainIndex>
make_Invocation(const ParameterInterface &params)
vtkm::internal::Invocation<ParameterInterface,
ControlInterface,
ExecutionInterface,
InputDomainIndex>
make_Invocation(const ParameterInterface &params,
ControlInterface = ControlInterface(),
ExecutionInterface = ExecutionInterface())
{
return vtkm::internal::Invocation<ParameterInterface,
ControlInterface,
ExecutionInterface,
InputDomainIndex>(params);
}

@ -19,9 +19,12 @@
##============================================================================
set(headers
DispatcherBase.h
WorkletBase.h
)
vtkm_declare_headers(${headers})
#add_subdirectory(testing)
vtkm_pyexpander_generated_file(DispatcherBaseDetailInvoke.h)
add_subdirectory(testing)

@ -0,0 +1,230 @@
//============================================================================
// 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_worklet_internal_DispatcherBase_h
#define vtk_m_worklet_internal_DispatcherBase_h
#include <vtkm/internal/FunctionInterface.h>
#include <vtkm/internal/Invocation.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/arg/Transport.h>
#include <vtkm/cont/internal/DynamicTransform.h>
#include <vtkm/exec/internal/WorkletInvokeFunctor.h>
#include <boost/mpl/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
namespace vtkm {
namespace worklet {
namespace internal {
namespace detail {
template<typename DispatcherBaseType>
struct DispatcherBaseDynamicTransformHelper
{
const DispatcherBaseType *Dispatcher;
VTKM_CONT_EXPORT
DispatcherBaseDynamicTransformHelper(const DispatcherBaseType *dispatcher)
: Dispatcher(dispatcher) { }
template<typename FunctionInterface>
VTKM_CONT_EXPORT
void operator()(const FunctionInterface &parameters) const {
this->Dispatcher->DynamicTransformInvoke(parameters);
}
};
template<typename Device>
struct DispatcherBaseTransportFunctor
{
vtkm::Id NumInstances;
DispatcherBaseTransportFunctor(vtkm::Id numInstances)
: NumInstances(numInstances) { }
template<typename T>
struct InvokeTypes {
typedef typename T::FirstType::TransportTag TransportTag;
typedef typename T::SecondType ControlParameter;
typedef vtkm::cont::arg::Transport<TransportTag,ControlParameter,Device>
TransportType;
};
template<typename T>
struct ReturnType {
typedef typename InvokeTypes<T>::TransportType::ExecObjectType type;
};
template<typename T>
VTKM_CONT_EXPORT
typename ReturnType<T>::type
operator()(const T &invokeData) const {
typename InvokeTypes<T>::TransportType transport;
return transport(invokeData.second, this->NumInstances);
}
};
} // namespace detail
/// Base class for all dispatcher classes. Every worklet type should have its
/// own dispatcher.
///
template<typename DerivedClass,
typename WorkletType,
typename BaseWorkletType,
typename Device>
class DispatcherBase
{
private:
typedef DispatcherBase<DerivedClass,WorkletType,BaseWorkletType,Device> MyType;
friend struct detail::DispatcherBaseDynamicTransformHelper<MyType>;
protected:
typedef vtkm::internal::FunctionInterface<
typename WorkletType::ControlSignature> ControlInterface;
typedef vtkm::internal::FunctionInterface<
typename WorkletType::ExecutionSignature> ExecutionInterface;
static const vtkm::IdComponent NUM_INVOKE_PARAMS = ControlInterface::ARITY;
template<typename Signature>
VTKM_CONT_EXPORT
void StartInvoke(
const vtkm::internal::FunctionInterface<Signature> &parameters) const
{
typedef vtkm::internal::FunctionInterface<Signature> ParameterInterface;
BOOST_STATIC_ASSERT_MSG(ParameterInterface::ARITY == NUM_INVOKE_PARAMS,
"Dispatcher Invoke called with wrong number of arguments.");
BOOST_MPL_ASSERT(( boost::is_base_of<BaseWorkletType,WorkletType> ));
parameters.DynamicTransformCont(
vtkm::cont::internal::DynamicTransform(),
detail::DispatcherBaseDynamicTransformHelper<MyType>(this));
}
template<typename Signature>
VTKM_CONT_EXPORT
void DynamicTransformInvoke(
const vtkm::internal::FunctionInterface<Signature> &parameters) const
{
// TODO: Check parameters
static const vtkm::IdComponent INPUT_DOMAIN_INDEX =
WorkletType::InputDomain::INDEX;
reinterpret_cast<const DerivedClass *>(this)->DoInvoke(
vtkm::internal::make_Invocation<INPUT_DOMAIN_INDEX>(
parameters, ControlInterface(), ExecutionInterface()));
}
public:
// Implementation of the Invoke method is in this generated file.
#include <vtkm/worklet/internal/DispatcherBaseDetailInvoke.h>
protected:
VTKM_CONT_EXPORT
DispatcherBase(const WorkletType &worklet) : Worklet(worklet) { }
template<typename Invocation>
VTKM_CONT_EXPORT
void BasicInvoke(const Invocation &invocation, vtkm::Id numInstances) const
{
this->InvokeTransportParameters(invocation, numInstances);
}
WorkletType Worklet;
private:
// These are not implemented. Dispatchers cannot be copied.
DispatcherBase(const MyType &);
void operator=(const MyType &);
template<typename Invocation>
VTKM_CONT_EXPORT
void InvokeTransportParameters(const Invocation &invocation,
vtkm::Id numInstances) const
{
// The first step in invoking a worklet is transport the arguments to the
// execution environment. The invocation object passed to this function
// contains the parameters passed to Invoke in the control environment. We
// will use the template magic in the FunctionInterface class to invoke the
// appropriate Transport class on each parameter to get a list of execution
// objects (corresponding to the arguments of the Invoke in the control
// environment) in a FunctionInterface.
// The Transport relies on both the ControlSignature tag and the control
// object itself. To make it easier to work with each parameter, use the
// zip mechanism of FunctionInterface to combine the separate function
// interfaces of the ControlSignature and the parameters into one. This
// will make a Function interface with each parameter being a Pair
// containing both the ControlSignature tag and the control object itself.
typedef typename vtkm::internal::FunctionInterfaceZipType<
typename Invocation::ControlInterface,
typename Invocation::ParameterInterface>::type ZippedInterface;
ZippedInterface zippedInterface =
vtkm::internal::make_FunctionInterfaceZip(
typename Invocation::ControlInterface(), invocation.Parameters);
// Use the StaticTransform mechanism to run the
// DispatcherBaseTransportFunctor on each parameter of the zipped
// interface. This functor will in turn run the appropriate Transform on
// the parameter and return the associated execution object. The end result
// of the transform is a FunctionInterface containing execution objects
// corresponding to each Invoke argument.
typedef detail::DispatcherBaseTransportFunctor<Device> TransportFunctor;
typedef typename ZippedInterface::template StaticTransformType<
TransportFunctor>::type ExecObjectParameters;
ExecObjectParameters execObjectParameters =
zippedInterface.StaticTransformCont(TransportFunctor(numInstances));
// Replace the parameters in the invocation with the execution object and
// pass to next step of Invoke.
this->InvokeSchedule(invocation.ChangeParameters(execObjectParameters),
numInstances);
}
template<typename Invocation>
VTKM_CONT_EXPORT
void InvokeSchedule(const Invocation &invocation, vtkm::Id numInstances) const
{
// The WorkletInvokeFunctor class handles the magic of fetching values
// for each instance and calling the worklet's function. So just create
// a WorkletInvokeFunctor and schedule it with the device adapter.
typedef vtkm::exec::internal::WorkletInvokeFunctor<WorkletType,Invocation>
WorkletInvokeFunctorType;
WorkletInvokeFunctorType workletFunctor =
WorkletInvokeFunctorType(this->Worklet, invocation);
typedef vtkm::cont::DeviceAdapterAlgorithm<Device> Algorithm;
Algorithm::Schedule(workletFunctor, numInstances);
}
};
}
}
} // namespace vtkm::worklet::internal
#endif //vtk_m_worklet_internal_DispatcherBase_h

@ -0,0 +1,143 @@
//============================================================================
// 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.
//============================================================================
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by FunctionInterfaceDetailPre.h.in
#if !defined(vtk_m_worklet_internal_DispatcherBase_h)
#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h
#endif
// Note that this file is included from the middle of the DispatcherBase.h
// class to provide the implementation of the Invoke method, which requires
// variable length template args. If we choose to support C++11 variable
// template arguments, then this could all be replaced efficiently with a
// single method with a variadic template function that calls
// make_FunctionInterface.
template<typename T1>
VTKM_CONT_EXPORT
void Invoke(T1 a1) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1));
}
template<typename T1,
typename T2>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2));
}
template<typename T1,
typename T2,
typename T3>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3));
}
template<typename T1,
typename T2,
typename T3,
typename T4>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4));
}
template<typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5));
}
template<typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6));
}
template<typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7));
}
template<typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7,a8));
}
template<typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9>
VTKM_CONT_EXPORT
void Invoke(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>(a1,a2,a3,a4,a5,a6,a7,a8,a9));
}

@ -0,0 +1,86 @@
//============================================================================
// 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.
//============================================================================
$# This file uses the pyexpander macro processing utility to build the
$# FunctionInterface facilities that use a variable number of arguments.
$# Information, documentation, and downloads for pyexpander can be found at:
$#
$# http://pyexpander.sourceforge.net/
$#
$# To build the source code, execute the following (after installing
$# pyexpander, of course):
$#
$# expander.py DispatcherBaseDetailInvoke.h.in > DispatcherBaseDetailInvoke.h
$#
$# Ignore the following comment. It is meant for the generated file.
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by FunctionInterfaceDetailPre.h.in
#if !defined(vtk_m_worklet_internal_DispatcherBase_h)
#error DispatcherBaseDetailInvoke.h must be included from DispatcherBase.h
#endif
// Note that this file is included from the middle of the DispatcherBase.h
// class to provide the implementation of the Invoke method, which requires
// variable length template args. If we choose to support C++11 variable
// template arguments, then this could all be replaced efficiently with a
// single method with a variadic template function that calls
// make_FunctionInterface.
$py(max_parameters=9)\
$# Python commands used in template expansion.
$py(
def template_params(num_params, name='T', start=1, default=''):
if num_params < start:
return ''
result = 'typename %s%d%s' % (name, start, default)
for param in xrange(start+1, num_params+1):
result += ',\n typename %s%d%s' % (name, param, default)
return result
def function_params(num_params, typename='T', argname='a', start=1):
if num_params < start:
return ''
result = '%s%d %s%d' % (typename, start, argname, start)
for param in xrange(start+1, num_params+1):
result += ', %s%d %s%d' % (typename, param, argname, param)
return result
def arg_list(num_params, argname='a', start=1):
if num_params < start:
return ''
result = '%s%d' % (argname, start)
for param in xrange(start+1, num_params+1):
result += ',%s%d' % (argname, param)
return result
)\
$#
$extend(template_params, function_params, arg_list)\
$for(num_params in xrange(1, max_parameters+1))\
template<$template_params(num_params)>
VTKM_CONT_EXPORT
void Invoke($function_params(num_params)) const
{
this->StartInvoke(
vtkm::internal::make_FunctionInterface<void>($arg_list(num_params)));
}
$endfor\

@ -0,0 +1,25 @@
##============================================================================
## 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.
##============================================================================
set(unit_tests
UnitTestDispatcherBase.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,262 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/worklet/internal/DispatcherBase.h>
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/worklet/internal/WorkletBase.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
typedef vtkm::cont::DeviceAdapterTagSerial Device;
static const vtkm::Id ARRAY_SIZE = 10;
struct TestExecObject
{
VTKM_EXEC_CONT_EXPORT
TestExecObject() : Array(NULL) { }
VTKM_EXEC_CONT_EXPORT
TestExecObject(vtkm::Id *array) : Array(array) { }
vtkm::Id *Array;
};
struct TestTransportTag { };
struct TestFetchTagInput { };
struct TestFetchTagOutput { };
} // anonymous namespace
namespace vtkm {
namespace cont {
namespace arg {
template<>
struct Transport<TestTransportTag, vtkm::Id *, Device>
{
typedef TestExecObject ExecObjectType;
VTKM_CONT_EXPORT
ExecObjectType operator()(vtkm::Id *contData, vtkm::Id size) const
{
VTKM_TEST_ASSERT(size == ARRAY_SIZE,
"Got unexpected size in test transport.");
return ExecObjectType(contData);
}
};
}
}
} // namespace vtkm::cont::arg
namespace vtkm {
namespace exec {
namespace arg {
template<typename Invocation, vtkm::IdComponent ParameterIndex>
struct Fetch<TestFetchTagInput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
{
typedef vtkm::Id ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id index, const Invocation &invocation) const {
return invocation.Parameters.
template GetParameter<ParameterIndex>().Array[index];
}
VTKM_EXEC_EXPORT
void Store(vtkm::Id, const Invocation &, ValueType) const {
// No-op
}
};
template<typename Invocation, vtkm::IdComponent ParameterIndex>
struct Fetch<TestFetchTagOutput, vtkm::exec::arg::AspectTagDefault, Invocation, ParameterIndex>
{
typedef vtkm::Id ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id, const Invocation &) const {
// No-op
return ValueType();
}
VTKM_EXEC_EXPORT
void Store(vtkm::Id index,
const Invocation &invocation,
ValueType value) const {
invocation.Parameters.template GetParameter<ParameterIndex>().Array[index] =
value;
}
};
}
}
} // vtkm::exec::arg
namespace {
class TestWorkletBase : public vtkm::worklet::internal::WorkletBase
{
public:
struct TestIn {
typedef TestTransportTag TransportTag;
typedef TestFetchTagInput FetchTag;
};
struct TestOut {
typedef TestTransportTag TransportTag;
typedef TestFetchTagOutput FetchTag;
};
};
class TestWorklet : public TestWorkletBase
{
public:
typedef void ControlSignature(TestIn, TestOut);
typedef _2 ExecutionSignature(_1, WorkIndex);
VTKM_EXEC_EXPORT
vtkm::Id operator()(vtkm::Id value, vtkm::Id index) const
{
VTKM_TEST_ASSERT(value == TestValue(index, vtkm::Id()),
"Got bad value in worklet.");
return TestValue(index, vtkm::Id()) + 1000;
}
};
#define ERROR_MESSAGE "Expected worklet error."
class TestErrorWorklet : public TestWorkletBase
{
public:
typedef void ControlSignature(TestIn, TestOut);
typedef void ExecutionSignature(_1, _2);
VTKM_EXEC_EXPORT
void operator()(vtkm::Id, vtkm::Id) const
{
this->RaiseError(ERROR_MESSAGE);
}
};
template<typename WorkletType>
class TestDispatcher :
public vtkm::worklet::internal::DispatcherBase<
TestDispatcher<WorkletType>,
WorkletType,
TestWorkletBase,
Device>
{
typedef vtkm::worklet::internal::DispatcherBase<
TestDispatcher<WorkletType>,
WorkletType,
TestWorkletBase,
Device> Superclass;
typedef vtkm::internal::FunctionInterface<void(vtkm::Id *, vtkm::Id *)>
ParameterInterface;
typedef vtkm::internal::Invocation<
ParameterInterface,
typename Superclass::ControlInterface,
typename Superclass::ExecutionInterface,
1> Invocation;
public:
VTKM_CONT_EXPORT
TestDispatcher(const WorkletType &worklet = WorkletType())
: Superclass(worklet) { }
VTKM_CONT_EXPORT
void DoInvoke(const Invocation &invocation) const
{
std::cout << "In TestDispatcher::DoInvoke()" << std::endl;
this->BasicInvoke(invocation, ARRAY_SIZE);
}
private:
WorkletType Worklet;
};
void TestBasicInvoke()
{
std::cout << "Set up data." << std::endl;
vtkm::Id inputArray[ARRAY_SIZE];
vtkm::Id outputArray[ARRAY_SIZE];
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
inputArray[index] = TestValue(index, vtkm::Id());
outputArray[index] = 0xDEADDEAD;
}
std::cout << "Create and run dispatcher." << std::endl;
TestDispatcher<TestWorklet> dispatcher;
dispatcher.Invoke(inputArray, outputArray);
std::cout << "Check output of invoke." << std::endl;
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
VTKM_TEST_ASSERT(outputArray[index] == TestValue(index, vtkm::Id()) + 1000,
"Got bad value from testing.");
}
}
void TestInvokeWithError()
{
std::cout << "Set up data." << std::endl;
vtkm::Id inputArray[ARRAY_SIZE];
vtkm::Id outputArray[ARRAY_SIZE];
for (vtkm::Id index = 0; index < ARRAY_SIZE; index++)
{
inputArray[index] = TestValue(index, vtkm::Id());
outputArray[index] = 0xDEADDEAD;
}
try
{
std::cout << "Create and run dispatcher that raises error." << std::endl;
TestDispatcher<TestErrorWorklet> dispatcher;
dispatcher.Invoke(inputArray, outputArray);
VTKM_TEST_FAIL("Exception not thrown.");
}
catch (vtkm::cont::ErrorExecution error)
{
std::cout << "Got expected exception." << std::endl;
VTKM_TEST_ASSERT(error.GetMessage() == ERROR_MESSAGE,
"Got unexpected error message.");
}
}
void TestDispatcherBase()
{
TestBasicInvoke();
TestInvokeWithError();
}
} // anonymous namespace
int UnitTestDispatcherBase(int, char *[])
{
return vtkm::cont::testing::Testing::Run(TestDispatcherBase);
}