vtk-m/vtkm/cont/internal/VirtualObjectTransfer.h
Kenneth Moreland cb3bb43ff9 Completely deprecate virtual methods
Deprecate `VirtualObjectHandle` and all other classes that are used to
implement objects with virtual methods in the execution environment.

Additionally, the code is updated so that if the
`VTKm_NO_DEPRECATED_VIRTUAL` flag is set none of the code is compiled at
all. This opens us up to opportunities that do not work with virtual
methods such as backends that do not support virtual methods and dynamic
libraries for CUDA.
2021-04-28 07:28:32 -06:00

181 lines
5.6 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_internal_VirtualObjectTransfer_h
#define vtk_m_cont_internal_VirtualObjectTransfer_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/Deprecated.h>
#include <vtkm/VirtualObjectBase.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#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 <array>
#include <memory>
namespace vtkm
{
namespace cont
{
namespace internal
{
struct CreateTransferInterface; //forward declare for friendship
template <typename VirtualDerivedType, typename DeviceAdapter>
struct VTKM_DEPRECATED(1.7, "Virtual methods are no longer supported in the execution environment.")
VirtualObjectTransfer
#ifdef VTKM_DOXYGEN_ONLY
{
/// A VirtualObjectTransfer is constructed with a pointer to the derived type that (eventually)
/// gets transferred to the execution environment of the given DeviceAdapter.
///
VTKM_CONT VirtualObjectTransfer(const VirtualDerivedType* virtualObject);
/// \brief Transfers the virtual object to the execution environment.
///
/// This method transfers the virtual object to the execution environment and returns a pointer
/// to the object that can be used in the execution environment (but not necessarily the control
/// environment). If the \c updateData flag is true, then the data is always copied to the
/// execution environment (such as if the data were updated since the last call to \c
/// PrepareForExecution). If the \c updateData flag is false and the object was already
/// transferred previously, the previously created object is returned.
///
VTKM_CONT const VirtualDerivedType* PrepareForExecution(bool updateData);
/// \brief Frees up any resources in the execution environment.
///
/// Any previously returned virtual object from \c PrepareForExecution becomes invalid.
///
VTKM_CONT void ReleaseResources();
}
#endif
;
class VTKM_CONT_EXPORT VTKM_DEPRECATED(
1.7,
"Virtual methods are no longer supported in the execution environment.") TransferInterface
{
public:
VTKM_CONT virtual ~TransferInterface();
VTKM_CONT virtual const vtkm::VirtualObjectBase* PrepareForExecution(
vtkm::Id hostModifiedCount) = 0;
VTKM_CONT virtual void ReleaseResources() = 0;
};
template <typename VirtualDerivedType, typename DeviceAdapter>
class TransferInterfaceImpl final : public TransferInterface
{
public:
VTKM_CONT TransferInterfaceImpl(const VirtualDerivedType* virtualObject)
: LastModifiedCount(-1)
, Transfer(virtualObject)
{
}
VTKM_CONT const vtkm::VirtualObjectBase* PrepareForExecution(vtkm::Id hostModifiedCount) override
{
bool updateData = (this->LastModifiedCount != hostModifiedCount);
const vtkm::VirtualObjectBase* executionObject = this->Transfer.PrepareForExecution(updateData);
this->LastModifiedCount = hostModifiedCount;
return executionObject;
}
VTKM_CONT void ReleaseResources() override { this->Transfer.ReleaseResources(); }
private:
vtkm::Id LastModifiedCount;
vtkm::cont::internal::VirtualObjectTransfer<VirtualDerivedType, DeviceAdapter> Transfer;
};
struct VTKM_CONT_EXPORT VTKM_DEPRECATED(
1.7,
"Virtual methods are no longer supported in the execution environment.") TransferState
{
TransferState() = default;
~TransferState() { this->ReleaseResources(); }
bool DeviceIdIsValid(vtkm::cont::DeviceAdapterId deviceId) const;
bool WillReleaseHostPointer() const { return this->DeleteFunction != nullptr; }
void UpdateHost(vtkm::VirtualObjectBase* host, void (*deleteFunction)(void*))
{
if (this->HostPointer != host)
{
this->ReleaseResources();
this->HostPointer = host;
this->DeleteFunction = deleteFunction;
}
}
void ReleaseResources()
{
this->ReleaseExecutionResources();
//This needs to be updated to release all execution information
if (this->DeleteFunction)
{
this->DeleteFunction(this->HostPointer);
}
this->HostPointer = nullptr;
this->DeleteFunction = nullptr;
}
void ReleaseExecutionResources()
{
//This needs to be updated to only release the active execution part
for (auto& state : this->DeviceTransferState)
{
if (state)
{
state->ReleaseResources();
}
}
}
const vtkm::VirtualObjectBase* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId) const
{
//make sure the device is up to date
auto index = static_cast<std::size_t>(deviceId.GetValue());
vtkm::Id count = this->HostPointer->GetModifiedCount();
return this->DeviceTransferState[index]->PrepareForExecution(count);
}
vtkm::VirtualObjectBase* HostPtr() const { return this->HostPointer; }
private:
friend struct CreateTransferInterface;
vtkm::VirtualObjectBase* HostPointer = nullptr;
void (*DeleteFunction)(void*) = nullptr;
std::array<std::unique_ptr<TransferInterface>, 8> DeviceTransferState;
};
}
}
} // vtkm::cont::internal
VTKM_DEPRECATED_SUPPRESS_END
#endif // vtkm_cont_internal_VirtualObjectTransfer_h