You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2017/01/03 22:02:46 UTC
[14/30] qpid-proton git commit: PROTON-1372: [C++ binding] Pimpl
event_loop - To make sure that we maintain C++03/C++11 cross compatibility.
PROTON-1372: [C++ binding] Pimpl event_loop
- To make sure that we maintain C++03/C++11 cross compatibility.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/f89d24d8
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/f89d24d8
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/f89d24d8
Branch: refs/heads/go1
Commit: f89d24d855fe684d97ef640235a04afdbb08c885
Parents: bea6173
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Dec 8 03:25:57 2016 -0500
Committer: Andrew Stitcher <as...@apache.org>
Committed: Thu Dec 8 03:49:58 2016 -0500
----------------------------------------------------------------------
.../bindings/cpp/include/proton/event_loop.hpp | 38 ++++++++++++++-----
.../cpp/include/proton/internal/config.hpp | 4 ++
.../cpp/include/proton/internal/object.hpp | 2 +-
.../cpp/include/proton/io/connection_driver.hpp | 5 ++-
.../bindings/cpp/include/proton/thread_safe.hpp | 23 ++++++------
proton-c/bindings/cpp/src/container_impl.cpp | 27 ++++++--------
proton-c/bindings/cpp/src/event_loop.cpp | 28 +++++++++++---
proton-c/bindings/cpp/src/include/contexts.hpp | 2 +-
.../cpp/src/include/event_loop_impl.hpp | 39 ++++++++++++++++++++
.../bindings/cpp/src/io/connection_driver.cpp | 12 +++++-
proton-c/bindings/cpp/src/thread_safe_test.cpp | 4 +-
11 files changed, 135 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/include/proton/event_loop.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/event_loop.hpp b/proton-c/bindings/cpp/include/proton/event_loop.hpp
index d43ba4f..f49d211 100644
--- a/proton-c/bindings/cpp/include/proton/event_loop.hpp
+++ b/proton-c/bindings/cpp/include/proton/event_loop.hpp
@@ -25,6 +25,7 @@
#include "./fwd.hpp"
#include "./internal/config.hpp"
#include "./internal/export.hpp"
+#include "./internal/pn_unique_ptr.hpp"
#include <functional>
@@ -41,31 +42,48 @@ namespace proton {
/// and have it executed in the same sequence.
///
class PN_CPP_CLASS_EXTERN event_loop {
+ /// @cond internal
+ class impl;
+ event_loop& operator=(impl* i);
+ /// @endcond
+
public:
- virtual ~event_loop() {}
+ /// Create event_loop
+ PN_CPP_EXTERN event_loop();
+
+ PN_CPP_EXTERN ~event_loop();
+
+#if PN_CPP_HAS_EXPLICIT_CONVERSIONS
+ /// When using C++11 (or later) you can use event_loop in a bool context
+ /// to indicate if there is an event loop set.
+ PN_CPP_EXTERN explicit operator bool() const { return bool(impl_); }
+#endif
+
+ /// No event loop set.
+ PN_CPP_EXTERN bool operator !() const { return !impl_; }
/// Arrange to have f() called in the event_loop's sequence: possibly
/// deferred, possibly in another thread.
///
/// @return true if f() has or will be called, false if the event_loop is ended
/// and f() cannot be injected.
- virtual bool inject(void_function0& f) = 0;
+ PN_CPP_EXTERN bool inject(void_function0& f);
#if PN_CPP_HAS_STD_FUNCTION
/// @copydoc inject(void_function0&)
- virtual bool inject(std::function<void()> f) = 0;
+ PN_CPP_EXTERN bool inject(std::function<void()> f);
#endif
- protected:
- event_loop() {}
-
private:
- PN_CPP_EXTERN static event_loop* get(pn_connection_t*);
- PN_CPP_EXTERN static event_loop* get(pn_session_t*);
- PN_CPP_EXTERN static event_loop* get(pn_link_t*);
+ PN_CPP_EXTERN static event_loop& get(pn_connection_t*);
+ PN_CPP_EXTERN static event_loop& get(pn_session_t*);
+ PN_CPP_EXTERN static event_loop& get(pn_link_t*);
+
+ internal::pn_unique_ptr<impl> impl_;
/// @cond INTERNAL
- friend class connection;
+ friend class container;
+ friend class io::connection_driver;
template <class T> friend class thread_safe;
/// @endcond
};
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/include/proton/internal/config.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/config.hpp b/proton-c/bindings/cpp/include/proton/internal/config.hpp
index 612e1e3..563a304 100644
--- a/proton-c/bindings/cpp/include/proton/internal/config.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/config.hpp
@@ -87,6 +87,10 @@
#define PN_CPP_HAS_STD_FUNCTION PN_CPP_HAS_CPP11
#endif
+#ifndef PN_CPP_HAS_STD_BIND
+#define PN_CPP_HAS_STD_BIND PN_CPP_HAS_CPP11
+#endif
+
#ifndef PN_CPP_HAS_CHRONO
#define PN_CPP_HAS_CHRONO PN_CPP_HAS_CPP11
#endif
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/include/proton/internal/object.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/internal/object.hpp b/proton-c/bindings/cpp/include/proton/internal/object.hpp
index 78a990c..d492b80 100644
--- a/proton-c/bindings/cpp/include/proton/internal/object.hpp
+++ b/proton-c/bindings/cpp/include/proton/internal/object.hpp
@@ -101,7 +101,7 @@ template <class T> class object : private comparable<object<T> > {
friend bool operator==(const object& a, const object& b) { return a.object_ == b.object_; }
friend bool operator<(const object& a, const object& b) { return a.object_ < b.object_; }
friend std::ostream& operator<<(std::ostream& o, const object& a) { o << a.object_.inspect(); return o; }
- template <class U> friend class proton::thread_safe;
+ template <class U> friend class proton::thread_safe;
};
/// Factory class used internally to make wrappers and extract proton objects
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
index d5da718..4a0efe9 100644
--- a/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
+++ b/proton-c/bindings/cpp/include/proton/io/connection_driver.hpp
@@ -111,7 +111,10 @@ PN_CPP_CLASS_EXTERN connection_driver {
/// the user pins it in memory using the proton::thread_safe<> template.
/// The event_loop is deleted when, and only when, the proton::connection is.
///
- PN_CPP_EXTERN connection_driver(proton::container&, event_loop* loop = 0);
+ PN_CPP_EXTERN connection_driver(proton::container&);
+#if PN_CPP_HAS_RVALUE_REFERENCES
+ PN_CPP_EXTERN connection_driver(proton::container&, event_loop&& loop);
+#endif
PN_CPP_EXTERN ~connection_driver();
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/include/proton/thread_safe.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/thread_safe.hpp b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
index 28aa3a6..608a1ca 100644
--- a/proton-c/bindings/cpp/include/proton/thread_safe.hpp
+++ b/proton-c/bindings/cpp/include/proton/thread_safe.hpp
@@ -43,8 +43,6 @@ template<> struct endpoint_traits<sender> {};
template<> struct endpoint_traits<receiver> {};
}
-template <class T> class returned;
-
/// **Experimental** - A thread-safe object wrapper.
///
/// The proton::object subclasses (proton::connection, proton::sender etc.) are
@@ -78,11 +76,11 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
~thread_safe() {
if (ptr()) {
- if (event_loop()) {
-#if PN_CPP_HAS_CPP11
- event_loop()->inject(std::bind(&decref, ptr()));
+ if (!!event_loop()) {
+#if PN_CPP_HAS_STD_BIND
+ event_loop().inject(std::bind(&decref, ptr()));
#else
- event_loop()->inject(*new inject_decref(ptr()));
+ event_loop().inject(*new inject_decref(ptr()));
#endif
} else {
decref(ptr());
@@ -91,7 +89,7 @@ class thread_safe : private internal::pn_ptr_base, private internal::endpoint_tr
}
/// Get the event loop for this object.
- class event_loop* event_loop() { return event_loop::get(ptr()); }
+ class event_loop& event_loop() { return event_loop::get(ptr()); }
/// Get the thread-unsafe proton object wrapped by this thread_safe<T>
T unsafe() { return T(ptr()); }
@@ -140,12 +138,13 @@ class returned : private internal::endpoint_traits<T>
/// Implicit conversion to target, usable only in a safe context.
operator T() { return ptr_->unsafe(); }
-#if PN_CPP_HAS_CPP11
+#if PN_CPP_HAS_SHARED_PTR
/// Release to a std::shared_ptr
operator std::shared_ptr<thread_safe<T> >() {
return std::shared_ptr<thread_safe<T> >(release());
}
-
+#endif
+#if PN_CPP_HAS_UNIQUE_PTR
/// Release to a std::unique_ptr
operator std::unique_ptr<thread_safe<T> >() {
return std::unique_ptr<thread_safe<T> >(release());
@@ -160,13 +159,13 @@ class returned : private internal::endpoint_traits<T>
/// Make a thread-safe wrapper for `obj`.
template <class T> returned<T> make_thread_safe(const T& obj) { return returned<T>(obj); }
-#if PN_CPP_HAS_CPP11
-
+#if PN_CPP_HAS_SHARED_PTR
/// Create a thread-safe shared_ptr to `obj`.
template <class T> std::shared_ptr<thread_safe<T> > make_shared_thread_safe(const T& obj) {
return make_thread_safe(obj);
}
-
+#endif
+#if PN_CPP_HAS_UNIQUE_PTR
/// Create a thread-safe unique_ptr to `obj`.
template <class T> std::unique_ptr<thread_safe<T> > make_unique_thread_safe(const T& obj) {
return make_thread_safe(obj);
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.cpp b/proton-c/bindings/cpp/src/container_impl.cpp
index 5f13b82..9cec831 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -38,6 +38,7 @@
#include "connector.hpp"
#include "container_impl.hpp"
#include "contexts.hpp"
+#include "event_loop_impl.hpp"
#include "messaging_adapter.hpp"
#include "msg.hpp"
#include "proton_bits.hpp"
@@ -160,24 +161,20 @@ container::impl::~impl() {
close_acceptor(i->second);
}
-namespace {
// FIXME aconway 2016-06-07: this is not thread safe. It is sufficient for using
// default_container::schedule() inside a handler but not for inject() from
// another thread.
-struct immediate_event_loop : public event_loop {
- virtual bool inject(void_function0& f) PN_CPP_OVERRIDE {
- try { f(); } catch(...) {}
- return true;
- }
+bool event_loop::impl::inject(void_function0& f) {
+ try { f(); } catch(...) {}
+ return true;
+}
-#if PN_CPP_HAS_CPP11
- virtual bool inject(std::function<void()> f) PN_CPP_OVERRIDE {
- try { f(); } catch(...) {}
- return true;
- }
-#endif
-};
+#if PN_CPP_HAS_STD_FUNCTION
+bool event_loop::impl::inject(std::function<void()> f) {
+ try { f(); } catch(...) {}
+ return true;
}
+#endif
returned<connection> container::impl::connect(const std::string &urlstr, const connection_options &user_opts) {
connection_options opts = client_connection_options(); // Defaults
@@ -195,7 +192,7 @@ returned<connection> container::impl::connect(const std::string &urlstr, const c
internal::pn_unique_ptr<connector> ctor(new connector(conn, opts, url));
connection_context& cc(connection_context::get(conn));
cc.handler.reset(ctor.release());
- cc.event_loop.reset(new immediate_event_loop);
+ cc.event_loop_ = new event_loop::impl;
pn_connection_t *pnc = unwrap(conn);
pn_connection_set_container(pnc, id_.c_str());
@@ -347,7 +344,7 @@ void container::impl::configure_server_connection(connection &c) {
pn_record_t *record = pn_connection_attachments(unwrap(c));
pn_record_set_handler(record, chandler.get());
}
- connection_context::get(c).event_loop.reset(new immediate_event_loop);
+ connection_context::get(c).event_loop_ = new event_loop::impl;
}
void container::impl::run() {
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/event_loop.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/event_loop.cpp b/proton-c/bindings/cpp/src/event_loop.cpp
index 3d373c4..ea4ee71 100644
--- a/proton-c/bindings/cpp/src/event_loop.cpp
+++ b/proton-c/bindings/cpp/src/event_loop.cpp
@@ -17,24 +17,40 @@
* under the License.
*/
+#include "proton/event_loop.hpp"
+
#include "contexts.hpp"
+#include "event_loop_impl.hpp"
#include <proton/session.h>
#include <proton/link.h>
-#include "proton/event_loop.hpp"
-
namespace proton {
-event_loop* event_loop::get(pn_connection_t* c) {
- return connection_context::get(c).event_loop.get();
+event_loop::event_loop() {}
+event_loop::~event_loop() {}
+
+event_loop& event_loop::operator=(impl* i) { impl_.reset(i); return *this; }
+
+bool event_loop::inject(void_function0& f) {
+ return impl_->inject(f);
+}
+
+#if PN_CPP_HAS_STD_FUNCTION
+bool event_loop::inject(std::function<void()> f) {
+ return impl_->inject(f);
+}
+#endif
+
+event_loop& event_loop::get(pn_connection_t* c) {
+ return connection_context::get(c).event_loop_;
}
-event_loop* event_loop::get(pn_session_t* s) {
+event_loop& event_loop::get(pn_session_t* s) {
return get(pn_session_connection(s));
}
-event_loop* event_loop::get(pn_link_t* l) {
+event_loop& event_loop::get(pn_link_t* l) {
return get(pn_link_session(l));
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/include/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/contexts.hpp b/proton-c/bindings/cpp/src/include/contexts.hpp
index 4306489..e80c434 100644
--- a/proton-c/bindings/cpp/src/include/contexts.hpp
+++ b/proton-c/bindings/cpp/src/include/contexts.hpp
@@ -93,7 +93,7 @@ class connection_context : public context {
io::link_namer* link_gen; // Link name generator.
internal::pn_unique_ptr<proton_handler> handler;
- internal::pn_unique_ptr<class event_loop> event_loop;
+ event_loop event_loop_;
static connection_context& get(pn_connection_t *c) { return ref<connection_context>(id(c)); }
static connection_context& get(const connection& c) { return ref<connection_context>(id(c)); }
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/include/event_loop_impl.hpp b/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
new file mode 100644
index 0000000..b34a981
--- /dev/null
+++ b/proton-c/bindings/cpp/src/include/event_loop_impl.hpp
@@ -0,0 +1,39 @@
+#ifndef PROTON_CPP_EVENT_LOOP_IMPL_HPP
+#define PROTON_CPP_EVENT_LOOP_IMPL_HPP
+
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include "proton/fwd.hpp"
+
+namespace proton {
+
+class event_loop::impl {
+ public:
+ bool inject(void_function0& f);
+#if PN_CPP_HAS_CPP11
+ bool inject(std::function<void()> f);
+#endif
+};
+
+}
+
+#endif // PROTON_CPP_EVENT_LOOP_IMPL_HPP
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/io/connection_driver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/io/connection_driver.cpp b/proton-c/bindings/cpp/src/io/connection_driver.cpp
index ca9f68e..148a00b 100644
--- a/proton-c/bindings/cpp/src/io/connection_driver.cpp
+++ b/proton-c/bindings/cpp/src/io/connection_driver.cpp
@@ -49,13 +49,21 @@ void connection_driver::init() {
connection_driver::connection_driver() : handler_(0), container_(0) { init(); }
-connection_driver::connection_driver(class container& cont, event_loop* loop) : handler_(0), container_(&cont) {
+connection_driver::connection_driver(class container& cont) : handler_(0), container_(&cont) {
init();
connection_context& ctx = connection_context::get(connection());
ctx.container = container_;
- ctx.event_loop.reset(loop);
}
+#if PN_CPP_HAS_RVALUE_REFERENCES
+connection_driver::connection_driver(class container& cont, event_loop&& loop) : handler_(0), container_(&cont) {
+ init();
+ connection_context& ctx = connection_context::get(connection());
+ ctx.container = container_;
+ ctx.event_loop_ = loop.impl_.get();
+}
+#endif
+
connection_driver::~connection_driver() {
pn_connection_driver_destroy(&driver_);
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/f89d24d8/proton-c/bindings/cpp/src/thread_safe_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/thread_safe_test.cpp b/proton-c/bindings/cpp/src/thread_safe_test.cpp
index 5b5d487..3a72f7f 100644
--- a/proton-c/bindings/cpp/src/thread_safe_test.cpp
+++ b/proton-c/bindings/cpp/src/thread_safe_test.cpp
@@ -50,7 +50,7 @@ void test_new() {
ASSERT_EQUAL(1, pn_refcount(c)); // Engine gone, thread_safe keeping c alive.
delete p;
-#if PN_CPP_HAS_CPP11
+#if PN_CPP_HAS_SHARED_PTR
{
std::shared_ptr<thread_safe<connection> > sp;
{
@@ -60,6 +60,8 @@ void test_new() {
}
ASSERT_EQUAL(1, pn_refcount(c)); // Engine gone, sp keeping c alive.
}
+#endif
+#if PN_CPP_HAS_UNIQUE_PTR
{
std::unique_ptr<thread_safe<connection> > up;
{
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org