mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-10 10:49:04 +08:00
bug #1598: Let MaxSizeVector respect alignment of objects and add a unit test
Also revert 8b3d9ed081fc5d4870290649853b19cb5179546e
This commit is contained in:
parent
d7378aae8e
commit
007f165c69
@ -169,7 +169,9 @@ class EventCount {
|
|||||||
|
|
||||||
class Waiter {
|
class Waiter {
|
||||||
friend class EventCount;
|
friend class EventCount;
|
||||||
std::atomic<Waiter*> next;
|
// Align to 128 byte boundary to prevent false sharing with other Waiter
|
||||||
|
// objects in the same vector.
|
||||||
|
EIGEN_ALIGN_TO_BOUNDARY(128) std::atomic<Waiter*> next;
|
||||||
std::mutex mu;
|
std::mutex mu;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
uint64_t epoch;
|
uint64_t epoch;
|
||||||
@ -179,9 +181,6 @@ class EventCount {
|
|||||||
kWaiting,
|
kWaiting,
|
||||||
kSignaled,
|
kSignaled,
|
||||||
};
|
};
|
||||||
// Pad past 128 byte boundary to prevent false sharing with other Waiter
|
|
||||||
// objects in the same vector.
|
|
||||||
char pad_[128];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -29,12 +29,13 @@ namespace Eigen {
|
|||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class MaxSizeVector {
|
class MaxSizeVector {
|
||||||
|
static const size_t alignment = EIGEN_PLAIN_ENUM_MAX(EIGEN_ALIGNOF(T), sizeof(void*));
|
||||||
public:
|
public:
|
||||||
// Construct a new MaxSizeVector, reserve n elements.
|
// Construct a new MaxSizeVector, reserve n elements.
|
||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
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::handmade_aligned_malloc(n * sizeof(T), alignment))) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a new MaxSizeVector, reserve and resize to n.
|
// Construct a new MaxSizeVector, reserve and resize to n.
|
||||||
@ -42,7 +43,7 @@ class MaxSizeVector {
|
|||||||
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
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::handmade_aligned_malloc(n * sizeof(T), alignment))) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
EIGEN_TRY
|
EIGEN_TRY
|
||||||
{
|
{
|
||||||
@ -52,7 +53,7 @@ class MaxSizeVector {
|
|||||||
{
|
{
|
||||||
// Construction failed, destruct in reverse order:
|
// Construction failed, destruct in reverse order:
|
||||||
for(; (i+1) > 0; --i) { data_[i-1].~T(); }
|
for(; (i+1) > 0; --i) { data_[i-1].~T(); }
|
||||||
internal::aligned_free(data_);
|
internal::handmade_aligned_free(data_);
|
||||||
EIGEN_THROW;
|
EIGEN_THROW;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,7 +63,7 @@ class MaxSizeVector {
|
|||||||
for (size_t i = size_; i > 0; --i) {
|
for (size_t i = size_; i > 0; --i) {
|
||||||
data_[i-1].~T();
|
data_[i-1].~T();
|
||||||
}
|
}
|
||||||
internal::aligned_free(data_);
|
internal::handmade_aligned_free(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(size_t n) {
|
void resize(size_t n) {
|
||||||
|
@ -142,6 +142,7 @@ ei_add_test(cxx11_tensor_sugar)
|
|||||||
ei_add_test(cxx11_tensor_roundings)
|
ei_add_test(cxx11_tensor_roundings)
|
||||||
ei_add_test(cxx11_tensor_layout_swap)
|
ei_add_test(cxx11_tensor_layout_swap)
|
||||||
ei_add_test(cxx11_tensor_io)
|
ei_add_test(cxx11_tensor_io)
|
||||||
|
ei_add_test(cxx11_maxsizevector)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(EIGEN_TEST_CXX11)
|
if(EIGEN_TEST_CXX11)
|
||||||
|
77
unsupported/test/cxx11_maxsizevector.cpp
Normal file
77
unsupported/test/cxx11_maxsizevector.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
#include <exception> // std::exception
|
||||||
|
|
||||||
|
#include <unsupported/Eigen/CXX11/Tensor>
|
||||||
|
|
||||||
|
struct Foo
|
||||||
|
{
|
||||||
|
static Index object_count;
|
||||||
|
static Index object_limit;
|
||||||
|
EIGEN_ALIGN_TO_BOUNDARY(128) int dummy;
|
||||||
|
|
||||||
|
Foo(int x=0) : dummy(x)
|
||||||
|
{
|
||||||
|
#ifdef EIGEN_EXCEPTIONS
|
||||||
|
// TODO: Is this the correct way to handle this?
|
||||||
|
if (Foo::object_count > Foo::object_limit) { std::cout << "\nThrow!\n"; throw Foo::Fail(); }
|
||||||
|
#endif
|
||||||
|
std::cout << '+';
|
||||||
|
++Foo::object_count;
|
||||||
|
eigen_assert((internal::UIntPtr(this) & (127)) == 0);
|
||||||
|
}
|
||||||
|
Foo(const Foo&)
|
||||||
|
{
|
||||||
|
std::cout << 'c';
|
||||||
|
++Foo::object_count;
|
||||||
|
eigen_assert((internal::UIntPtr(this) & (127)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
~Foo()
|
||||||
|
{
|
||||||
|
std::cout << '~';
|
||||||
|
--Foo::object_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fail : public std::exception {};
|
||||||
|
};
|
||||||
|
|
||||||
|
Index Foo::object_count = 0;
|
||||||
|
Index Foo::object_limit = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EIGEN_DECLARE_TEST(cxx11_maxsizevector)
|
||||||
|
{
|
||||||
|
typedef MaxSizeVector<Foo> VectorX;
|
||||||
|
Foo::object_count = 0;
|
||||||
|
for(int r = 0; r < g_repeat; r++) {
|
||||||
|
Index rows = internal::random<Index>(3,30);
|
||||||
|
Foo::object_limit = internal::random<Index>(0, rows - 2);
|
||||||
|
std::cout << "object_limit = " << Foo::object_limit << std::endl;
|
||||||
|
bool exception_raised = false;
|
||||||
|
#ifdef EIGEN_EXCEPTIONS
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
std::cout << "\nVectorX m(" << rows << ");\n";
|
||||||
|
VectorX vect(rows);
|
||||||
|
for(int i=0; i<rows; ++i)
|
||||||
|
vect.push_back(Foo());
|
||||||
|
#ifdef EIGEN_EXCEPTIONS
|
||||||
|
VERIFY(false); // not reached if exceptions are enabled
|
||||||
|
}
|
||||||
|
catch (const Foo::Fail&) { exception_raised = true; }
|
||||||
|
VERIFY(exception_raised);
|
||||||
|
#endif
|
||||||
|
VERIFY_IS_EQUAL(Index(0), Foo::object_count);
|
||||||
|
|
||||||
|
{
|
||||||
|
Foo::object_limit = rows+1;
|
||||||
|
VectorX vect2(rows, Foo());
|
||||||
|
VERIFY_IS_EQUAL(Foo::object_count, rows);
|
||||||
|
}
|
||||||
|
VERIFY_IS_EQUAL(Index(0), Foo::object_count);
|
||||||
|
std::cout << '\n';
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user