summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-07-10 06:30:33 +0000
committerPatrick Ohly <patrick.ohly@intel.com>2012-07-10 06:30:33 +0000
commit663a7063e4524370a9b5819866970f71b307993c (patch)
treef04eda7563a0c39d9adf3dd71afe2b414b93d346
parent99e27d46611d5e1afd33559ed86c5a2174a17645 (diff)
boost: support boost::bind() + weak pointers
On several occasions, boost::bind() is used with a this pointer as second parameter. This is only safe as long as the functor is only called when the instance is still valid. After including BoostHelper.h it is also possible to use a weak pointer. The result is a functor which does not prevent deleting the instance and doesn't do anything when the instance is gone when called.
-rw-r--r--src/syncevo/BoostHelper.h142
-rw-r--r--src/syncevo/syncevo.am2
2 files changed, 144 insertions, 0 deletions
diff --git a/src/syncevo/BoostHelper.h b/src/syncevo/BoostHelper.h
new file mode 100644
index 00000000..0d5a4d2c
--- /dev/null
+++ b/src/syncevo/BoostHelper.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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) version 3.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/**
+ * Including this header file allows to use boost::bind() with
+ * a class member as first parameter and a boost::weak_ptr
+ * as second parameter.
+ *
+ * When the functor is invoked, it will lock the instance
+ * and only call the member if that succeeds. Otherwise it
+ * will silently return to the caller.
+ *
+ * The member function must have "void" as return value.
+ *
+ * This behavior makes sense in particular with asynchronous method
+ * calls where the result is only relevant while the caller still
+ * exists.
+ *
+ * The code is inspired by
+ * http://permalink.gmane.org/gmane.comp.lib.boost.user/70276 and was
+ * adapted to the SyncEvolution namespace and coding style. In contrast
+ * to that code, the shared_ptr is kept until the invoker gets freed.
+ * Seems a bit safer that way. Instead of duplicating the ->* operator
+ * in WeakPtrAdapter it uses the type of the member as template parameter
+ * to cover all kinds of members.
+ */
+
+#ifndef INCL_SYNCEVOLUTION_BOOST_HELPER
+# define INCL_SYNCEVOLUTION_BOOST_HELPER
+
+#include <boost/bind.hpp>
+#include <boost/smart_ptr.hpp>
+
+#include <syncevo/declarations.h>
+SE_BEGIN_CXX
+
+template <typename P, typename M>
+class WeakPtrInvoker
+{
+ public:
+ WeakPtrInvoker(const P &ptr, const M &member) :
+ m_ptr(ptr),
+ m_member(member)
+ {}
+
+ void operator()() const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)();
+ }
+ }
+
+ template <typename A1>
+ void operator()(A1 a1) const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)(a1);
+ }
+ }
+
+ template <typename A1, typename A2>
+ void operator()(A1 a1, A2 a2) const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)(a1, a2);
+ }
+ }
+
+ template <typename A1, typename A2, typename A3>
+ void operator()(A1 a1, A2 a2, A3 a3) const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)(a1, a2, a3);
+ }
+ }
+
+ template <typename A1, typename A2, typename A3, typename A4>
+ void operator()(A1 a1, A2 a2, A3 a3, A4 a4) const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)(a1, a2, a3, a4);
+ }
+ }
+
+ template <typename A1, typename A2, typename A3, typename A4, typename A5>
+ void operator()(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
+ {
+ if (m_ptr) {
+ (boost::get_pointer(m_ptr)->*m_member)(a1, a2, a3, a4, a5);
+ }
+ }
+
+ private:
+ P m_ptr;
+ M m_member;
+};
+
+template <typename T> class WeakPtrAdapter
+{
+public:
+ WeakPtrAdapter(const boost::shared_ptr<T> &ptr) :
+ m_ptr(ptr)
+ {}
+
+ template <typename M>
+ WeakPtrInvoker<boost::shared_ptr<T>, M> operator->*(M member) const
+ {
+ return WeakPtrInvoker<boost::shared_ptr<T>, M>(m_ptr, member);
+ }
+
+private:
+ boost::shared_ptr<T> m_ptr;
+};
+
+SE_END_CXX
+
+namespace boost
+{
+ template<class T>
+ SyncEvo::WeakPtrAdapter<T> get_pointer(const boost::weak_ptr<T> &ptr)
+ {
+ return SyncEvo::WeakPtrAdapter<T>(ptr.lock());
+ }
+}
+
+#endif // INCL_SYNCEVOLUTION_BOOST_HELPER
diff --git a/src/syncevo/syncevo.am b/src/syncevo/syncevo.am
index 2ecce458..7024f10b 100644
--- a/src/syncevo/syncevo.am
+++ b/src/syncevo/syncevo.am
@@ -60,6 +60,7 @@ src_syncevo_sources = \
\
src/syncevo/util.cpp \
src/syncevo/util.h \
+ src/syncevo/BoostHelper.h \
\
src/syncevo/Timespec.h \
\
@@ -152,6 +153,7 @@ src_syncevo_libsyncevolution_include_HEADERS = \
src/syncevo/SyncConfig.h \
src/syncevo/SyncSource.h \
src/syncevo/util.h \
+ src/syncevo/BoostHelper.h \
src/syncevo/SuspendFlags.h \
src/syncevo/SyncContext.h \
src/syncevo/Timespec.h \