summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2015-08-28 16:34:56 +0200
committerMurray Cumming <murrayc@murrayc.com>2015-09-15 09:08:05 +0200
commitbd40d0acec53de33ce6257366613c6e68e40ca57 (patch)
tree2a28c597070b25ec5cd74dc68adcfb9940b32f8c
parentdf4aff9ee1cdb698f1657c96485c84620dfe53e6 (diff)
downloadglibmm-bd40d0acec53de33ce6257366613c6e68e40ca57.tar.gz
Add Glib::WeakRef<>
* glib/glibmm/filelist.am: Add weakref.h. * glib/glibmm/weakref.h: New file. * glib/glibmm.h: Add weakref.h. (Not yet. I'll do it before I push weakref.h.) * tests/Makefile.am: Add test case glibmm_weakref. * tests/glibmm_weakref/main.cc: New test case. Bug #583399. Thanks to worknesday, who attached a first version of WeakRef to the bug report. Bug #583399
-rw-r--r--glib/glibmm/filelist.am1
-rw-r--r--glib/glibmm/weakref.h447
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/glibmm_weakref/main.cc174
4 files changed, 625 insertions, 0 deletions
diff --git a/glib/glibmm/filelist.am b/glib/glibmm/filelist.am
index 4de7bad6..352a1321 100644
--- a/glib/glibmm/filelist.am
+++ b/glib/glibmm/filelist.am
@@ -81,6 +81,7 @@ glibmm_files_extra_h = \
value.h \
value_custom.h \
vectorutils.h \
+ weakref.h \
wrap.h \
wrap_init.h
diff --git a/glib/glibmm/weakref.h b/glib/glibmm/weakref.h
new file mode 100644
index 00000000..cfdf4937
--- /dev/null
+++ b/glib/glibmm/weakref.h
@@ -0,0 +1,447 @@
+#ifndef _GLIBMM_WEAKREF_H
+#define _GLIBMM_WEAKREF_H
+
+/* Copyright (C) 2015 The glibmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glib-object.h>
+#include <glibmm/refptr.h>
+#include <glibmm/objectbase.h>
+#include <type_traits> // std::is_base_of<>
+#include <utility> // std::swap<>, std::forward<>
+
+namespace Glib
+{
+
+/** WeakRef<> is a weak reference smartpointer.
+ *
+ * WeakRef can store a pointer to any class that is derived from Glib::ObjectBase.
+ *
+ * Unlike a RefPtr, a WeakRef does not contribute to the reference counting of
+ * the underlying object.
+ *
+ * @newin{2,46}
+ */
+template <typename T_CppObject>
+class WeakRef
+{
+ static_assert(std::is_base_of<Glib::ObjectBase,T_CppObject>::value,
+ "Glib::WeakRef can be used only for classes derived from Glib::ObjectBase.");
+
+public:
+ /** Default constructor.
+ *
+ * Create an empty weak reference.
+ */
+ inline WeakRef();
+
+ /// Copy constructor.
+ inline WeakRef(const WeakRef& src);
+
+ /// Move constructor.
+ inline WeakRef(WeakRef&& src);
+
+ /// Copy constructor from different, but castable type.
+ template <typename T_CastFrom>
+ inline WeakRef(const WeakRef<T_CastFrom>& src);
+
+ /// Move constructor from different, but castable type.
+ template <typename T_CastFrom>
+ inline WeakRef(WeakRef<T_CastFrom>&& src);
+
+ /** Constructor from a RefPtr of the same or a castable type.
+ *
+ * Create a weak reference from a RefPtr of the same or a castable type.
+ * If the RefPtr references nothing, an empty weak reference will be constructed.
+ */
+ template <typename T_CastFrom>
+ inline WeakRef(const RefPtr<T_CastFrom>& src);
+
+ /// Destructor.
+ inline ~WeakRef();
+
+ /// Swap the contents of two WeakRef<>.
+ inline void swap(WeakRef& other);
+
+ /// Copy assignment operator.
+ inline WeakRef& operator=(const WeakRef& src);
+
+ /// Move assignment operator.
+ inline WeakRef& operator=(WeakRef&& src);
+
+ /// Copy assignment from different, but castable type.
+ template <typename T_CastFrom>
+ inline WeakRef& operator=(const WeakRef<T_CastFrom>& src);
+
+ /// Move assignment from different, but castable type.
+ template <typename T_CastFrom>
+ inline WeakRef& operator=(WeakRef<T_CastFrom>&& src);
+
+ /// Assignment from a RefPtr of the same or a castable type.
+ template <typename T_CastFrom>
+ inline WeakRef& operator=(const RefPtr<T_CastFrom>& src);
+
+ /** Test whether the WeakRef<> points to any underlying instance.
+ *
+ * Mimics usage of ordinary pointers:
+ * @code
+ * if (ptr)
+ * do_something();
+ * @endcode
+ *
+ * In a multi-threaded program a <tt>true</tt> return value can become
+ * obsolete at any time, even before the caller has a chance to test it,
+ * because the underlying instance may lose its last reference in another
+ * thread. Use get() if this is not acceptable.
+ */
+ inline explicit operator bool() const;
+
+ /** Create a strong reference to the underlying object.
+ *
+ * This is a thread-safe way to acquire a strong reference to the underlying
+ * object. If the WeakRef is empty, the returned RefPtr will reference nothing.
+ */
+ inline RefPtr<T_CppObject> get() const;
+
+ /// Make this WeakRef empty.
+ inline void reset();
+
+ /** Dynamic cast to derived class.
+ *
+ * The WeakRef can't be cast with the usual notation so instead you can use
+ * @code
+ * ptr_derived = Glib::WeakRef<Derived>::cast_dynamic(ptr_base);
+ * @endcode
+ */
+ template <typename T_CastFrom>
+ static inline WeakRef cast_dynamic(const WeakRef<T_CastFrom>& src);
+
+ /** Static cast to derived class.
+ *
+ * The WeakRef can't be cast with the usual notation so instead you can use
+ * @code
+ * ptr_derived = Glib::WeakRef<Derived>::cast_static(ptr_base);
+ * @endcode
+ */
+ template <typename T_CastFrom>
+ static inline WeakRef cast_static(const WeakRef<T_CastFrom>& src);
+
+ /** Cast to non-const.
+ *
+ * The WeakRef can't be cast with the usual notation so instead you can use
+ * @code
+ * ptr_nonconst = Glib::WeakRef<NonConstType>::cast_const(ptr_const);
+ * @endcode
+ */
+ template <typename T_CastFrom>
+ static inline WeakRef cast_const(const WeakRef<T_CastFrom>& src);
+
+private:
+ // Let all instantiations of WeakRef access private data.
+ template <typename T_CastFrom>
+ friend class WeakRef;
+
+ // If pCppObject != nullptr && gobject == nullptr,
+ // then the caller holds a strong reference.
+ inline void set(T_CppObject* pCppObject, GWeakRef* gobject);
+
+ // WeakRef owns *gobject_, but it does not own *pCppObject_.
+ // Invariant: (!pCppObject_ || gobject_),
+ // i.e. if pCppObject_ != nullptr then also gobject_ != nullptr.
+ T_CppObject* pCppObject_;
+ GWeakRef* gobject_;
+
+ // Some methods would be simpler if gobject_ were a GWeakRef instead of
+ // a GWeakRef*, but then the move constructor and the move assignment
+ // operation would not be efficient.
+
+}; // end class WeakRef
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef()
+:
+pCppObject_(nullptr), gobject_(nullptr)
+{
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef(const WeakRef& src)
+:
+pCppObject_(src.pCppObject_), gobject_(nullptr)
+{
+ if (pCppObject_)
+ {
+ // We must own a strong reference to the underlying GObject while
+ // calling g_weak_ref_init().
+ gpointer ptr = g_weak_ref_get(src.gobject_);
+ if (ptr)
+ {
+ gobject_ = new GWeakRef;
+ g_weak_ref_init(gobject_, pCppObject_->gobj());
+ g_object_unref(ptr);
+ }
+ else
+ pCppObject_ = nullptr;
+ }
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::WeakRef(WeakRef&& src)
+:
+pCppObject_(src.pCppObject_), gobject_(src.gobject_)
+{
+ src.pCppObject_ = nullptr;
+ src.gobject_ = nullptr;
+}
+
+// The templated ctor allows copy construction from any object that's
+// castable. Thus, it does downcasts:
+// base_ref = derived_ref
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(const WeakRef<T_CastFrom>& src)
+:
+pCppObject_(src.pCppObject_), gobject_(nullptr)
+{
+ if (pCppObject_)
+ {
+ // We must own a strong reference to the underlying GObject while
+ // calling g_weak_ref_init().
+ gpointer ptr = g_weak_ref_get(src.gobject_);
+ if (ptr)
+ {
+ gobject_ = new GWeakRef;
+ g_weak_ref_init(gobject_, pCppObject_->gobj());
+ g_object_unref(ptr);
+ }
+ else
+ pCppObject_ = nullptr;
+ }
+}
+
+// The templated ctor allows move construction from any object that's
+// castable. Thus, it does downcasts:
+// base_ref = std::move(derived_ref)
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(WeakRef<T_CastFrom>&& src)
+:
+pCppObject_(src.pCppObject_), gobject_(src.gobject_)
+{
+ src.pCppObject_ = nullptr;
+ src.gobject_ = nullptr;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>::WeakRef(const RefPtr<T_CastFrom>& src)
+:
+pCppObject_(src.operator->()), gobject_(nullptr)
+{
+ if (pCppObject_)
+ {
+ gobject_ = new GWeakRef;
+ g_weak_ref_init(gobject_, pCppObject_->gobj());
+ }
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>::~WeakRef()
+{
+ if (gobject_)
+ {
+ g_weak_ref_clear(gobject_);
+ delete gobject_;
+ }
+}
+
+template <class T_CppObject>
+void WeakRef<T_CppObject>::swap(WeakRef& other)
+{
+ std::swap(pCppObject_, other.pCppObject_);
+ std::swap(gobject_, other.gobject_);
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const WeakRef& src)
+{
+ set(src.pCppObject_, src.gobject_);
+ return *this;
+}
+
+template <typename T_CppObject>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(WeakRef&& src)
+{
+ // See RefPtr for an explanation of the swap() technique to implement
+ // copy assignment and move assignment.
+ // This technique is inefficient for copy assignment of WeakRef,
+ // because it involves copy construction + destruction, i.e. in a typical
+ // case g_weak_ref_init() + g_weak_ref_clear(), when a g_weak_ref_set()
+ // would be enough. For move assignment, the swap technique is fine.
+ WeakRef<T_CppObject> temp(std::forward<WeakRef<T_CppObject>>(src));
+ this->swap(temp);
+ return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const WeakRef<T_CastFrom>& src)
+{
+ set(src.pCppObject_, src.gobject_);
+ return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(WeakRef<T_CastFrom>&& src)
+{
+ WeakRef<T_CppObject> temp(std::forward<WeakRef<T_CastFrom>>(src));
+ this->swap(temp);
+ return *this;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject>& WeakRef<T_CppObject>::operator=(const RefPtr<T_CastFrom>& src)
+{
+ T_CppObject* pCppObject = src.operator->();
+ set(pCppObject, nullptr);
+ return *this;
+}
+
+template <class T_CppObject>
+WeakRef<T_CppObject>::operator bool() const
+{
+ if (!pCppObject_)
+ return false;
+
+ gpointer ptr = g_weak_ref_get(gobject_);
+ if (!ptr)
+ return false;
+
+ g_object_unref(ptr);
+ return true;
+}
+
+template <typename T_CppObject>
+RefPtr<T_CppObject> WeakRef<T_CppObject>::get() const
+{
+ RefPtr<T_CppObject> ret;
+
+ if (!pCppObject_)
+ return ret;
+
+ gpointer ptr = g_weak_ref_get(gobject_);
+ if (!ptr)
+ return ret;
+
+ // A RefPtr constructed from pointer expects reference to be done externally.
+ pCppObject_->reference();
+ ret = RefPtr<T_CppObject>(pCppObject_);
+
+ g_object_unref(ptr);
+
+ return ret;
+}
+
+template <typename T_CppObject>
+void WeakRef<T_CppObject>::reset()
+{
+ set(nullptr, nullptr);
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_dynamic(const WeakRef<T_CastFrom>& src)
+{
+ WeakRef<T_CppObject> ret;
+
+ if (!src.pCppObject_)
+ return ret;
+
+ gpointer ptr = g_weak_ref_get(src.gobject_);
+ if (!ptr)
+ return ret;
+
+ // Don't call dynamic_cast<>() unless we know that the referenced object
+ // still exists.
+ T_CppObject *const pCppObject = dynamic_cast<T_CppObject*>(src.pCppObject_);
+ ret.set(pCppObject, nullptr);
+ g_object_unref(ptr);
+
+ return ret;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_static(const WeakRef<T_CastFrom>& src)
+{
+ T_CppObject *const pCppObject = static_cast<T_CppObject*>(src.pCppObject_);
+
+ WeakRef<T_CppObject> ret;
+ ret.set(pCppObject, src.gobject_);
+ return ret;
+}
+
+template <typename T_CppObject> template <typename T_CastFrom>
+WeakRef<T_CppObject> WeakRef<T_CppObject>::cast_const(const WeakRef<T_CastFrom>& src)
+{
+ T_CppObject *const pCppObject = const_cast<T_CppObject*>(src.pCppObject_);
+
+ WeakRef<T_CppObject> ret;
+ ret.set(pCppObject, src.gobject_);
+ return ret;
+}
+
+template <typename T_CppObject>
+void WeakRef<T_CppObject>::set(T_CppObject* pCppObject, GWeakRef* gobject)
+{
+ // We must own a strong reference to the underlying GObject while
+ // calling g_weak_ref_init() or g_weak_ref_set().
+ // If pCppObject != nullptr && gobject == nullptr,
+ // then the caller holds a strong reference.
+
+ // An aim with this moderately complicated method is to keep the same
+ // GWeakRef, calling g_weak_ref_set() when possible, instead of using swap(),
+ // which implies creating a new WeakRef, swapping with *this, and deleting
+ // the new WeakRef.
+
+ gpointer ptr = nullptr;
+ if (pCppObject && gobject)
+ ptr = g_weak_ref_get(gobject);
+
+ pCppObject_ = (ptr || !gobject) ? pCppObject : nullptr;
+ if (pCppObject_ && !gobject_)
+ {
+ gobject_ = new GWeakRef;
+ g_weak_ref_init(gobject_, pCppObject_->gobj());
+ }
+ else if (gobject_)
+ g_weak_ref_set(gobject_, pCppObject_ ? pCppObject_->gobj() : nullptr);
+
+ if (ptr)
+ g_object_unref(ptr);
+}
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+/** Swap the contents of two WeakRef<>.
+ * @relates Glib::WeakRef
+ */
+template <class T_CppObject> inline
+void swap(WeakRef<T_CppObject>& lhs, WeakRef<T_CppObject>& rhs)
+{
+ lhs.swap(rhs);
+}
+
+} // namespace Glib
+
+#endif // _GLIBMM_WEAKREF_H
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e01f4182..b2dddc32 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -46,6 +46,7 @@ check_PROGRAMS = \
glibmm_null_containerhandle/test \
glibmm_refptr/test \
glibmm_refptr_sigc_bind/test \
+ glibmm_weakref/test \
glibmm_bytearray/test
TESTS = $(check_PROGRAMS)
@@ -110,4 +111,6 @@ glibmm_null_containerhandle_test_SOURCES = glibmm_null_containerhandle/main.cc
glibmm_null_containerhandle_test_LDADD = $(giomm_ldadd)
glibmm_refptr_test_SOURCES = glibmm_refptr/main.cc
glibmm_refptr_sigc_bind_test_SOURCES = glibmm_refptr_sigc_bind/main.cc
+glibmm_weakref_test_SOURCES = glibmm_weakref/main.cc
+glibmm_weakref_test_LDADD = $(giomm_ldadd)
glibmm_bytearray_test_SOURCES = glibmm_bytearray/main.cc
diff --git a/tests/glibmm_weakref/main.cc b/tests/glibmm_weakref/main.cc
new file mode 100644
index 00000000..715ca1d7
--- /dev/null
+++ b/tests/glibmm_weakref/main.cc
@@ -0,0 +1,174 @@
+/* Copyright (C) 2015 The glibmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <glibmm.h>
+#include <giomm.h> //There is no class derived from Glib::Object in glibmm
+#include <iostream>
+#include <cstring>
+#include <utility> // std::move
+#include <glibmm/weakref.h> //!! Until it's included in glibmm.h
+
+int main(int, char**)
+{
+ Glib::init();
+ bool success = true;
+
+ // A Glib::WeakRef cannot be created from a Glib::RefPtr<Glib::Bytes>,
+ // because Glib::Bytes is not derived from Glib::ObjectBase.
+ //const int bdata = 1234;
+ //Glib::RefPtr<Glib::Bytes> bytes = Glib::Bytes::create(&bdata, sizeof bdata);
+ //Glib::WeakRef<Glib::Bytes> weakbytes = bytes; // does not compile
+
+ // Gio::MemoryInputStream
+ Glib::RefPtr<Gio::MemoryInputStream> memstream1 = Gio::MemoryInputStream::create();
+ const char data[] = "Some arbitrary data";
+ memstream1->add_data(data, sizeof data, Gio::MemoryInputStream::SlotDestroyData());
+
+ // Downcast copy, followed by upcast.
+ Glib::WeakRef<Gio::MemoryInputStream> weakmemstream1 = memstream1;
+ Glib::WeakRef<Gio::InputStream> weakstream1 = weakmemstream1;
+ Glib::WeakRef<Gio::MemoryInputStream> weakmemstream2 =
+ Glib::WeakRef<Gio::MemoryInputStream>::cast_dynamic(weakstream1);
+ Glib::RefPtr<Gio::MemoryInputStream> memstream2 = weakmemstream2.get();
+ if (memstream2)
+ {
+ char buffer[200];
+ gsize bytes_read = 0;
+ try
+ {
+ memstream2->read_all(buffer, sizeof buffer, bytes_read);
+ std::cout << buffer << std::endl;
+ success &= std::strcmp(buffer, data) == 0;
+ }
+ catch (const Glib::Error& ex)
+ {
+ std::cout << "Error reading from memory stream: " << ex.what() << std::endl;
+ success = false;
+ }
+ }
+ else
+ {
+ std::cout << "!memstream2" << std::endl;
+ success = false;
+ }
+
+ // Move construction.
+ Glib::WeakRef<Gio::MemoryInputStream> weakmemstream3(std::move(weakmemstream1));
+ if (weakmemstream1.get() || !weakmemstream3.get())
+ {
+ success = false;
+ if (weakmemstream1.get())
+ std::cout << "weakmemstream1 || !weakmemstream3: weakmemstream1" << std::endl;
+ if (!weakmemstream3.get())
+ std::cout << "weakmemstream1 || !weakmemstream3: !weakmemstream3" << std::endl;
+ }
+ else
+ {
+ // Move assignment.
+ weakmemstream2 = std::move(weakmemstream3);
+ if (!weakmemstream2 || weakmemstream3)
+ {
+ success = false;
+ if (!weakmemstream2.get())
+ std::cout << "!weakmemstream2 || weakmemstream3: !weakmemstream2" << std::endl;
+ if (weakmemstream3.get())
+ std::cout << "!weakmemstream2 || weakmemstream3: weakmemstream3" << std::endl;
+ }
+ else
+ {
+ // Downcast move, followed by upcast.
+ weakstream1 = std::move(weakmemstream2);
+ weakmemstream1 = Glib::WeakRef<Gio::MemoryInputStream>::cast_dynamic(weakstream1);
+ if (weakmemstream2 || !weakmemstream1)
+ {
+ success = false;
+ if (weakmemstream2)
+ std::cout << "weakmemstream2 || !weakmemstream1: weakmemstream2" << std::endl;
+ if (!weakmemstream1)
+ std::cout << "weakmemstream2 || !weakmemstream1: !weakmemstream1" << std::endl;
+ }
+ }
+ }
+
+ // Gio::SimpleAction
+ Glib::RefPtr<Gio::SimpleAction> action1 = Gio::SimpleAction::create("Action1");
+
+ Glib::ustring name = action1->get_name();
+ std::cout << "The name is '" << name << "'." << std::endl;
+ success &= name == "Action1";
+
+ Glib::WeakRef<Gio::SimpleAction> weakaction1 = action1;
+ Glib::WeakRef<Gio::SimpleAction> weakaction2 = weakaction1;
+
+ // A second RefPtr
+ Glib::RefPtr<Gio::SimpleAction> action2 = weakaction1.get();
+ if (action2)
+ {
+ name = action2->get_name();
+ std::cout << "The name is '" << name << "'." << std::endl;
+ success &= name == "Action1";
+ }
+ else
+ {
+ std::cout << "!action2" << std::endl;
+ success = false;
+ }
+
+ weakaction1.reset();
+ if (weakaction1.get())
+ {
+ std::cout << "weakaction1" << std::endl;
+ success = false;
+ }
+
+ action2 = weakaction2.get();
+ if (action2)
+ {
+ name = action2->get_name();
+ std::cout << "The name is '" << name << "'." << std::endl;
+ success &= name == "Action1";
+ }
+ else
+ {
+ std::cout << "!action2" << std::endl;
+ success = false;
+ }
+
+ // Reset one of the RefPtrs. One remains.
+ action1.reset();
+ action2 = weakaction2.get();
+ if (action2)
+ {
+ name = action2->get_name();
+ std::cout << "The name is '" << name << "'." << std::endl;
+ success &= name == "Action1";
+ }
+ else
+ {
+ std::cout << "!action2" << std::endl;
+ success = false;
+ }
+
+ // Reset the other RefPtr as well.
+ action2.reset();
+ if (weakaction2.get())
+ {
+ std::cout << "weakaction2" << std::endl;
+ success = false;
+ }
+
+ return success ? EXIT_SUCCESS : EXIT_FAILURE;
+}