//============================================================================ // 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_VirtualObjectHandle_h #define vtk_m_cont_VirtualObjectHandle_h #include #include #include #include #ifdef VTKM_NO_DEPRECATED_VIRTUAL #error "This header should not be included when VTKM_NO_DEPRECATED_VIRTUAL is set." #endif //VTKM_NO_DEPRECATED_VIRTUAL // This is a deprecated class. Don't warn about deprecation while implementing // deprecated functionality. VTKM_DEPRECATED_SUPPRESS_BEGIN #include #include namespace vtkm { namespace cont { namespace internal { struct CreateTransferInterface { template VTKM_CONT inline void operator()(DeviceAdapter device, internal::TransferState* transfers, const VirtualDerivedType* virtualObject) const { using TransferImpl = TransferInterfaceImpl; auto i = static_cast(device.GetValue()); transfers->DeviceTransferState[i].reset(new TransferImpl(virtualObject)); } }; } /// \brief Implements VTK-m's execution side Virtual Methods functionality. /// /// The template parameter \c VirtualBaseType is the base class that acts as the /// interface. This base clase must inherit from \c vtkm::VirtualObjectBase. See the /// documentation of that class to see the other requirements. /// /// A derived object can be bound to the handle either during construction or using the \c Reset /// function on previously constructed handles. These function accept a control side pointer to /// the derived class object, a boolean flag stating if the handle should acquire ownership of /// the object (i.e. manage the lifetime), and a type-list of device adapter tags where the object /// is expected to be used. /// /// To get an execution side pointer call the \c PrepareForExecution function. The device adapter /// passed to this function should be one of the device in the list passed during the set up of /// the handle. /// /// /// \sa vtkm::VirtualObjectBase /// template class VTKM_ALWAYS_EXPORT VTKM_DEPRECATED( 1.7, "Virtual methods are no longer supported in the execution environment.") VirtualObjectHandle : public vtkm::cont::ExecutionAndControlObjectBase { VTKM_STATIC_ASSERT_MSG((std::is_base_of::value), "All virtual objects must be subclass of vtkm::VirtualObjectBase."); public: VTKM_CONT VirtualObjectHandle() : Internals(std::make_shared()) { } template VTKM_CONT explicit VirtualObjectHandle(VirtualDerivedType* derived, bool acquireOwnership = true, DeviceAdapterList devices = DeviceAdapterList()) : Internals(std::make_shared()) { this->Reset(derived, acquireOwnership, devices); } /// Get if in a valid state (a target is bound) VTKM_CONT bool GetValid() const { return this->Internals->HostPtr() != nullptr; } /// Get if this handle owns the control side target object VTKM_CONT bool OwnsObject() const { return this->Internals->WillReleaseHostPointer(); } /// Get the control side pointer to the virtual object VTKM_CONT VirtualBaseType* Get() const { return static_cast(this->Internals->HostPtr()); } /// Reset the underlying derived type object template VTKM_CONT void Reset(VirtualDerivedType* derived, bool acquireOwnership = true, DeviceAdapterList devices = DeviceAdapterList()) { VTKM_DEPRECATED_SUPPRESS_BEGIN VTKM_STATIC_ASSERT_MSG((std::is_base_of::value), "Tried to bind a type that is not a subclass of the base class."); if (acquireOwnership) { auto deleter = [](void* p) { delete static_cast(p); }; this->Internals->UpdateHost(derived, deleter); } else { this->Internals->UpdateHost(derived, nullptr); } if (derived) { vtkm::cont::internal::ForEachValidDevice( devices, internal::CreateTransferInterface(), this->Internals.get(), derived); } VTKM_DEPRECATED_SUPPRESS_END } /// Release all host and execution side resources VTKM_CONT void ReleaseResources() { this->Internals->ReleaseResources(); } /// Release all the execution side resources VTKM_CONT void ReleaseExecutionResources() { this->Internals->ReleaseExecutionResources(); } /// Get a valid \c VirtualBaseType* with the current control side state for \c deviceId. /// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal /// The returned pointer will be invalidated if: /// 1. A new pointer is requested for a different deviceId /// 2. VirtualObjectHandle is destroyed /// 3. Reset or ReleaseResources is called /// VTKM_CONT const VirtualBaseType* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId, vtkm::cont::Token&) const { const bool validId = this->Internals->DeviceIdIsValid(deviceId); if (!validId) { //can't be reached since DeviceIdIsValid will through an exception //if deviceId is not valid return nullptr; } return static_cast(this->Internals->PrepareForExecution(deviceId)); } VTKM_CONT VTKM_DEPRECATED(1.6, "PrepareForExecution now requires a vtkm::cont::Token object.") const VirtualBaseType* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId) const { vtkm::cont::Token token; return this->PrepareForExecution(deviceId, token); } /// Used as part of the \c ExecutionAndControlObjectBase interface. Returns the same pointer /// as \c Get. VTKM_CONT const VirtualBaseType* PrepareForControl() const { return this->Get(); } private: std::shared_ptr Internals; }; } } // vtkm::cont VTKM_DEPRECATED_SUPPRESS_END #endif // vtk_m_cont_VirtualObjectHandle_h