Commit acf825b2 authored by Robert Maynard's avatar Robert Maynard

Correct IsType and Cast on ArrayHandleVirtual to work on OSX.

parent 7b9fa975
...@@ -51,16 +51,6 @@ public: ...@@ -51,16 +51,6 @@ public:
void ReleaseResources(); void ReleaseResources();
private: private:
// StorageAny is meant to be seamless when it comes to IsType so we will match
// when either the type_info is 'StorageAny<T,S>' or 'Storage<T,S>'. That is why
// we need to override the default implementation.
bool IsSameType(const std::type_info& other) const
{
//We don't wan to check just 'S' as that just the tag
using ST = typename vtkm::cont::internal::Storage<T, S>;
return other == typeid(ST) || other == typeid(*this);
}
std::unique_ptr<StorageVirtual> MakeNewInstance() const std::unique_ptr<StorageVirtual> MakeNewInstance() const
{ {
return std::unique_ptr<StorageVirtual>(new StorageAny<T, S>{ vtkm::cont::ArrayHandle<T, S>{} }); return std::unique_ptr<StorageVirtual>(new StorageAny<T, S>{ vtkm::cont::ArrayHandle<T, S>{} });
......
...@@ -115,7 +115,8 @@ private: ...@@ -115,7 +115,8 @@ private:
/// array at that position. /// array at that position.
/// ///
template <class FunctorType> template <class FunctorType>
class ArrayHandleImplicit : public detail::ArrayHandleImplicitTraits<FunctorType>::Superclass class VTKM_ALWAYS_EXPORT ArrayHandleImplicit
: public detail::ArrayHandleImplicitTraits<FunctorType>::Superclass
{ {
private: private:
using ArrayTraits = typename detail::ArrayHandleImplicitTraits<FunctorType>; using ArrayTraits = typename detail::ArrayHandleImplicitTraits<FunctorType>;
......
...@@ -134,7 +134,6 @@ public: ...@@ -134,7 +134,6 @@ public:
return true; // different valuetype and/or storage return true; // different valuetype and/or storage
} }
/// Returns true if this array's storage matches the type passed in. /// Returns true if this array's storage matches the type passed in.
/// ///
template <typename ArrayHandleType> template <typename ArrayHandleType>
...@@ -155,6 +154,28 @@ public: ...@@ -155,6 +154,28 @@ public:
return this->IsSameType<ArrayHandleType>(is_base{}); return this->IsSameType<ArrayHandleType>(is_base{});
} }
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
/// ErrorBadType if the cast does not work. Use \c IsType
/// to check if the cast can happen.
///
template <typename ArrayHandleType>
VTKM_CONT ArrayHandleType Cast() const
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
using VT = typename ArrayHandleType::ValueType;
static_assert(
std::is_same<VT, T>::value,
"ArrayHandleVirtual<ValueType> can only be casted to an ArrayHandle of the same ValueType.");
//We need to determine if we are checking that `ArrayHandleType`
//is a virtual array handle since that is an easy check.
//Or if we have to go ask the storage if they are holding
//
using ST = typename ArrayHandleType::StorageTag;
using is_base = std::is_same<vtkm::cont::StorageTagVirtual, ST>;
return this->CastToType<ArrayHandleType>(is_base{});
}
/// Returns a new instance of an ArrayHandleVirtual with the same storage /// Returns a new instance of an ArrayHandleVirtual with the same storage
/// ///
VTKM_CONT ArrayHandle<T, ::vtkm::cont::StorageTagVirtual> NewInstance() const VTKM_CONT ArrayHandle<T, ::vtkm::cont::StorageTagVirtual> NewInstance() const
...@@ -285,19 +306,36 @@ private: ...@@ -285,19 +306,36 @@ private:
bool IsSameType(std::true_type vtkmNotUsed(inheritsFromArrayHandleVirtual)) const bool IsSameType(std::true_type vtkmNotUsed(inheritsFromArrayHandleVirtual)) const
{ {
//All classes that derive from ArrayHandleVirtual have virtual methods so we can use //All classes that derive from ArrayHandleVirtual have virtual methods so we can use
//typeid directly //typeid directly.
return typeid(*this) == typeid(ArrayHandleType); //needs optimizations based on platform. !OSX can use typeid
return nullptr != dynamic_cast<const ArrayHandleType*>(this);
} }
template <typename ArrayHandleType> template <typename ArrayHandleType>
bool IsSameType(std::false_type vtkmNotUsed(notFromArrayHandleVirtual)) const bool IsSameType(std::false_type vtkmNotUsed(notFromArrayHandleVirtual)) const;
template <typename ArrayHandleType>
ArrayHandleType CastToType(std::true_type vtkmNotUsed(inheritsFromArrayHandleVirtual)) const
{ {
//We need to go long the way to find the StorageType //All classes that derive from ArrayHandleVirtual have virtual methods so we can use
//as StorageType is private on lots of derived ArrayHandles //dynamic_cast directly
//See Issue #314 if (!this->Storage)
using ST = typename ArrayHandleType::StorageTag; {
return this->Storage->IsType(typeid(vtkm::cont::internal::Storage<T, ST>)); VTKM_LOG_CAST_FAIL(*this, ArrayHandleType);
throwFailedDynamicCast("ArrayHandleVirtual", vtkm::cont::TypeName<ArrayHandleType>());
}
const ArrayHandleType* derived = dynamic_cast<const ArrayHandleType*>(this);
if (!derived)
{
VTKM_LOG_CAST_FAIL(*this, ArrayHandleType);
throwFailedDynamicCast("ArrayHandleVirtual", vtkm::cont::TypeName<ArrayHandleType>());
}
VTKM_LOG_CAST_SUCC(*this, derived);
return *derived;
} }
template <typename ArrayHandleType>
ArrayHandleType CastToType(std::false_type vtkmNotUsed(notFromArrayHandleVirtual)) const;
}; };
//============================================================================= //=============================================================================
...@@ -306,6 +344,23 @@ template <typename T> ...@@ -306,6 +344,23 @@ template <typename T>
using ArrayHandleVirtual = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>; using ArrayHandleVirtual = vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagVirtual>;
//=============================================================================
// Free function casting helpers
template <typename ArrayHandleType, typename T>
VTKM_CONT inline bool IsType(const vtkm::cont::ArrayHandleVirtual<T>& virtHandle)
{
return virtHandle.template IsType<ArrayHandleType>();
}
template <typename ArrayHandleType, typename T>
VTKM_CONT inline ArrayHandleType Cast(const vtkm::cont::ArrayHandleVirtual<T>& virtHandle)
{
return virtHandle.template Cast<ArrayHandleType>();
}
//============================================================================= //=============================================================================
// Specializations of serialization related classes // Specializations of serialization related classes
template <typename T> template <typename T>
......
...@@ -22,12 +22,43 @@ ...@@ -22,12 +22,43 @@
#include <vtkm/cont/ArrayHandleVirtual.h> #include <vtkm/cont/ArrayHandleVirtual.h>
#include <vtkm/cont/ArrayHandleAny.h>
#include <vtkm/cont/TryExecute.h> #include <vtkm/cont/TryExecute.h>
namespace vtkm namespace vtkm
{ {
namespace cont namespace cont
{ {
template <typename T>
template <typename ArrayHandleType>
bool ArrayHandle<T, StorageTagVirtual>::IsSameType(
std::false_type vtkmNotUsed(notFromArrayHandleVirtual)) const
{
if (!this->Storage)
{
return false;
}
using S = typename ArrayHandleType::StorageTag;
return this->Storage->template IsType<vtkm::cont::StorageAny<T, S>>();
}
template <typename T>
template <typename ArrayHandleType>
ArrayHandleType ArrayHandle<T, StorageTagVirtual>::CastToType(
std::false_type vtkmNotUsed(notFromArrayHandleVirtual)) const
{
if (!this->Storage)
{
VTKM_LOG_CAST_FAIL(*this, ArrayHandleType);
throwFailedDynamicCast("ArrayHandleVirtual", vtkm::cont::TypeName<ArrayHandleType>());
}
using S = typename ArrayHandleType::StorageTag;
const auto* any = this->Storage->template Cast<vtkm::cont::StorageAny<T, S>>();
return any->GetHandle();
}
namespace detail namespace detail
{ {
template <typename DerivedPortal> template <typename DerivedPortal>
...@@ -69,7 +100,6 @@ inline void make_hostPortal(Payload&& payload, Args&&... args) ...@@ -69,7 +100,6 @@ inline void make_hostPortal(Payload&& payload, Args&&... args)
#include <vtkm/cont/ArrayHandleAny.h>
//============================================================================= //=============================================================================
// Specializations of serialization related classes // Specializations of serialization related classes
namespace diy namespace diy
......
...@@ -40,7 +40,7 @@ namespace cont ...@@ -40,7 +40,7 @@ namespace cont
{ {
/// ArrayHandleVirtualCoordinates is a specialization of ArrayHandle. /// ArrayHandleVirtualCoordinates is a specialization of ArrayHandle.
class VTKM_CONT_EXPORT ArrayHandleVirtualCoordinates final class VTKM_ALWAYS_EXPORT ArrayHandleVirtualCoordinates final
: public vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>> : public vtkm::cont::ArrayHandleVirtual<vtkm::Vec<vtkm::FloatDefault, 3>>
{ {
public: public:
...@@ -77,20 +77,6 @@ public: ...@@ -77,20 +77,6 @@ public:
using ST = typename decltype(castedHandle)::StorageTag; using ST = typename decltype(castedHandle)::StorageTag;
this->Storage = std::make_shared<vtkm::cont::StorageAny<ValueType, ST>>(castedHandle); this->Storage = std::make_shared<vtkm::cont::StorageAny<ValueType, ST>>(castedHandle);
} }
/// Returns this array cast to the given \c ArrayHandle type. Throws \c
/// ErrorBadType if the cast does not work. Use \c IsType
/// to check if the cast can happen.
///
template <typename ArrayHandleType>
VTKM_CONT ArrayHandleType Cast() const
{
using T = typename ArrayHandleType::ValueType;
using S = typename ArrayHandleType::StorageTag;
const vtkm::cont::StorageVirtual* storage = this->GetStorage();
const auto* any = storage->Cast<vtkm::cont::StorageAny<T, S>>();
return any->GetHandle();
}
}; };
template <typename Functor, typename... Args> template <typename Functor, typename... Args>
...@@ -111,7 +97,6 @@ void CastAndCall(const vtkm::cont::ArrayHandleVirtualCoordinates& coords, ...@@ -111,7 +97,6 @@ void CastAndCall(const vtkm::cont::ArrayHandleVirtualCoordinates& coords,
} }
template <> template <>
struct TypeString<vtkm::cont::ArrayHandleVirtualCoordinates> struct TypeString<vtkm::cont::ArrayHandleVirtualCoordinates>
{ {
......
...@@ -53,7 +53,8 @@ namespace internal ...@@ -53,7 +53,8 @@ namespace internal
{ {
template <class ArrayPortalType> template <class ArrayPortalType>
class Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>> class VTKM_ALWAYS_EXPORT
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>
{ {
using ClassType = using ClassType =
Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>; Storage<typename ArrayPortalType::ValueType, StorageTagImplicit<ArrayPortalType>>;
......
...@@ -87,12 +87,6 @@ void Storage<void, ::vtkm::cont::StorageTagVirtual>::ReleaseResources() ...@@ -87,12 +87,6 @@ void Storage<void, ::vtkm::cont::StorageTagVirtual>::ReleaseResources()
this->DeviceUpToDate = false; this->DeviceUpToDate = false;
} }
//--------------------------------------------------------------------
bool Storage<void, ::vtkm::cont::StorageTagVirtual>::IsSameType(const std::type_info& other) const
{
return typeid(*this) == other;
}
//-------------------------------------------------------------------- //--------------------------------------------------------------------
std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>> std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>>
Storage<void, ::vtkm::cont::StorageTagVirtual>::NewInstance() const Storage<void, ::vtkm::cont::StorageTagVirtual>::NewInstance() const
......
...@@ -34,7 +34,7 @@ namespace vtkm ...@@ -34,7 +34,7 @@ namespace vtkm
namespace cont namespace cont
{ {
struct StorageTagVirtual struct VTKM_ALWAYS_EXPORT StorageTagVirtual
{ {
}; };
...@@ -99,7 +99,11 @@ public: ...@@ -99,7 +99,11 @@ public:
/// Determines if storage types matches the type passed in. /// Determines if storage types matches the type passed in.
/// ///
bool IsType(const std::type_info& other) const { return this->IsSameType(other); } template <typename DerivedStorage>
bool IsType() const
{ //needs optimizations based on platform. !OSX can use typeid
return nullptr != dynamic_cast<const DerivedStorage*>(this);
}
/// \brief Create a new storage of the same type as this storage. /// \brief Create a new storage of the same type as this storage.
/// ///
...@@ -155,7 +159,6 @@ private: ...@@ -155,7 +159,6 @@ private:
// virtual void DoShrink(vtkm::Id numberOfValues) = 0; // virtual void DoShrink(vtkm::Id numberOfValues) = 0;
//RTTI routines //RTTI routines
virtual bool IsSameType(const std::type_info&) const;
virtual std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>> MakeNewInstance() virtual std::unique_ptr<Storage<void, ::vtkm::cont::StorageTagVirtual>> MakeNewInstance()
const = 0; const = 0;
......
...@@ -89,31 +89,23 @@ struct Transport<vtkm::cont::arg::TransportTagAtomicArray, ...@@ -89,31 +89,23 @@ struct Transport<vtkm::cont::arg::TransportTagAtomicArray,
vtkm::Id, vtkm::Id,
vtkm::Id) const vtkm::Id) const
{ {
using S = vtkm::cont::StorageTagBasic; using ArrayHandleType = vtkm::cont::ArrayHandle<T>;
const bool is_type = vtkm::cont::IsType<ArrayHandleType>(array);
const vtkm::cont::StorageVirtual* storage = array.GetStorage(); if (!is_type)
if (!storage)
{
throw vtkm::cont::ErrorBadValue("ArrayHandleVirtual must not have a nullptr for storage.");
}
if (!storage->IsType(typeid(vtkm::cont::internal::Storage<T, S>)))
{ {
#if defined(VTKM_ENABLE_LOGGING) #if defined(VTKM_ENABLE_LOGGING)
using AH = vtkm::cont::ArrayHandle<T, S>; VTKM_LOG_CAST_FAIL(array, ArrayHandleType);
VTKM_LOG_CAST_FAIL(array, AH);
#endif #endif
throw vtkm::cont::ErrorBadValue("Arrays being used as atomic's must always have storage that " throw vtkm::cont::ErrorBadValue("Arrays being used as atomic's must always have storage that "
"is of the type StorageTagBasic."); "is of the type StorageTagBasic.");
} }
const auto* any = static_cast<const vtkm::cont::StorageAny<T, S>*>(storage); ArrayHandleType handle = vtkm::cont::Cast<ArrayHandleType>(array);
VTKM_LOG_CAST_SUCC(array, *any);
// Note: we ignore the size of the domain because the randomly accessed // Note: we ignore the size of the domain because the randomly accessed
// array might not have the same size depending on how the user is using // array might not have the same size depending on how the user is using
// the array. // the array.
ExecType obj(any->GetHandle()); ExecType obj(handle);
return obj.PrepareForExecution(Device()); return obj.PrepareForExecution(Device());
} }
}; };
......
...@@ -137,11 +137,11 @@ VTKM_CONT bool IsType(const VariantArrayHandleContainerBase* container) ...@@ -137,11 +137,11 @@ VTKM_CONT bool IsType(const VariantArrayHandleContainerBase* container)
{ {
return false; return false;
} }
using VT = typename ArrayHandleType::ValueType; using VT = typename ArrayHandleType::ValueType;
using ST = typename ArrayHandleType::StorageTag; using ST = typename ArrayHandleType::StorageTag;
const vtkm::cont::StorageVirtual* storage = container->GetStorage(); const vtkm::cont::StorageVirtual* storage = container->GetStorage();
return storage->IsType(typeid(vtkm::cont::internal::Storage<VT, ST>)); return storage->IsType<vtkm::cont::StorageAny<VT, ST>>();
} }
template <typename T> template <typename T>
...@@ -151,7 +151,9 @@ VTKM_CONT bool IsValueType(const VariantArrayHandleContainerBase* container) ...@@ -151,7 +151,9 @@ VTKM_CONT bool IsValueType(const VariantArrayHandleContainerBase* container)
{ //you can't use typeid on nullptr of polymorphic types { //you can't use typeid on nullptr of polymorphic types
return false; return false;
} }
return typeid(VariantArrayHandleContainer<T>) == typeid(*container);
//needs optimizations based on platform. !OSX can use typeid
return (nullptr != dynamic_cast<const VariantArrayHandleContainer<T>*>(container));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment