Support providing a Token to ReadPortal and WritePortal

When managing portals in the execution environment, `ArrayHandle` uses the
`Token` object to ensure that the memory associated with a portal exists
for the length of time that it is needed. This is done by creating the
portal with a `Token` object, and the associated portal objects are
guaranteed to be valid while that `Token` object exists. This is supported
by essentially locking the array from further changes.

`Token` objects are typically used when creating a control-side portal with
the `ReadPortal` or `WritePortal`. This is not to say that a `Token` would
not be useful; a control-side portal going out of scope is definitely a
problem. But the creation and distruction of portals in the control
environment is generally too much work for the possible benefits.

However, under certain circumstances it could be useful to use a `Token` to
get a control-side portal. For example, if the `PrepareForExecution` method
of an `ExecutionObjectBase` needs to fill a small `ArrayHandle` on the
control side to pass to the execution side, it would be better to use the
provided `Token` object when doing so. This change allows you to optionally
provide that `Token` when creating these control-side portals.
This commit is contained in:
Kenneth Moreland 2022-11-01 09:29:17 -06:00
parent 81f1982afa
commit 54f0ef2a88
3 changed files with 35 additions and 5 deletions

@ -0,0 +1,21 @@
# Support providing a Token to ReadPortal and WritePortal
When managing portals in the execution environment, `ArrayHandle` uses the
`Token` object to ensure that the memory associated with a portal exists
for the length of time that it is needed. This is done by creating the
portal with a `Token` object, and the associated portal objects are
guaranteed to be valid while that `Token` object exists. This is supported
by essentially locking the array from further changes.
`Token` objects are typically used when creating a control-side portal with
the `ReadPortal` or `WritePortal`. This is not to say that a `Token` would
not be useful; a control-side portal going out of scope is definitely a
problem. But the creation and distruction of portals in the control
environment is generally too much work for the possible benefits.
However, under certain circumstances it could be useful to use a `Token` to
get a control-side portal. For example, if the `PrepareForExecution` method
of an `ExecutionObjectBase` needs to fill a small `ArrayHandle` on the
control side to pass to the execution side, it would be better to use the
provided `Token` object when doing so. This change allows you to optionally
provide that `Token` when creating these control-side portals.

@ -452,6 +452,7 @@ public:
ReadPortalType GetPortalConstControl() const { return this->ReadPortal(); }
/// \endcond
///@{
/// \brief Get an array portal that can be used in the control environment.
///
/// The returned array can be used in the control environment to read values from the array. (It
@ -465,9 +466,14 @@ public:
VTKM_CONT ReadPortalType ReadPortal() const
{
vtkm::cont::Token token;
return this->ReadPortal(token);
}
VTKM_CONT ReadPortalType ReadPortal(vtkm::cont::Token& token) const
{
return StorageType::CreateReadPortal(
this->GetBuffers(), vtkm::cont::DeviceAdapterTagUndefined{}, token);
}
///@}
/// \brief Get an array portal that can be used in the control environment.
///
@ -481,7 +487,10 @@ public:
VTKM_CONT WritePortalType WritePortal() const
{
vtkm::cont::Token token;
return this->WritePortal(token);
}
VTKM_CONT WritePortalType WritePortal(vtkm::cont::Token& token) const
{
return StorageType::CreateWritePortal(
this->GetBuffers(), vtkm::cont::DeviceAdapterTagUndefined{}, token);
}

@ -67,10 +67,10 @@ const vtkm::exec::CellLocatorPartitioned CellLocatorPartitioned::PrepareForExecu
this->Update();
vtkm::Id numPartitions = this->Partitions.GetNumberOfPartitions();
this->LocatorsExec.Allocate(numPartitions, vtkm::CopyFlag::Off);
auto portalLocators = this->LocatorsExec.WritePortal();
this->GhostsExec.Allocate(numPartitions, vtkm::CopyFlag::Off);
auto portalGhosts = this->GhostsExec.WritePortal();
this->LocatorsExec.Allocate(numPartitions, vtkm::CopyFlag::Off, token);
auto portalLocators = this->LocatorsExec.WritePortal(token);
this->GhostsExec.Allocate(numPartitions, vtkm::CopyFlag::Off, token);
auto portalGhosts = this->GhostsExec.WritePortal(token);
for (vtkm::Id index = 0; index < numPartitions; ++index)
{
// fill arrayhandle of cellLocators