From a7ce56ac18e8e51c8fea3860abe0185b629986af Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 25 Jan 2023 20:38:20 -0800 Subject: [PATCH] add shared_array::thaw() --- src/pvxs/sharedArray.h | 40 +++++++++++++++++++++++++++ test/testshared.cpp | 63 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/src/pvxs/sharedArray.h b/src/pvxs/sharedArray.h index 996bdd8..c9f8a9c 100644 --- a/src/pvxs/sharedArray.h +++ b/src/pvxs/sharedArray.h @@ -415,6 +415,30 @@ public: return ret; } + /** Return non-const (maybe) copy. consuming this + * @post empty()==true + * @since UNRELEASED + * + * If unique(), transforms this reference into the returned const reference. + * If not unique(), returns a copy and clears this reference. + * In either case, the returned reference will be unique(). + */ + shared_array::type> + thaw() { + if(this->unique()) { // only reference, avoid copy + shared_array::type> ret(this->_data, (typename std::remove_const::type*)this->_data.get(), this->_count); + + this->clear(); + return ret; + + } else { // other references, copy + shared_array::type> ret(this->_data.get(), + this->_data.get() + this->_count); + this->clear(); + return ret; + } + } + #if _DOXYGEN_ /** Cast to/from void, preserving const-ness. * @@ -617,6 +641,22 @@ public: return ret; } + shared_array::type> + thaw() { + if(this->unique()) { // only reference, avoid copy + shared_array::type> ret(this->_data, (typename std::remove_const::type*)this->_data.get(), this->_count, this->_type); + + this->clear(); + return ret; + + } else { // other references, copy + auto copy(allocArray(this->_type, this->_count)); + detail::convertArr(this->_type, copy._data.get(), this->_type, this->_data.get(), this->_count); + this->clear(); + return copy.template castTo::type>(); + } + } + // static_cast() to non-void, preserving const-ness template::value && (std::is_const::value == std::is_const::value), int>::type =0> shared_array diff --git a/test/testshared.cpp b/test/testshared.cpp index 4ca7644..7127425 100644 --- a/test/testshared.cpp +++ b/test/testshared.cpp @@ -157,6 +157,65 @@ void testFreezeError() })<<"Attempt to freeze() non-unique"; } +void testThaw() +{ + testDiag("%s", __func__); + + shared_array X({2, 5}), Y(X), Z({4, 5}); + auto saveX = X.data(); + auto saveZ = Z.data(); + + auto A(X.thaw()); // copies + auto B(Y.thaw()); // casts + auto C(Z.thaw()); // casts + testOk1(A.unique()); + testOk1(B.unique()); + testOk1(C.unique()); + testEq(A.size(), 2u); + testEq(B.size(), 2u); + testEq(C.size(), 2u); + testEq(X.size(), 0u); + testEq(Y.size(), 0u); + testEq(Z.size(), 0u); + testNotEq(A.data(), saveX); + testEq (B.data(), saveX); + testEq (C.data(), saveZ); + testEq(A[0], 2u); + testEq(B[0], 2u); + testEq(C[0], 4u); +} + +void testFreezeThawVoid() +{ + testDiag("%s", __func__); + + shared_array A(2, 5); + auto saveA = A.data(); + auto vA(A.castTo()); + A.clear(); + auto cvB(vA.freeze()); + testEq(vA.size(), 0u); + testEq(cvB.size(), 2u); + testEq(cvB.original_type(), ArrayType::UInt32); + testTrue(cvB.unique()); + + auto cvC(cvB); + auto vB(cvB.thaw()); // copy + testTrue(cvC.unique()); + auto vC(cvC.thaw()); // cast + testEq(cvB.size(), 0u); + testEq(cvC.size(), 0u); + testEq(vB.size(), 2u); + testEq(vC.size(), 2u); + testNotEq(vB.data(), saveA); + testEq (vC.data(), saveA); + + auto B(vB.castTo()); + auto C(vC.castTo()); + testEq(B[0], 5u); + testEq(C[0], 5u); +} + void testComplex() { testDiag("%s", __func__); @@ -297,7 +356,7 @@ void testConvert() MAIN(testshared) { - testPlan(127); + testPlan(155); testSetup(); testEmpty(); testEmpty(); @@ -311,6 +370,8 @@ MAIN(testshared) testVoidAssemble(); testFreeze(); testFreezeError(); + testThaw(); + testFreezeThawVoid(); testComplex(); testValue(); testCast();