vtk-m/vtkm/cont/internal/TransferInfo.h
Kenneth Moreland 53c17a6876 Release locks in ArrayHandleVirtual control portals
This fixes an issue where getting a `ReadPortal` or a `WritePortal` from
an `ArrayHandleVirtual` could cause a deadlock from a held token even if
the returned portal was detached or destroyed.

The problem was that `ArrayHandleVirtual` was keeping a reference to the
`ArrayPortal` from the concrete array. This was because the returned
`ArrayPortalRef`, which was designed to work on both control and
execution environments, had no good way to destroy the portal. This
meant that the `ArrayHandleVirtual` was caching a copy of the concrete
array's portal. This was not a great idea before because the array could
get invalidated. It is worse now because it keeps the concrete array
locked.

Fixed the problem by subclassing `vtkm::ArrayPortalRef` to make a
control-specific version that will delete the concrete portal on its own
destruction.
2020-03-09 15:53:38 -06:00

68 lines
2.0 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_TransferInfo_h
#define vtk_m_cont_internal_TransferInfo_h
#include <vtkm/cont/vtkm_cont_export.h>
#include <vtkm/Types.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/internal/ArrayPortalVirtual.h>
#include <memory>
namespace vtkm
{
namespace internal
{
class PortalVirtualBase;
}
namespace cont
{
namespace internal
{
struct VTKM_CONT_EXPORT TransferInfoArray
{
bool valid(vtkm::cont::DeviceAdapterId tagValue) const noexcept;
void updateHost(std::unique_ptr<vtkm::internal::PortalVirtualBase>&& host) noexcept;
void updateDevice(
vtkm::cont::DeviceAdapterId id,
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& host_copy, //NOT the same as host version
const vtkm::internal::PortalVirtualBase* device,
const std::shared_ptr<void>& state) noexcept;
void releaseDevice();
void releaseAll();
std::unique_ptr<vtkm::internal::PortalVirtualBase>&& hostPtr() noexcept
{
return std::move(this->Host);
}
const vtkm::internal::PortalVirtualBase* devicePtr() const noexcept { return this->Device; }
vtkm::cont::DeviceAdapterId deviceId() const noexcept { return this->DeviceId; }
std::shared_ptr<void>& state() noexcept { return this->DeviceTransferState; }
private:
vtkm::cont::DeviceAdapterId DeviceId = vtkm::cont::DeviceAdapterTagUndefined{};
std::unique_ptr<vtkm::internal::PortalVirtualBase> Host = nullptr;
std::unique_ptr<vtkm::internal::PortalVirtualBase> HostCopyOfDevice = nullptr;
const vtkm::internal::PortalVirtualBase* Device = nullptr;
std::shared_ptr<void> DeviceTransferState = nullptr;
};
}
}
}
#endif