[Libreoffice-commits] core.git: include/rtl sal/CppunitTest_sal_rtl_ref.mk sal/Module_sal.mk sal/qa

Daniel Robertson danlrobertson89 at gmail.com
Fri Nov 6 07:19:57 PST 2015


 include/rtl/ref.hxx            |   27 +++++++++
 sal/CppunitTest_sal_rtl_ref.mk |   22 ++++++++
 sal/Module_sal.mk              |    1 
 sal/qa/rtl/ref/rtl_ref.cxx     |  112 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 162 insertions(+)

New commits:
commit f15d11a9f8d6c783fd8c937256fa3372f8e4fe01
Author: Daniel Robertson <danlrobertson89 at gmail.com>
Date:   Tue Nov 3 09:47:36 2015 -0500

    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 at libreoffice.org>
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>

diff --git a/include/rtl/ref.hxx b/include/rtl/ref.hxx
index 097584b..82dda83 100644
--- a/include/rtl/ref.hxx
+++ b/include/rtl/ref.hxx
@@ -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> &
diff --git a/sal/CppunitTest_sal_rtl_ref.mk b/sal/CppunitTest_sal_rtl_ref.mk
new file mode 100644
index 0000000..f42bf92
--- /dev/null
+++ b/sal/CppunitTest_sal_rtl_ref.mk
@@ -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:
diff --git a/sal/Module_sal.mk b/sal/Module_sal.mk
index 192da93..0b02103 100644
--- a/sal/Module_sal.mk
+++ b/sal/Module_sal.mk
@@ -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 \
diff --git a/sal/qa/rtl/ref/rtl_ref.cxx b/sal/qa/rtl/ref/rtl_ref.cxx
new file mode 100644
index 0000000..66d54e6
--- /dev/null
+++ b/sal/qa/rtl/ref/rtl_ref.cxx
@@ -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: */


More information about the Libreoffice-commits mailing list