//============================================================================ // 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_UncertainArrayHandle_h #define vtk_m_cont_UncertainArrayHandle_h #include namespace vtkm { namespace cont { /// \brief An ArrayHandle of an uncertain value type and storage. /// /// `UncertainArrayHandle` holds an `ArrayHandle` object using runtime polymorphism /// to manage different value and storage types. It behaves like its superclass, /// `UnknownArrayHandle`, except that it also contains two template parameters that /// provide `vtkm::List`s of potential value and storage types, respectively. /// /// These potential value and storage types come into play when the `CastAndCall` /// method is called (or the `UncertainArrayHandle` is used in the /// `vtkm::cont::CastAndCall` function). In this case, the `CastAndCall` will /// search for `ArrayHandle`s of types that match these two lists. /// /// Both `UncertainArrayHandle` and `UnknownArrayHandle` have a method named /// `ResetTypes` that redefine the lists of potential value and storage types /// by returning a new `UncertainArrayHandle` containing the same `ArrayHandle` /// but with the new value and storage type lists. /// template class VTKM_ALWAYS_EXPORT UncertainArrayHandle : public vtkm::cont::UnknownArrayHandle { VTKM_IS_LIST(ValueTypeList); VTKM_IS_LIST(StorageTypeList); VTKM_STATIC_ASSERT_MSG((!std::is_same::value), "Cannot use vtkm::ListUniversal with UncertainArrayHandle."); VTKM_STATIC_ASSERT_MSG((!std::is_same::value), "Cannot use vtkm::ListUniversal with UncertainArrayHandle."); using Superclass = UnknownArrayHandle; using Thisclass = UncertainArrayHandle; public: VTKM_CONT UncertainArrayHandle() = default; template VTKM_CONT UncertainArrayHandle(const vtkm::cont::ArrayHandle& array) : Superclass(array) { } explicit VTKM_CONT UncertainArrayHandle(const vtkm::cont::UnknownArrayHandle& src) : Superclass(src) { } UncertainArrayHandle(const Thisclass&) = default; template VTKM_CONT UncertainArrayHandle(const UncertainArrayHandle& src) : Superclass(src) { } /// \brief Create a new array of the same type as this array. /// /// This method creates a new array that is the same type as this one and /// returns a new `UncertainArrayHandle` for it. This method is convenient when /// creating output arrays that should be the same type as some input array. /// VTKM_CONT Thisclass NewInstance() const { return Thisclass(this->Superclass::NewInstance()); } /// Like `ResetTypes` except it only resets the value types. /// template VTKM_CONT UncertainArrayHandle ResetValueTypes( NewValueTypeList = NewValueTypeList{}) const { return this->ResetTypes(); } /// Like `ResetTypes` except it only resets the storage types. /// template VTKM_CONT UncertainArrayHandle ResetStorageTypes( NewStorageTypeList = NewStorageTypeList{}) const { return this->ResetTypes(); } /// \brief Call a functor using the underlying array type. /// /// `CastAndCall` attempts to cast the held array to a specific value type, /// and then calls the given functor with the cast array. /// template VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const { this->CastAndCallForTypes(std::forward(functor), std::forward(args)...); } }; // Defined here to avoid circular dependencies between UnknownArrayHandle and UncertainArrayHandle. template VTKM_CONT vtkm::cont::UncertainArrayHandle UnknownArrayHandle::ResetTypes(NewValueTypeList, NewStorageTypeList) const { return vtkm::cont::UncertainArrayHandle(*this); } namespace internal { template struct DynamicTransformTraits> { using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall; }; } // namespace internal } } // namespace vtkm::cont //============================================================================= // Specializations of serialization related classes /// @cond SERIALIZATION namespace vtkm { namespace cont { template struct SerializableTypeString> { static VTKM_CONT std::string Get() { return SerializableTypeString::Get(); } }; } } // namespace vtkm::cont namespace mangled_diy_namespace { namespace internal { struct UncertainArrayHandleSerializeFunctor { template void operator()(const ArrayHandleType& ah, BinaryBuffer& bb) const { vtkmdiy::save(bb, vtkm::cont::SerializableTypeString::Get()); vtkmdiy::save(bb, ah); } }; struct UncertainArrayHandleDeserializeFunctor { template void operator()(vtkm::List, vtkm::cont::UnknownArrayHandle& unknownArray, const std::string& typeString, bool& success, BinaryBuffer& bb) const { using ArrayHandleType = vtkm::cont::ArrayHandle; if (!success && (typeString == vtkm::cont::SerializableTypeString::Get())) { ArrayHandleType knownArray; vtkmdiy::load(bb, knownArray); unknownArray = knownArray; success = true; } } }; } // internal template struct Serialization> { using Type = vtkm::cont::UncertainArrayHandle; public: static VTKM_CONT void save(BinaryBuffer& bb, const Type& obj) { obj.CastAndCall(internal::UncertainArrayHandleSerializeFunctor{}, bb); } static VTKM_CONT void load(BinaryBuffer& bb, Type& obj) { std::string typeString; vtkmdiy::load(bb, typeString); bool success = false; vtkm::ListForEach(internal::UncertainArrayHandleDeserializeFunctor{}, vtkm::cont::detail::ListAllArrayTypes{}, obj, typeString, success, bb); if (!success) { throw vtkm::cont::ErrorBadType( "Error deserializing Unknown/UncertainArrayHandle. Message TypeString: " + typeString); } } }; } // namespace mangled_diy_namespace /// @endcond SERIALIZATION #endif //vtk_m_cont_UncertainArrayHandle_h