Skip to content

Commit c54b520

Browse files
author
Terry Cojean
committed
Fix issues pointed by reviews.
1 parent 57d0ae7 commit c54b520

2 files changed

Lines changed: 57 additions & 23 deletions

File tree

core/test/base/array.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3333
#include <ginkgo/core/base/array.hpp>
3434

3535

36+
#include <algorithm>
37+
38+
3639
#include <gtest/gtest.h>
3740

3841

@@ -284,14 +287,14 @@ TYPED_TEST(Array, CanBeResized)
284287
}
285288

286289

287-
TYPED_TEST(Array, VewCanBeResetNotResized)
290+
TYPED_TEST(Array, ViewCanBeResetNotResized)
288291
{
289292
TypeParam data[] = {1, 2, 3};
290293
auto view = gko::Array<TypeParam>::view(this->exec, 3, data);
291294
view.resize_and_reset(1);
292295

293296
EXPECT_EQ(view.get_const_data(), nullptr);
294-
ASSERT_EQ(view.get_num_elems(), 1);
297+
ASSERT_EQ(view.get_num_elems(), 0);
295298
}
296299

297300

@@ -342,6 +345,7 @@ TYPED_TEST(Array, CopyArrayToArray)
342345
EXPECT_EQ(array.get_data()[2], TypeParam{2});
343346
EXPECT_EQ(array.get_data()[3], TypeParam{1});
344347
EXPECT_EQ(array.get_num_elems(), 4);
348+
EXPECT_NE(array.get_data(), array2.get_data());
345349
ASSERT_EQ(array2.get_num_elems(), 4);
346350
}
347351

@@ -363,6 +367,7 @@ TYPED_TEST(Array, CopyViewToView)
363367
EXPECT_EQ(data[2], TypeParam{2});
364368
EXPECT_EQ(view.get_num_elems(), 3);
365369
EXPECT_EQ(view2.get_num_elems(), 3);
370+
EXPECT_EQ(view2.get_data()[0], TypeParam{2});
366371
ASSERT_THROW(view2 = view_size4, gko::OutOfBoundsError);
367372
}
368373

@@ -407,9 +412,11 @@ TYPED_TEST(Array, MoveArrayToArray)
407412
{
408413
gko::Array<TypeParam> array(this->exec, {1, 2, 3});
409414
gko::Array<TypeParam> array2(this->exec, {5, 4, 2, 1});
415+
auto data2 = array2.get_data();
410416

411417
array = std::move(array2);
412418

419+
EXPECT_EQ(array.get_data(), data2);
413420
EXPECT_EQ(array.get_data()[0], TypeParam{5});
414421
EXPECT_EQ(array.get_data()[1], TypeParam{4});
415422
EXPECT_EQ(array.get_data()[2], TypeParam{2});
@@ -435,7 +442,12 @@ TYPED_TEST(Array, MoveViewToView)
435442
EXPECT_EQ(view.get_data()[2], TypeParam{2});
436443
EXPECT_EQ(view.get_num_elems(), 3);
437444
EXPECT_EQ(view2.get_data(), nullptr);
438-
ASSERT_EQ(view2.get_num_elems(), 0);
445+
EXPECT_EQ(view2.get_num_elems(), 0);
446+
EXPECT_NE(data, nullptr);
447+
EXPECT_EQ(data[0], TypeParam{1});
448+
EXPECT_EQ(data[1], TypeParam{2});
449+
EXPECT_EQ(data[2], TypeParam{3});
450+
ASSERT_EQ(data[3], TypeParam{4});
439451
}
440452

441453

@@ -468,13 +480,18 @@ TYPED_TEST(Array, MoveArrayToView)
468480
auto view = gko::Array<TypeParam>::view(this->exec, 3, data);
469481
gko::Array<TypeParam> array_size2(this->exec, {5, 4});
470482
gko::Array<TypeParam> array_size4(this->exec, {5, 4, 2, 1});
483+
auto size2_ptr = array_size2.get_data();
484+
auto size4_ptr = array_size4.get_data();
471485

472486
view = std::move(array_size2);
473487

474488
EXPECT_EQ(view.get_data()[0], TypeParam{5});
475489
EXPECT_EQ(view.get_data()[1], TypeParam{4});
476490
EXPECT_EQ(view.get_num_elems(), 2);
477-
EXPECT_NO_THROW(view = array_size4);
491+
EXPECT_NE(view.get_data(), data);
492+
EXPECT_EQ(view.get_data(), size2_ptr);
493+
EXPECT_NO_THROW(view = std::move(array_size4));
494+
EXPECT_EQ(view.get_data(), size4_ptr);
478495
EXPECT_EQ(array_size2.get_data(), nullptr);
479496
ASSERT_EQ(array_size2.get_num_elems(), 0);
480497
}

include/ginkgo/core/base/array.hpp

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,11 @@ class Array {
295295
data_ = data_manager{nullptr, other.data_.get_deleter()};
296296
}
297297
if (other.get_executor() == nullptr) {
298-
this->resize_and_reset(0);
298+
this->clear();
299299
return *this;
300300
}
301-
// We allow resizing only if we are an array, we cannot resize a view!
302-
// If we are a view, we do bound checking to ensure the data can be
303-
// copied over.
304-
if (data_.get_deleter().target_type() != typeid(view_deleter)) {
301+
302+
if (this->resize_is_allowed()) {
305303
this->resize_and_reset(other.get_num_elems());
306304
} else {
307305
GKO_ENSURE_COMPATIBLE_BOUNDS(other.get_num_elems(),
@@ -322,12 +320,14 @@ class Array {
322320
* b = std::move(a);
323321
* ```
324322
* Depending on whether `a` and `b` are array or view, this happens:
325-
* + `a` and `b` are view, `b` becomes the only valid view of `a`
326-
* + `a` and `b` are array, `b` becomes the only valid array of `a`
327-
* + `a` is `a` view and `b` is an array, `b` frees its data and becomes the
328-
* only valid view of `a`
329-
* + `a` is an array and `b` is `a` view, `b` becomes the only valid array
330-
* of `a`
323+
* + `a` and `b` are views, `b` becomes the only valid view of `a`;
324+
* + `a` and `b` are arrays, `b` becomes the only valid array of `a`;
325+
* + `a` is a view and `b` is an array, `b` frees its data and becomes the
326+
* only valid view of `a` ();
327+
* + `a` is an array and `b` is a view, `b` becomes the only valid array
328+
* of `a`.
329+
*
330+
* In all the previous cases, `a` becomes invalid (e.g., a `nullptr`).
331331
*
332332
* This does not invoke the constructors of the elements, instead they are
333333
* copied as POD types.
@@ -349,15 +349,15 @@ class Array {
349349
data_ = data_manager{nullptr, other.data_.get_deleter()};
350350
}
351351
if (other.get_executor() == nullptr) {
352-
this->resize_and_reset(0);
352+
this->clear();
353353
return *this;
354354
}
355355
if (exec_ == other.get_executor()) {
356356
// same device, only move the pointer
357357
using std::swap;
358358
swap(data_, other.data_);
359359
swap(num_elems_, other.num_elems_);
360-
other.resize_and_reset(0);
360+
other.clear();
361361
} else {
362362
// different device, copy the data
363363
*this = other;
@@ -380,8 +380,9 @@ class Array {
380380

381381
/**
382382
* Resizes the array so it is able to hold the specified number of elements.
383-
* To a view, this only resets the pointer. Afterwards, the only way to use
384-
* a view in such a state is to `std::move` another view.
383+
* In a view, this resets the pointer, so it does not point to anything
384+
* (`num_elems` will also be set to 0). After a reset of a view, the view
385+
can be moved to in order to reuse it if needed.
385386
*
386387
* All data stored in the array will be lost.
387388
*
@@ -400,14 +401,13 @@ class Array {
400401
"gko::Executor (nullptr)");
401402
}
402403

403-
num_elems_ = num_elems;
404404
// For views, we should never allocate any data, all we can do is unset
405405
// the pointer.
406-
if (num_elems > 0 &&
407-
data_.get_deleter().target_type() != typeid(view_deleter)) {
406+
if (num_elems > 0 && this->resize_is_allowed()) {
407+
num_elems_ = num_elems;
408408
data_.reset(exec_->alloc<value_type>(num_elems));
409409
} else {
410-
data_.reset(nullptr);
410+
this->clear();
411411
}
412412
}
413413

@@ -464,6 +464,23 @@ class Array {
464464
data_ = std::move(tmp.data_);
465465
}
466466

467+
protected:
468+
/**
469+
* Tells whether resizing is allowed or not for this instance of Array.
470+
*
471+
* Views cannot be resized since the data is not owned by the Array which
472+
* stores a view. It is also unclear whether custom deleter types should be
473+
* allowed to resize as they could be a user-created view-type, therefore
474+
* only proper Array which use the `default_deleter` can be resized for now.
475+
*
476+
* @return whether this Array can be resized or not.
477+
*/
478+
bool resize_is_allowed()
479+
{
480+
return data_.get_deleter().target_type() == typeid(default_deleter);
481+
}
482+
483+
467484
private:
468485
using data_manager =
469486
std::unique_ptr<value_type[], std::function<void(value_type[])>>;

0 commit comments

Comments
 (0)