clean up the new FastSmallVector class

also, this fixes some potential memory leaks if vectors of different
sizes are assigned and it fixes the assignment-to-self (`x = x`) case.
This commit is contained in:
Andreas Lauser
2019-03-20 12:36:36 +01:00
parent a8f5501e15
commit 1e7d566a93
4 changed files with 148 additions and 166 deletions

View File

@@ -79,7 +79,7 @@ specializationTemplate = \
#include <opm/material/common/Valgrind.hpp>
{% if numDerivs < 0 %}\
#include "FastSmallVector.hpp"
#include <opm/material/common/FastSmallVector.hpp>
{% else %}\
#include <array>
{% endif %}\

View File

@@ -0,0 +1,146 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::FastSmallVector
*/
#ifndef OPM_FAST_SMALL_VECTOR_HPP
#define OPM_FAST_SMALL_VECTOR_HPP
#include <array>
#include <cstring>
namespace Opm {
template <typename ValueType, unsigned N>
class FastSmallVector
{
public:
FastSmallVector()
{
size_ = 0;
dataPtr_ = smallBuf_.data();
}
explicit FastSmallVector(const size_t numElem)
{
init_(numElem);
}
FastSmallVector(const size_t numElem, const ValueType value)
{
init_(numElem);
std::fill(dataPtr_, dataPtr_ + size_, value);
}
FastSmallVector(const FastSmallVector& other)
{
size_ = 0;
dataPtr_ = smallBuf_.data();
(*this) = other;
}
FastSmallVector(FastSmallVector&& other)
{
size_ = 0;
dataPtr_ = smallBuf_.data();
(*this) = std::move(other);
}
~FastSmallVector()
{
if (dataPtr_ != smallBuf_.data())
delete [] dataPtr_;
}
FastSmallVector& operator=(FastSmallVector&& other)
{
if (dataPtr_ != smallBuf_.data() && dataPtr_ != other.dataPtr_)
delete [] dataPtr_;
size_ = other.size_;
if (size_ <= N) {
smallBuf_ = std::move(other.smallBuf_);
dataPtr_ = smallBuf_.data();
}
else
dataPtr_ = other.dataPtr_;
other.dataPtr_ = nullptr;
other.size_ = 0;
return (*this);
}
FastSmallVector& operator=(const FastSmallVector& other)
{
size_ = other.size_;
if (size_ <= N) {
smallBuf_ = other.smallBuf_;
dataPtr_ = smallBuf_.data();
}
else if (dataPtr_ != other.dataPtr_) {
if (dataPtr_ != smallBuf_.data())
delete[] dataPtr_;
dataPtr_ = new ValueType[size_];
std::copy(other.dataPtr_, other.dataPtr_ + size_, dataPtr_);
}
return (*this);
}
ValueType& operator[](size_t idx)
{ return dataPtr_[idx]; }
const ValueType& operator[](size_t idx) const
{ return dataPtr_[idx]; }
size_t size() const
{ return size_; }
private:
void init_(size_t numElem)
{
size_ = numElem;
if (size_ > N)
dataPtr_ = new ValueType[size_];
else
dataPtr_ = smallBuf_.data();
}
std::array<ValueType, N> smallBuf_;
std::size_t size_;
ValueType* dataPtr_;
};
} // namespace Opm
#endif // OPM_FAST_SMALL_VECTOR_HPP

View File

@@ -37,7 +37,7 @@
#include <opm/material/common/Valgrind.hpp>
#include "FastSmallVector.hpp"
#include <opm/material/common/FastSmallVector.hpp>
#include <cmath>
#include <cassert>
#include <cstring>

View File

@@ -1,164 +0,0 @@
#include <array>
#include <cstring>
namespace Opm {
namespace DenseAd {
template <typename ValueType, unsigned N>
class FastSmallVector
{
public:
FastSmallVector();
explicit FastSmallVector(const size_t num_elem);
FastSmallVector(const size_t num_elem, const ValueType value);
FastSmallVector(const FastSmallVector& other);
FastSmallVector(FastSmallVector&& other);
~FastSmallVector();
FastSmallVector& operator=(const FastSmallVector& other);
FastSmallVector& operator=(FastSmallVector&& other);
ValueType& operator[](size_t index);
const ValueType& operator[](size_t index) const;
size_t size() const;
private:
std::array<ValueType, N> small_buffer_;
std::size_t size_;
ValueType* data_ptr_;
};
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
FastSmallVector()
: size_(0)
, data_ptr_(small_buffer_.data())
{
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
FastSmallVector(const size_t num_elem)
: size_(num_elem)
, data_ptr_(small_buffer_.data())
{
if (size_ > N) {
data_ptr_ = new ValueType[num_elem];
}
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
FastSmallVector(const size_t num_elem, const ValueType value)
: FastSmallVector(num_elem)
{
std::fill_n(data_ptr_, size_, value);
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
FastSmallVector(FastSmallVector&& other)
: size_ (other.size_)
{
small_buffer_ = std::move(other.small_buffer_);
if (size_ <= N) {
data_ptr_ = small_buffer_.data();
} else {
data_ptr_ = other.data_ptr_;
}
other.data_ptr_= nullptr;
other.size_ = 0;
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
FastSmallVector(const FastSmallVector& other)
: small_buffer_(other.small_buffer_)
, size_(other.size_)
{
if (size_ <= N) {
data_ptr_ = small_buffer_.data();
} else {
data_ptr_ = new ValueType[size_];
memcpy(data_ptr_, other.data_ptr_, size_ * sizeof(ValueType));
}
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>&
FastSmallVector<ValueType, N>::
operator = (const FastSmallVector&other)
{
small_buffer_ = other.small_buffer_;
size_ = other.size_;
if (size_ <= N) {
data_ptr_ = small_buffer_.data();
} else {
data_ptr_ = new ValueType[size_];
memcpy(data_ptr_, other.data_ptr_, size_ * sizeof(ValueType));
}
return (*this);
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>&
FastSmallVector<ValueType, N>::
operator = (FastSmallVector&& other)
{
if (data_ptr_ != small_buffer_.data() && data_ptr_ != nullptr) {
delete [] data_ptr_;
}
size_ = other.size_;
small_buffer_ = std::move(other.small_buffer_);
if (size_ <= N) {
data_ptr_ = small_buffer_.data();
} else {
data_ptr_ = other.data_ptr_;
}
other.data_ptr_ = nullptr;
other.size_ = 0;
return (*this);
}
template <typename ValueType, unsigned N>
FastSmallVector<ValueType, N>::
~FastSmallVector()
{
if ((data_ptr_ != small_buffer_.data()) && (data_ptr_ != nullptr)) {
delete [] data_ptr_;
}
}
template <typename ValueType, unsigned N>
ValueType&
FastSmallVector<ValueType, N>::
operator[](size_t index)
{
return data_ptr_[index];
}
template <typename ValueType, unsigned N>
const ValueType&
FastSmallVector<ValueType, N>::
operator[](size_t index) const
{
return data_ptr_[index];
}
template <typename ValueType, unsigned N>
size_t
FastSmallVector<ValueType, N>::
size() const
{
return size_;
}
}
}