Make sure important vtkm::cont classes have noexcept move ops.

This is important so they can be stored efficiently inside
containers such as std::vector that require strong move guarantees.
This commit is contained in:
Robert Maynard 2018-12-07 15:54:20 -05:00
parent 6520ca1ff9
commit 0da7830d9a
11 changed files with 219 additions and 14 deletions

@ -109,8 +109,10 @@ public:
VTKM_CONT CellSetExplicit(const std::string& name = std::string());
VTKM_CONT CellSetExplicit(const Thisclass& src);
VTKM_CONT CellSetExplicit(Thisclass&& src) noexcept;
VTKM_CONT Thisclass& operator=(const Thisclass& src);
VTKM_CONT Thisclass& operator=(Thisclass&& src) noexcept;
virtual ~CellSetExplicit();

@ -51,6 +51,19 @@ VTKM_CONT CellSetExplicit<ShapeStorageTag,
{
}
template <typename ShapeStorageTag,
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
VTKM_CONT CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CellSetExplicit(Thisclass &&src) noexcept
: CellSet(std::forward<CellSet>(src)),
Data(std::move(src.Data))
{
}
template <typename ShapeStorageTag,
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
@ -64,6 +77,19 @@ operator=(const Thisclass& src) -> Thisclass&
return *this;
}
template <typename ShapeStorageTag,
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,
typename OffsetsStorageTag>
VTKM_CONT auto
CellSetExplicit<ShapeStorageTag, NumIndicesStorageTag, ConnectivityStorageTag, OffsetsStorageTag>::
operator=(Thisclass&& src) noexcept -> Thisclass&
{
this->CellSet::operator=(std::forward<CellSet>(src));
this->Data = std::move(src.Data);
return *this;
}
template <typename ShapeStorageTag,
typename NumIndicesStorageTag,
typename ConnectivityStorageTag,

@ -52,8 +52,10 @@ public:
}
CellSetStructured(const Thisclass& src);
CellSetStructured(Thisclass&& src) noexcept;
Thisclass& operator=(const Thisclass& src);
Thisclass& operator=(Thisclass&& src) noexcept;
vtkm::Id GetNumberOfCells() const override { return this->Structure.GetNumberOfCells(); }

@ -30,6 +30,13 @@ CellSetStructured<DIMENSION>::CellSetStructured(const CellSetStructured<DIMENSIO
{
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>::CellSetStructured(CellSetStructured<DIMENSION>&& src) noexcept
: CellSet(std::forward<CellSet>(src)),
Structure(std::move(src.Structure))
{
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>& CellSetStructured<DIMENSION>::operator=(
const CellSetStructured<DIMENSION>& src)
@ -39,6 +46,15 @@ CellSetStructured<DIMENSION>& CellSetStructured<DIMENSION>::operator=(
return *this;
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>& CellSetStructured<DIMENSION>::operator=(
CellSetStructured<DIMENSION>&& src) noexcept
{
this->CellSet::operator=(std::forward<CellSet>(src));
this->Structure = std::move(src.Structure);
return *this;
}
template <vtkm::IdComponent DIMENSION>
template <typename TopologyElement>
typename CellSetStructured<DIMENSION>::SchedulingRangeType

@ -57,9 +57,6 @@ public:
vtkm::Vec<vtkm::FloatDefault, 3> origin = vtkm::Vec<vtkm::FloatDefault, 3>(0.0f, 0.0f, 0.0f),
vtkm::Vec<vtkm::FloatDefault, 3> spacing = vtkm::Vec<vtkm::FloatDefault, 3>(1.0f, 1.0f, 1.0f));
VTKM_CONT
CoordinateSystem& operator=(const vtkm::cont::CoordinateSystem& src) = default;
VTKM_CONT
vtkm::cont::ArrayHandleVirtualCoordinates GetData() const;

@ -24,11 +24,6 @@ namespace vtkm
{
namespace cont
{
DataSet::DataSet()
{
}
void DataSet::Clear()
{
this->CoordSystems.clear();

@ -38,8 +38,6 @@ namespace cont
class VTKM_CONT_EXPORT DataSet
{
public:
VTKM_CONT DataSet();
VTKM_CONT void Clear();
VTKM_CONT void AddField(const Field& field) { this->Fields.push_back(field); }

@ -74,6 +74,55 @@ Field::Field(std::string name,
VTKM_ASSERT(this->FieldAssociation == Association::LOGICAL_DIM);
}
VTKM_CONT
Field::Field(const vtkm::cont::Field& src)
: Name(src.Name)
, FieldAssociation(src.FieldAssociation)
, AssocCellSetName(src.AssocCellSetName)
, AssocLogicalDim(src.AssocLogicalDim)
, Data(src.Data)
, Range(src.Range)
, ModifiedFlag(src.ModifiedFlag)
{
}
VTKM_CONT
Field::Field(vtkm::cont::Field&& src) noexcept : Name(std::move(src.Name)),
FieldAssociation(std::move(src.FieldAssociation)),
AssocCellSetName(std::move(src.AssocCellSetName)),
AssocLogicalDim(std::move(src.AssocLogicalDim)),
Data(std::move(src.Data)),
Range(std::move(src.Range)),
ModifiedFlag(std::move(src.ModifiedFlag))
{
}
VTKM_CONT
Field& Field::operator=(const vtkm::cont::Field& src)
{
this->Name = src.Name;
this->FieldAssociation = src.FieldAssociation;
this->AssocCellSetName = src.AssocCellSetName;
this->AssocLogicalDim = src.AssocLogicalDim;
this->Data = src.Data;
this->Range = src.Range;
this->ModifiedFlag = src.ModifiedFlag;
return *this;
}
VTKM_CONT
Field& Field::operator=(vtkm::cont::Field&& src) noexcept
{
this->Name = std::move(src.Name);
this->FieldAssociation = std::move(src.FieldAssociation);
this->AssocCellSetName = std::move(src.AssocCellSetName);
this->AssocLogicalDim = std::move(src.AssocLogicalDim);
this->Data = std::move(src.Data);
this->Range = std::move(src.Range);
this->ModifiedFlag = std::move(src.ModifiedFlag);
return *this;
}
VTKM_CONT
void Field::PrintSummary(std::ostream& out) const

@ -118,11 +118,13 @@ public:
{
}
VTKM_CONT
virtual ~Field();
Field(const vtkm::cont::Field& src);
Field(vtkm::cont::Field&& src) noexcept;
VTKM_CONT
Field& operator=(const vtkm::cont::Field& src) = default;
VTKM_CONT virtual ~Field();
VTKM_CONT Field& operator=(const vtkm::cont::Field& src);
VTKM_CONT Field& operator=(vtkm::cont::Field&& src) noexcept;
VTKM_CONT
const std::string& GetName() const { return this->Name; }

@ -72,6 +72,7 @@ set(unit_tests
UnitTestDynamicCellSet.cxx
UnitTestFieldRangeCompute.cxx
UnitTestLogging.cxx
UnitTestMoveConstructors.cxx
UnitTestMultiBlock.cxx
UnitTestRuntimeDeviceInformation.cxx
UnitTestRuntimeDeviceNames.cxx

@ -0,0 +1,117 @@
//============================================================================
// 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.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleVirtualCoordinates.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/CellSetStructured.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h>
#include <vtkm/TypeListTag.h>
#include <vtkm/cont/testing/Testing.h>
#include <type_traits>
namespace
{
// clang-format off
template<typename T>
void is_noexcept_movable()
{
constexpr bool valid = std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value;
std::string msg = typeid(T).name() + std::string(" should be noexcept moveable");
VTKM_TEST_ASSERT(valid, msg);
}
template<typename T>
void is_triv_noexcept_movable()
{
constexpr bool valid =
#if !(defined(VTKM_GCC) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
//GCC 4.8 doesn't have implementations for is_trivially_*
std::is_trivially_move_constructible<T>::value &&
std::is_trivially_move_assignable<T>::value &&
#endif
std::is_nothrow_move_constructible<T>::value &&
std::is_nothrow_move_assignable<T>::value;
std::string msg = typeid(T).name() + std::string(" should be noexcept moveable");
VTKM_TEST_ASSERT(valid, msg);
}
// clang-format o
struct IsTrivNoExcept
{
template <typename T>
void operator()(T) const
{
is_triv_noexcept_movable<T>();
}
};
struct IsNoExceptHandle
{
template <typename T>
void operator()(T) const
{
is_noexcept_movable< vtkm::cont::ArrayHandle<T> >();
}
};
}
//-----------------------------------------------------------------------------
void TestContDataTypesHaveMoveSemantics()
{
//verify the Vec types are triv and noexcept
vtkm::testing::Testing::TryTypes( IsTrivNoExcept{}, vtkm::TypeListTagVecCommon{} );
is_triv_noexcept_movable<vtkm::Vec<vtkm::Vec<float,3>,3>>();
//verify that ArrayHandles are noexcept movable
//allowing for efficient storage in containers such as std::vector
vtkm::testing::Testing::TryTypes( IsNoExceptHandle{}, vtkm::TypeListTagAll{} );
//verify the DataSet, Field, and CoordinateSystem,
//all have efficient storage in containers such as std::vector
is_noexcept_movable<vtkm::cont::DataSet>();
is_noexcept_movable<vtkm::cont::Field>();
is_noexcept_movable<vtkm::cont::CoordinateSystem>();
//verify the CellSetStructured, and CellSetExplicit
//have efficient storage in containers such as std::vector
is_noexcept_movable<vtkm::cont::CellSetStructured<2>>();
is_noexcept_movable<vtkm::cont::CellSetStructured<3>>();
is_noexcept_movable<vtkm::cont::CellSetExplicit<>>();
}
//-----------------------------------------------------------------------------
int UnitTestMoveConstructors(int, char* [])
{
return vtkm::cont::testing::Testing::Run(TestContDataTypesHaveMoveSemantics);
}