vtk-m/vtkm/cont/UncertainArrayHandle.h

230 lines
7.5 KiB
C++

//============================================================================
// 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 <vtkm/cont/UnknownArrayHandle.h>
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 <typename ValueTypeList, typename StorageTypeList>
class VTKM_ALWAYS_EXPORT UncertainArrayHandle : public vtkm::cont::UnknownArrayHandle
{
VTKM_IS_LIST(ValueTypeList);
VTKM_IS_LIST(StorageTypeList);
VTKM_STATIC_ASSERT_MSG((!std::is_same<ValueTypeList, vtkm::ListUniversal>::value),
"Cannot use vtkm::ListUniversal with UncertainArrayHandle.");
VTKM_STATIC_ASSERT_MSG((!std::is_same<StorageTypeList, vtkm::ListUniversal>::value),
"Cannot use vtkm::ListUniversal with UncertainArrayHandle.");
using Superclass = UnknownArrayHandle;
using Thisclass = UncertainArrayHandle<ValueTypeList, StorageTypeList>;
public:
VTKM_CONT UncertainArrayHandle() = default;
template <typename T, typename S>
VTKM_CONT UncertainArrayHandle(const vtkm::cont::ArrayHandle<T, S>& array)
: Superclass(array)
{
}
explicit VTKM_CONT UncertainArrayHandle(const vtkm::cont::UnknownArrayHandle& src)
: Superclass(src)
{
}
UncertainArrayHandle(const Thisclass&) = default;
template <typename OtherValues, typename OtherStorage>
VTKM_CONT UncertainArrayHandle(const UncertainArrayHandle<OtherValues, OtherStorage>& 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 <typename NewValueTypeList>
VTKM_CONT UncertainArrayHandle<NewValueTypeList, StorageTypeList> ResetValueTypes(
NewValueTypeList = NewValueTypeList{}) const
{
return this->ResetTypes<NewValueTypeList, StorageTypeList>();
}
/// Like `ResetTypes` except it only resets the storage types.
///
template <typename NewStorageTypeList>
VTKM_CONT UncertainArrayHandle<ValueTypeList, NewStorageTypeList> ResetStorageTypes(
NewStorageTypeList = NewStorageTypeList{}) const
{
return this->ResetTypes<ValueTypeList, NewStorageTypeList>();
}
/// \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 <typename Functor, typename... Args>
VTKM_CONT void CastAndCall(Functor&& functor, Args&&... args) const
{
this->CastAndCallForTypes<ValueTypeList, StorageTypeList>(std::forward<Functor>(functor),
std::forward<Args>(args)...);
}
};
// Defined here to avoid circular dependencies between UnknownArrayHandle and UncertainArrayHandle.
template <typename NewValueTypeList, typename NewStorageTypeList>
VTKM_CONT vtkm::cont::UncertainArrayHandle<NewValueTypeList, NewStorageTypeList>
UnknownArrayHandle::ResetTypes(NewValueTypeList, NewStorageTypeList) const
{
return vtkm::cont::UncertainArrayHandle<NewValueTypeList, NewStorageTypeList>(*this);
}
namespace internal
{
template <typename ValueTypeList, typename StorageTypeList>
struct DynamicTransformTraits<vtkm::cont::UncertainArrayHandle<ValueTypeList, StorageTypeList>>
{
using DynamicTag = vtkm::cont::internal::DynamicTransformTagCastAndCall;
};
} // namespace internal
}
} // namespace vtkm::cont
//=============================================================================
// Specializations of serialization related classes
/// @cond SERIALIZATION
namespace vtkm
{
namespace cont
{
template <typename ValueTypeList, typename StorageTypeList>
struct SerializableTypeString<vtkm::cont::UncertainArrayHandle<ValueTypeList, StorageTypeList>>
{
static VTKM_CONT std::string Get()
{
return SerializableTypeString<vtkm::cont::UnknownArrayHandle>::Get();
}
};
}
} // namespace vtkm::cont
namespace mangled_diy_namespace
{
namespace internal
{
struct UncertainArrayHandleSerializeFunctor
{
template <typename ArrayHandleType>
void operator()(const ArrayHandleType& ah, BinaryBuffer& bb) const
{
vtkmdiy::save(bb, vtkm::cont::SerializableTypeString<ArrayHandleType>::Get());
vtkmdiy::save(bb, ah);
}
};
struct UncertainArrayHandleDeserializeFunctor
{
template <typename T, typename S>
void operator()(vtkm::List<T, S>,
vtkm::cont::UnknownArrayHandle& unknownArray,
const std::string& typeString,
bool& success,
BinaryBuffer& bb) const
{
using ArrayHandleType = vtkm::cont::ArrayHandle<T, S>;
if (!success && (typeString == vtkm::cont::SerializableTypeString<ArrayHandleType>::Get()))
{
ArrayHandleType knownArray;
vtkmdiy::load(bb, knownArray);
unknownArray = knownArray;
success = true;
}
}
};
} // internal
template <typename ValueTypeList, typename StorageTypeList>
struct Serialization<vtkm::cont::UncertainArrayHandle<ValueTypeList, StorageTypeList>>
{
using Type = vtkm::cont::UncertainArrayHandle<ValueTypeList, StorageTypeList>;
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<ValueTypeList, StorageTypeList>{},
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