Make MaxSizeVector leak-safe

This commit is contained in:
Christoph Hertzberg 2018-08-23 19:37:56 +02:00
parent ff8e0ecc2f
commit 39335cf51e

View File

@ -35,7 +35,6 @@ class MaxSizeVector {
explicit MaxSizeVector(size_t n) explicit MaxSizeVector(size_t n)
: reserve_(n), size_(0), : reserve_(n), size_(0),
data_(static_cast<T*>(internal::aligned_malloc(n * sizeof(T)))) { data_(static_cast<T*>(internal::aligned_malloc(n * sizeof(T)))) {
for (size_t i = 0; i < n; ++i) { new (&data_[i]) T; }
} }
// Construct a new MaxSizeVector, reserve and resize to n. // Construct a new MaxSizeVector, reserve and resize to n.
@ -44,35 +43,55 @@ class MaxSizeVector {
MaxSizeVector(size_t n, const T& init) MaxSizeVector(size_t n, const T& init)
: reserve_(n), size_(n), : reserve_(n), size_(n),
data_(static_cast<T*>(internal::aligned_malloc(n * sizeof(T)))) { data_(static_cast<T*>(internal::aligned_malloc(n * sizeof(T)))) {
for (size_t i = 0; i < n; ++i) { new (&data_[i]) T(init); } size_t i = 0;
EIGEN_TRY
{
for(; i < size_; ++i) { new (&data_[i]) T(init); }
}
EIGEN_CATCH(...)
{
// Construction failed, destruct in reverse order:
for(; (i+1) > 0; --i) { data_[i-1].~T(); }
internal::aligned_free(data_);
EIGEN_THROW;
}
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
~MaxSizeVector() { ~MaxSizeVector() {
for (size_t i = 0; i < size_; ++i) { for (size_t i = size_; i > 0; --i) {
data_[i].~T(); data_[i-1].~T();
} }
internal::aligned_free(data_); internal::aligned_free(data_);
} }
void resize(size_t n) { void resize(size_t n) {
eigen_assert(n <= reserve_); eigen_assert(n <= reserve_);
for (size_t i = size_; i < n; ++i) { for (; size_ < n; ++size_) {
new (&data_[i]) T; new (&data_[size_]) T;
} }
for (size_t i = n; i < size_; ++i) { for (; size_ > n; --size_) {
data_[i].~T(); data_[size_-1].~T();
} }
size_ = n; eigen_assert(size_ == n);
} }
// Append new elements (up to reserved size). // Append new elements (up to reserved size).
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void push_back(const T& t) { void push_back(const T& t) {
eigen_assert(size_ < reserve_); eigen_assert(size_ < reserve_);
data_[size_++] = t; new (&data_[size_++]) T(t);
} }
// For C++03 compatibility this only takes one argument
template<class X>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void emplace_back(const X& x) {
eigen_assert(size_ < reserve_);
new (&data_[size_++]) T(x);
}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const T& operator[] (size_t i) const { const T& operator[] (size_t i) const {
eigen_assert(i < size_); eigen_assert(i < size_);
@ -99,11 +118,8 @@ class MaxSizeVector {
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void pop_back() { void pop_back() {
// NOTE: This does not destroy the value at the end the way
// std::vector's version of pop_back() does. That happens when
// the Vector is destroyed.
eigen_assert(size_ > 0); eigen_assert(size_ > 0);
size_--; data_[--size_].~T();
} }
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE