//============================================================================ // 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. //============================================================================ #ifndef vtk_m_cont_ExecutionAndControlObjectBase_h #define vtk_m_cont_ExecutionAndControlObjectBase_h #include namespace vtkm { namespace cont { /// Base `ExecutionAndControlObjectBase` class. These are objects that behave /// as execution objects but can also be use din the control environment. /// Any subclass of `ExecutionAndControlObjectBase` must implement a /// `PrepareForExecution` method that takes a device adapter tag and a /// `vtkm::cont::Token` reference and returns /// an object for that device. It also must implement `PrepareForControl` that simply /// returns an object that works in the control environment. /// struct ExecutionAndControlObjectBase : vtkm::cont::ExecutionObjectBase { }; namespace internal { namespace detail { struct CheckPrepareForControl { template static auto check(T* p) -> decltype(p->PrepareForControl(), std::true_type()); template static auto check(...) -> std::false_type; }; } // namespace detail template using IsExecutionAndControlObjectBase = std::is_base_of::type>; template struct HasPrepareForControl : decltype(detail::CheckPrepareForControl::check::type>(nullptr)) { }; /// Checks that the argument is a proper execution object. /// #define VTKM_IS_EXECUTION_AND_CONTROL_OBJECT(execObject) \ static_assert(::vtkm::cont::internal::IsExecutionAndControlObjectBase::value, \ "Provided type is not a subclass of vtkm::cont::ExecutionAndControlObjectBase."); \ static_assert(::vtkm::cont::internal::HasPrepareForExecution::value || \ ::vtkm::cont::internal::HasPrepareForExecutionDeprecated::value, \ "Provided type does not have requisite PrepareForExecution method."); \ static_assert(::vtkm::cont::internal::HasPrepareForControl::value, \ "Provided type does not have requisite PrepareForControl method.") /// \brief Gets the object to use in the control environment from an ExecutionAndControlObject. /// /// An execution and control object (that is, an object inheriting from /// `vtkm::cont::ExecutionAndControlObjectBase`) is really a control object factory that generates /// a objects to be used in either the execution environment or the control environment. This /// function takes a subclass of `ExecutionAndControlObjectBase` and returns the control object. /// template VTKM_CONT auto CallPrepareForControl(T&& execObject) -> decltype(execObject.PrepareForControl()) { VTKM_IS_EXECUTION_AND_CONTROL_OBJECT(T); return execObject.PrepareForControl(); } /// \brief Gets the object to use in the control environment from an ExecutionAndControlObject. /// /// An execution and control object (that is, an object inheriting from /// `vtkm::cont::ExecutionAndControlObjectBase`) is really a control object factory that generates /// a objects to be used in either the execution environment or the control environment. This /// templated type gives the type for the class used in the control environment for a given /// ExecutionAndControlObject. /// template using ControlObjectType = decltype(CallPrepareForControl(std::declval())); } // namespace internal } } // namespace vtkm::cont #endif //vtk_m_cont_ExecutionAndControlObjectBase_h