You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2017/06/02 22:51:17 UTC

[03/20] qpid-proton git commit: PROTON-1288: c++ hide proton::message implementation details

PROTON-1288: c++ hide proton::message implementation details

Hide extra book-keeping types in extra storage allocated with the pn_message_t.


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/48a5e47a
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/48a5e47a
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/48a5e47a

Branch: refs/heads/PROTON-1488
Commit: 48a5e47a09268ddb19f925d8f66301718f42b87a
Parents: 860b322
Author: Alan Conway <ac...@redhat.com>
Authored: Wed May 17 13:52:13 2017 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed May 24 14:38:25 2017 -0400

----------------------------------------------------------------------
 .../bindings/cpp/include/proton/message.hpp     |  6 +-
 proton-c/bindings/cpp/src/message.cpp           | 74 +++++++++++++-------
 2 files changed, 52 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/48a5e47a/proton-c/bindings/cpp/include/proton/message.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/message.hpp b/proton-c/bindings/cpp/include/proton/message.hpp
index ff60c99..faf2f29 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -321,13 +321,11 @@ class message {
 
     /// @cond INTERNAL
   private:
+    struct impl;
     pn_message_t *pn_msg() const;
+    struct impl& impl() const;
 
     mutable pn_message_t *pn_msg_;
-    mutable value body_;
-    mutable property_map application_properties_;
-    mutable annotation_map message_annotations_;
-    mutable annotation_map delivery_annotations_;
 
     /// Decode the message corresponding to a delivery from a link.
     void decode(proton::delivery);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/48a5e47a/proton-c/bindings/cpp/src/message.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/message.cpp b/proton-c/bindings/cpp/src/message.cpp
index 59f8329..df7fae1 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -41,6 +41,32 @@
 
 namespace proton {
 
+struct message::impl {
+    value body_;
+    property_map application_properties_;
+    annotation_map message_annotations_;
+    annotation_map delivery_annotations_;
+
+    impl(pn_message_t *msg) {
+        body_.reset(pn_message_body(msg));
+    }
+
+    void clear() {
+        application_properties_.clear();
+        message_annotations_.clear();
+        delivery_annotations_.clear();
+    }
+
+  friend void swap(impl& x, impl& y) {
+      using std::swap;
+      swap(x.body_, y.body_);
+      swap(x.application_properties_, y.application_properties_);
+      swap(x.message_annotations_, y.message_annotations_);
+      swap(x.delivery_annotations_, y.delivery_annotations_);
+  }
+};
+
+
 message::message() : pn_msg_(0) {}
 message::message(const message &m) : pn_msg_(0) { *this = m; }
 
@@ -55,28 +81,31 @@ message& message::operator=(message&& m) {
 message::message(const value& x) : pn_msg_(0) { body() = x; }
 
 message::~message() {
-    // Workaround proton bug: Must release all refs to body before calling pn_message_free()
-    body_.reset();
-    pn_message_free(pn_msg_);
+    if (pn_msg_) {
+        impl().~impl();               // destroy in-place
+        pn_message_free(pn_msg_);
+    }
 }
 
 void swap(message& x, message& y) {
     using std::swap;
     swap(x.pn_msg_, y.pn_msg_);
-    swap(x.body_, y.body_);
-    swap(x.application_properties_, y.application_properties_);
-    swap(x.message_annotations_, y.message_annotations_);
-    swap(x.delivery_annotations_, y.delivery_annotations_);
+    swap(x.impl(), y.impl());
 }
 
 pn_message_t *message::pn_msg() const {
     if (!pn_msg_) {
-        pn_msg_ = pn_message();
-        body_.reset(pn_message_body(pn_msg_));
+        pn_msg_ = pn_message_with_extra(sizeof(struct message::impl));
+        // Construct impl in extra storage allocated with pn_msg_
+        new (pn_message_get_extra(pn_msg_)) struct message::impl(pn_msg_);
     }
     return pn_msg_;
 }
 
+struct message::impl& message::impl() const {
+    return *(struct message::impl*)pn_message_get_extra(pn_msg());
+}
+
 message& message::operator=(const message& m) {
     if (&m != this) {
         // TODO aconway 2015-08-10: more efficient pn_message_copy function
@@ -209,8 +238,8 @@ void message::inferred(bool b) { pn_message_set_inferred(pn_msg(), b); }
 
 void message::body(const value& x) { body() = x; }
 
-const value& message::body() const { pn_msg(); return body_; }
-value& message::body() { pn_msg(); return body_; }
+const value& message::body() const { return impl().body_; }
+value& message::body() { return impl().body_; }
 
 // MAP CACHING: the properties and annotations maps can either be encoded in the
 // pn_message pn_data_t structures OR decoded as C++ map members of the message
@@ -239,35 +268,35 @@ template<class M, class F> M& put_map(pn_message_t* msg, F get, M& map) {
 }
 
 message::property_map& message::properties() {
-    return get_map(pn_msg(), pn_message_properties, application_properties_);
+    return get_map(pn_msg(), pn_message_properties, impl().application_properties_);
 }
 
 const message::property_map& message::properties() const {
-    return get_map(pn_msg(), pn_message_properties, application_properties_);
+    return get_map(pn_msg(), pn_message_properties, impl().application_properties_);
 }
 
 
 message::annotation_map& message::message_annotations() {
-    return get_map(pn_msg(), pn_message_annotations, message_annotations_);
+    return get_map(pn_msg(), pn_message_annotations, impl().message_annotations_);
 }
 
 const message::annotation_map& message::message_annotations() const {
-    return get_map(pn_msg(), pn_message_annotations, message_annotations_);
+    return get_map(pn_msg(), pn_message_annotations, impl().message_annotations_);
 }
 
 
 message::annotation_map& message::delivery_annotations() {
-    return get_map(pn_msg(), pn_message_instructions, delivery_annotations_);
+    return get_map(pn_msg(), pn_message_instructions, impl().delivery_annotations_);
 }
 
 const message::annotation_map& message::delivery_annotations() const {
-    return get_map(pn_msg(), pn_message_instructions, delivery_annotations_);
+    return get_map(pn_msg(), pn_message_instructions, impl().delivery_annotations_);
 }
 
 void message::encode(std::vector<char> &s) const {
-    put_map(pn_msg(), pn_message_properties, application_properties_);
-    put_map(pn_msg(), pn_message_annotations, message_annotations_);
-    put_map(pn_msg(), pn_message_instructions, delivery_annotations_);
+    put_map(pn_msg(), pn_message_properties, impl().application_properties_);
+    put_map(pn_msg(), pn_message_annotations, impl().message_annotations_);
+    put_map(pn_msg(), pn_message_instructions, impl().delivery_annotations_);
     size_t sz = std::max(s.capacity(), size_t(512));
     while (true) {
         s.resize(sz);
@@ -293,10 +322,7 @@ std::vector<char> message::encode() const {
 void message::decode(const std::vector<char> &s) {
     if (s.empty())
         throw error("message decode: no data");
-    application_properties_.clear();
-    message_annotations_.clear();
-    delivery_annotations_.clear();
-    assert(!s.empty());
+    impl().clear();
     check(pn_message_decode(pn_msg(), &s[0], s.size()));
 }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org