rtl::Reference Add move construction/assignment
Add move constructor and appropriately overloaded assignment operator to rtl::Reference, and add basic unit tests for the reference counting of rtl::Reference. Change-Id: Ia7ff5d786bdf3b17709cec06608c91e22379746c Reviewed-on: https://gerrit.libreoffice.org/19762 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
This commit is contained in:
committed by
Stephan Bergmann
parent
c460ddb983
commit
f15d11a9f8
@@ -72,6 +72,15 @@ public:
|
||||
m_pBody->acquire();
|
||||
}
|
||||
|
||||
#ifdef LIBO_INTERNAL_ONLY
|
||||
/** Move constructor...
|
||||
*/
|
||||
inline Reference (Reference<reference_type> && handle)
|
||||
: m_pBody (handle.m_pBody)
|
||||
{
|
||||
handle.m_pBody = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Destructor...
|
||||
*/
|
||||
@@ -106,6 +115,24 @@ public:
|
||||
return set( handle.m_pBody );
|
||||
}
|
||||
|
||||
#ifdef LIBO_INTERNAL_ONLY
|
||||
/** Assignment.
|
||||
* Unbinds this instance from its body (if bound),
|
||||
* bind it to the body represented by the handle, and
|
||||
* set the body represented by the handle to nullptr.
|
||||
*/
|
||||
inline Reference<reference_type> &
|
||||
SAL_CALL operator= (Reference<reference_type> && handle)
|
||||
{
|
||||
// self-movement guts ourself
|
||||
if (m_pBody)
|
||||
m_pBody->release();
|
||||
m_pBody = handle.m_pBody;
|
||||
handle.m_pBody = nullptr;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Assignment...
|
||||
*/
|
||||
inline Reference<reference_type> &
|
||||
|
22
sal/CppunitTest_sal_rtl_ref.mk
Normal file
22
sal/CppunitTest_sal_rtl_ref.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
|
||||
#
|
||||
#
|
||||
# This file is part of the LibreOffice project.
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#
|
||||
|
||||
$(eval $(call gb_CppunitTest_CppunitTest,sal_rtl_ref))
|
||||
|
||||
$(eval $(call gb_CppunitTest_add_exception_objects,sal_rtl_ref,\
|
||||
sal/qa/rtl/ref/rtl_ref \
|
||||
))
|
||||
|
||||
$(eval $(call gb_CppunitTest_use_libraries,sal_rtl_ref,\
|
||||
sal \
|
||||
$(gb_UWINAPI) \
|
||||
))
|
||||
|
||||
# vim: set noet sw=4 ts=4:
|
@@ -54,6 +54,7 @@ $(eval $(call gb_Module_add_check_targets,sal,\
|
||||
CppunitTest_sal_rtl_oustring \
|
||||
CppunitTest_sal_rtl_oustringbuffer \
|
||||
CppunitTest_sal_rtl_process \
|
||||
CppunitTest_sal_rtl_ref \
|
||||
CppunitTest_sal_rtl_strings \
|
||||
CppunitTest_sal_rtl_textenc \
|
||||
CppunitTest_sal_rtl_uri \
|
||||
|
112
sal/qa/rtl/ref/rtl_ref.cxx
Normal file
112
sal/qa/rtl/ref/rtl_ref.cxx
Normal file
@@ -0,0 +1,112 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This file is part of the LibreOffice project.
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <rtl/ref.hxx>
|
||||
#include <sal/types.h>
|
||||
#include <cppunit/TestFixture.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
#include <cppunit/plugin/TestPlugIn.h>
|
||||
|
||||
namespace rtl_ref
|
||||
{
|
||||
|
||||
class MoveTestClass
|
||||
{
|
||||
private:
|
||||
bool m_bIncFlag;
|
||||
long m_nRef;
|
||||
public:
|
||||
MoveTestClass(): m_bIncFlag(false), m_nRef(0) { }
|
||||
|
||||
// There should never be more than two references to this class as it
|
||||
// is used as a test class for move functions. One reference being the
|
||||
// original reference and the second being the test reference
|
||||
void acquire()
|
||||
{
|
||||
if(m_bIncFlag)
|
||||
{
|
||||
++m_nRef;
|
||||
m_bIncFlag = false;
|
||||
}
|
||||
else
|
||||
CPPUNIT_FAIL("RC was incremented when in should not have been");
|
||||
}
|
||||
|
||||
void release() { --m_nRef; }
|
||||
|
||||
long use_count() { return m_nRef; }
|
||||
|
||||
void set_inc_flag() { m_bIncFlag = true; }
|
||||
};
|
||||
|
||||
rtl::Reference< MoveTestClass > get_reference( MoveTestClass* pcTestClass )
|
||||
{
|
||||
// constructor will increment the reference count
|
||||
pcTestClass->set_inc_flag();
|
||||
rtl::Reference< MoveTestClass > tmp(pcTestClass);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
class TestReferenceRefCounting : public CppUnit::TestFixture
|
||||
{
|
||||
void testMove()
|
||||
{
|
||||
MoveTestClass cTestClass;
|
||||
|
||||
// constructor will increment the reference count
|
||||
cTestClass.set_inc_flag();
|
||||
rtl::Reference< MoveTestClass > test1( &cTestClass );
|
||||
|
||||
// move should not increment the reference count
|
||||
rtl::Reference< MoveTestClass > test2( std::move(test1) );
|
||||
CPPUNIT_ASSERT_MESSAGE("test2.use_count() == 1",
|
||||
test2->use_count() == 1);
|
||||
|
||||
// test1 now contains a null pointer
|
||||
CPPUNIT_ASSERT_MESSAGE("!test1.is()",
|
||||
!test1.is());
|
||||
|
||||
// function return should move the reference
|
||||
test2 = get_reference( &cTestClass );
|
||||
CPPUNIT_ASSERT_MESSAGE("test2.use_count() == 1",
|
||||
test2->use_count() == 1);
|
||||
|
||||
// normal copy
|
||||
test2->set_inc_flag();
|
||||
test1 = test2;
|
||||
CPPUNIT_ASSERT_MESSAGE("test2.use_count() == 2",
|
||||
test2->use_count() == 2);
|
||||
|
||||
// use count should decrement
|
||||
test2 = rtl::Reference< MoveTestClass >(nullptr);
|
||||
CPPUNIT_ASSERT_MESSAGE("test1.use_count() == 1",
|
||||
test1->use_count() == 1);
|
||||
|
||||
// move of a null pointer should not cause an error
|
||||
test1 = std::move(test2);
|
||||
|
||||
CPPUNIT_ASSERT_MESSAGE("!test1.is()",
|
||||
!test1.is());
|
||||
CPPUNIT_ASSERT_MESSAGE("!test2.is()",
|
||||
!test2.is());
|
||||
|
||||
CPPUNIT_ASSERT_MESSAGE("cTestClass.use_count() == 0",
|
||||
cTestClass.use_count() == 0);
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_SUITE(TestReferenceRefCounting);
|
||||
CPPUNIT_TEST(testMove);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
};
|
||||
|
||||
} // namespace rtl_ref
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(rtl_ref::TestReferenceRefCounting);
|
||||
CPPUNIT_PLUGIN_IMPLEMENT();
|
||||
|
||||
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|
Reference in New Issue
Block a user