qpid-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From acon...@apache.org
Subject [1/3] qpid-proton git commit: PROTON-865: 0-overhead facades, reference counting and smart ptr support.
Date Mon, 31 Aug 2015 17:32:57 GMT
Repository: qpid-proton
Updated Branches:
  refs/heads/cjansen-cpp-client c69625830 -> 9bb9c442c


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/contexts.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/contexts.cpp b/proton-c/bindings/cpp/src/contexts.cpp
index 98c502b..3309214 100644
--- a/proton-c/bindings/cpp/src/contexts.cpp
+++ b/proton-c/bindings/cpp/src/contexts.cpp
@@ -20,53 +20,93 @@
  */
 
 #include "contexts.hpp"
-#include "proton/error.hpp"
 #include "msg.hpp"
+
+#include "proton/facade.hpp"
+#include "proton/error.hpp"
+#include "proton/handler.hpp"
+
 #include "proton/object.h"
 #include "proton/message.h"
 #include "proton/session.h"
 #include "proton/link.h"
 
-PN_HANDLE(PNI_CPP_CONNECTION_CONTEXT)
-PN_HANDLE(PNI_CPP_CONTAINER_CONTEXT)
-PN_HANDLE(PNI_CPP_EVENT_CONTEXT)
-
 namespace proton {
 
-void connection_context(pn_connection_t *pn_connection, connection_impl *connection) {
-    pn_record_t *record = pn_connection_attachments(pn_connection);
-    pn_record_def(record, PNI_CPP_CONNECTION_CONTEXT, PN_VOID);
-    pn_record_set(record, PNI_CPP_CONNECTION_CONTEXT, connection);
+namespace {
+
+// A proton class for counted c++ objects used as proton attachments
+#define CID_cpp_context CID_pn_void
+static const pn_class_t *cpp_context_reify(void *object) { return CPP_CONTEXT; }
+#define cpp_context_new NULL
+#define cpp_context_free NULL
+#define cpp_context_initialize NULL
+void cpp_context_incref(void* p) { proton::incref(reinterpret_cast<counted*>(p)); }
+void cpp_context_decref(void* p) { proton::decref(reinterpret_cast<counted*>(p)); }
+// Always return 1 to prevent the class finalizer logic running after we are deleted.
+int cpp_context_refcount(void* p) { return 1; }
+#define cpp_context_finalize NULL
+#define cpp_context_hashcode NULL
+#define cpp_context_compare NULL
+#define cpp_context_inspect NULL
+
+pn_class_t CPP_CONTEXT_ = PN_METACLASS(cpp_context);
 }
-connection_impl *connection_context(pn_connection_t *pn_connection) {
-    if (!pn_connection) return NULL;
-    pn_record_t *record = pn_connection_attachments(pn_connection);
-    connection_impl *p = (connection_impl *) pn_record_get(record, PNI_CPP_CONNECTION_CONTEXT);
-    return p;
+
+pn_class_t *CPP_CONTEXT = &CPP_CONTEXT_;
+
+void set_context(pn_record_t* record, pn_handle_t handle, counted* value)
+{
+    pn_record_def(record, handle, CPP_CONTEXT);
+    pn_record_set(record, handle, value);
+}
+
+counted* get_context(pn_record_t* record, pn_handle_t handle) {
+    return reinterpret_cast<counted*>(pn_record_get(record, handle));
 }
 
+// Connection context
+
+PN_HANDLE(CONNECTION_CONTEXT)
+
+connection_context::connection_context() : handler(0), default_session(0) {}
+connection_context::~connection_context() { delete handler; }
+
+struct connection_context& connection_context::get(pn_connection_t* c) {
+    connection_context* ctx = reinterpret_cast<connection_context*>(
+        get_context(pn_connection_attachments(c), CONNECTION_CONTEXT));
+    if (!ctx) {
+        ctx = new connection_context();
+        set_context(pn_connection_attachments(c), CONNECTION_CONTEXT, ctx);
+    }
+    return *ctx;
+}
+
+PN_HANDLE(CONTAINER_CONTEXT)
 
 void container_context(pn_reactor_t *pn_reactor, container_impl *container) {
     pn_record_t *record = pn_reactor_attachments(pn_reactor);
-    pn_record_def(record, PNI_CPP_CONTAINER_CONTEXT, PN_VOID);
-    pn_record_set(record, PNI_CPP_CONTAINER_CONTEXT, container);
+    pn_record_def(record, CONTAINER_CONTEXT, PN_VOID);
+    pn_record_set(record, CONTAINER_CONTEXT, container);
 }
 container_impl *container_context(pn_reactor_t *pn_reactor) {
     pn_record_t *record = pn_reactor_attachments(pn_reactor);
-    container_impl *p = (container_impl *) pn_record_get(record, PNI_CPP_CONTAINER_CONTEXT);
+    container_impl *p = (container_impl *) pn_record_get(record, CONTAINER_CONTEXT);
     if (!p) throw error(MSG("Reactor has no C++ container context"));
     return p;
 }
 
+PN_HANDLE(EVENT_CONTEXT)
+
 void event_context(pn_event_t *pn_event, pn_message_t *m) {
     pn_record_t *record = pn_event_attachments(pn_event);
-    pn_record_def(record, PNI_CPP_EVENT_CONTEXT, PN_OBJECT); // refcount it for life of the event
-    pn_record_set(record, PNI_CPP_EVENT_CONTEXT, m);
+    pn_record_def(record, EVENT_CONTEXT, PN_OBJECT); // refcount it for life of the event
+    pn_record_set(record, EVENT_CONTEXT, m);
 }
 pn_message_t *event_context(pn_event_t *pn_event) {
     if (!pn_event) return NULL;
     pn_record_t *record = pn_event_attachments(pn_event);
-    pn_message_t *p = (pn_message_t *) pn_record_get(record, PNI_CPP_EVENT_CONTEXT);
+    pn_message_t *p = (pn_message_t *) pn_record_get(record, EVENT_CONTEXT);
     return p;
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/contexts.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/contexts.hpp b/proton-c/bindings/cpp/src/contexts.hpp
index 1f0678d..ed6642b 100644
--- a/proton-c/bindings/cpp/src/contexts.hpp
+++ b/proton-c/bindings/cpp/src/contexts.hpp
@@ -21,24 +21,36 @@
  * under the License.
  *
  */
+
+#include "proton/facade.hpp"
+
 #include "proton/reactor.h"
 #include "proton/connection.h"
 #include "proton/message.h"
 
 namespace proton {
 
+class session;
+class handler;
+
+extern pn_class_t* CPP_CONTEXT;
+counted* get_context(pn_record_t*, pn_handle_t handle);
+void set_context(pn_record_t*, pn_handle_t, counted* value);
+
+struct connection_context : public counted {
+    static connection_context& get(pn_connection_t* c);
+
+    connection_context();
+    ~connection_context();
+
+    class handler* handler;
+    session* default_session;
+};
+
 class connection_impl;
 void connection_context(pn_connection_t *pn_connection, connection_impl *connection);
 connection_impl *connection_context(pn_connection_t *pn_connection);
 
-class session;
-void session_context(pn_session_t *pn_session, session *session);
-session *session_context(pn_session_t *pn_session);
-
-class link;
-void link_context(pn_link_t *get(), link *link);
-link *link_context(pn_link_t *get());
-
 class container_impl;
 void container_context(pn_reactor_t *pn_reactor, container_impl *container);
 container_impl *container_context(pn_reactor_t *pn_reactor);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/conversion_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/conversion_test.cpp b/proton-c/bindings/cpp/src/conversion_test.cpp
new file mode 100644
index 0000000..5302a2b
--- /dev/null
+++ b/proton-c/bindings/cpp/src/conversion_test.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+// Pointer conversion test.
+// NOTE needs to be run with valgrind to be effective.
+
+
+#include "test_bits.hpp"
+#include "proton/connection.hpp"
+#include "proton/session.hpp"
+#include "proton/session.hpp"
+
+using namespace std;
+using namespace proton;
+
+template <class connection_ptr, class session_ptr>
+void test_shared() {
+    connection_ptr conn(*connection::cast(pn_connection()));
+    session& s = conn->default_session();
+    session_ptr p = s;
+    ASSERT(p.unique());
+    session_ptr p2 = s;
+    ASSERT(!p.unique());                      // Should be in same family as s
+    conn.reset();                               // Make sure we still have session
+    p->create_sender("");
+}
+
+template <class connection_ptr, class session_ptr>
+void test_counted() {
+    connection_ptr conn(connection::cast(pn_connection()), false);
+    session& s = conn->default_session();
+    session_ptr p = s;
+    session_ptr p2 = s;
+    conn.reset();                               // Make sure we still have session
+    p->create_sender("");
+}
+
+template <class connection_ptr, class session_ptr>
+void test_unique() {
+    connection_ptr conn(connection::cast(pn_connection()));
+    session& s = conn->default_session();
+    session_ptr p(s);
+    session_ptr p2(s);
+    conn.reset();                               // Make sure we still have session
+    p->create_sender("");
+}
+
+
+int main(int argc, char** argv) {
+    int failed = 0;
+    failed += run_test(test_counted<counted_ptr<connection>,
+                       counted_ptr<session> >, "counted");
+#if PN_CPP11
+    failed += run_test(test_shared<std::shared_ptr<connection>,
+                       std::shared_ptr<session> >, "std::shared");
+    failed += run_test(test_unique<std::unique_ptr<connection>,
+                       std::unique_ptr<session> >, "std::unique");
+#endif
+#if PN_USE_BOOST
+    failed += run_test(test_shared<boost::shared_ptr<connection>,
+                       boost::shared_ptr<session> >, "boost::shared");
+    failed += run_test(test_counted<boost::intrusive_ptr<connection>,
+                       boost::intrusive_ptr<session> >, "boost::intrusive");
+#endif
+    return failed;
+}
+

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/data.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/data.cpp b/proton-c/bindings/cpp/src/data.cpp
index dd35890..2b925ff 100644
--- a/proton-c/bindings/cpp/src/data.cpp
+++ b/proton-c/bindings/cpp/src/data.cpp
@@ -17,51 +17,119 @@
  * under the License.
  */
 
-#include "proton/data.hpp"
-#include "proton/codec.h"
 #include "proton_bits.hpp"
-#include <utility>
+#include "proton/data.hpp"
+
+#include <proton/codec.h>
 
 namespace proton {
 
-data::data() : data_(::pn_data(0)), own_(true) {}
+void data::operator delete(void *p) { ::pn_data_free(reinterpret_cast<pn_data_t*>(p)); }
 
-data::data(pn_data_t* p) : data_(p), own_(false) { }
+data& data::operator=(const data& x) { ::pn_data_copy(pn_cast(this), pn_cast(&x)); return *this; }
 
-data::data(const data& x) : data_(::pn_data(0)), own_(true) { *this = x; }
+void data::clear() { ::pn_data_clear(pn_cast(this)); }
 
-data::~data() { if (own_ && data_) ::pn_data_free(data_); }
+bool data::empty() const { return ::pn_data_size(pn_cast(this)) == 0; }
 
-void data::view(pn_data_t* new_data) {
-    if (data_ && own_) pn_data_free(data_);
-    data_ = new_data;
-    own_ = false;
-}
+std::ostream& operator<<(std::ostream& o, const data& d) { return o << inspectable(pn_cast(&d)); }
+
+PN_UNIQUE_OR_AUTO_PTR<data> data::create() { return PN_UNIQUE_OR_AUTO_PTR<data>(cast(::pn_data(0))); }
 
-void data::swap(data& x) {
-    std::swap(data_, x.data_);
-    std::swap(own_, x.own_);
+encoder& data::encoder() { return reinterpret_cast<class encoder&>(*this); }
+decoder& data::decoder() { return reinterpret_cast<class decoder&>(*this); }
+
+namespace {
+
+// Compare nodes, return -1 if a<b, 0 if a==b, +1 if a>b
+// Forward-declare so we can use it recursively.
+int compare_next(data& a, data& b);
+
+template <class T> int compare(const T& a, const T& b) {
+    if (a < b) return -1;
+    else if (a > b) return +1;
+    else return 0;
 }
 
-data& data::operator=(const data& x) {
-    if (this != &x) {
-        if (!own_) {
-            data_ = ::pn_data(::pn_data_size(x.data_));
-            own_ = true;
-        } else {
-            clear();
-        }
-        ::pn_data_copy(data_, x.data_);
+int compare_container(data& a, data& b) {
+    decoder::scope sa(a.decoder()), sb(b.decoder());
+    // Compare described vs. not-described.
+    int cmp = compare(sa.is_described, sb.is_described);
+    if (cmp) return cmp;
+    // Lexical sort (including descriptor if there is one)
+    size_t min_size = std::min(sa.size, sb.size) + int(sa.is_described);
+    for (size_t i = 0; i < min_size; ++i) {
+        cmp = compare_next(a, b);
+        if (cmp) return cmp;
     }
-    return *this;
+    return compare(sa.size, sb.size);
 }
 
-void data::clear() { ::pn_data_clear(data_); }
+template <class T> int compare_simple(data& a, data& b) {
+    T va = T();
+    T vb = T();
+    a.decoder() >> va;
+    b.decoder() >> vb;
+    return compare(va, vb);
+}
 
-void data::rewind() { ::pn_data_rewind(data_); }
+int compare_next(data& a, data& b) {
+    // Sort by type_id first.
+    type_id ta = a.type(), tb = b.type();
+    int cmp = compare(ta, tb);
+    if (cmp) return cmp;
 
-bool data::empty() const { return ::pn_data_size(data_) == 0; }
+    switch (ta) {
+      case NULL_: return 0;
+      case ARRAY:
+      case LIST:
+      case MAP:
+      case DESCRIBED:
+        return compare_container(a, b);
+      case BOOL: return compare_simple<amqp_bool>(a, b);
+      case UBYTE: return compare_simple<amqp_ubyte>(a, b);
+      case BYTE: return compare_simple<amqp_byte>(a, b);
+      case USHORT: return compare_simple<amqp_ushort>(a, b);
+      case SHORT: return compare_simple<amqp_short>(a, b);
+      case UINT: return compare_simple<amqp_uint>(a, b);
+      case INT: return compare_simple<amqp_int>(a, b);
+      case CHAR: return compare_simple<amqp_char>(a, b);
+      case ULONG: return compare_simple<amqp_ulong>(a, b);
+      case LONG: return compare_simple<amqp_long>(a, b);
+      case TIMESTAMP: return compare_simple<amqp_timestamp>(a, b);
+      case FLOAT: return compare_simple<amqp_float>(a, b);
+      case DOUBLE: return compare_simple<amqp_double>(a, b);
+      case DECIMAL32: return compare_simple<amqp_decimal32>(a, b);
+      case DECIMAL64: return compare_simple<amqp_decimal64>(a, b);
+      case DECIMAL128: return compare_simple<amqp_decimal128>(a, b);
+      case UUID: return compare_simple<amqp_uuid>(a, b);
+      case BINARY: return compare_simple<amqp_binary>(a, b);
+      case STRING: return compare_simple<amqp_string>(a, b);
+      case SYMBOL: return compare_simple<amqp_symbol>(a, b);
+    }
+    // Invalid but equal type_id, treat as equal.
+    return 0;
+}
+
+int compare(data& a, data& b) {
+    a.decoder().rewind();
+    b.decoder().rewind();
+    while (a.decoder().more() && b.decoder().more()) {
+        int cmp = compare_next(a, b);
+        if (cmp != 0) return cmp;
+    }
+    if (b.decoder().more()) return -1;
+    if (a.decoder().more()) return 1;
+    return 0;
+}
+} // namespace
 
-std::ostream& operator<<(std::ostream& o, const data& d) { return o << inspectable(d.data_); }
+bool data::operator==(const data& x) const {
+    return compare(const_cast<data&>(*this), const_cast<data&>(x)) == 0;
+}
+bool data::operator<(const data& x) const {
+    return compare(const_cast<data&>(*this), const_cast<data&>(x)) < 0;
+}
 
 }
+

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/decoder.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/decoder.cpp b/proton-c/bindings/cpp/src/decoder.cpp
index 6ad7dfe..e118e5a 100644
--- a/proton-c/bindings/cpp/src/decoder.cpp
+++ b/proton-c/bindings/cpp/src/decoder.cpp
@@ -18,7 +18,7 @@
  */
 
 #include "proton/decoder.hpp"
-#include "proton/value.hpp"
+#include "proton/data.hpp"
 #include <proton/codec.h>
 #include "proton_bits.hpp"
 #include "msg.hpp"
@@ -31,11 +31,6 @@ namespace proton {
  * to be returned by the decoder.
  *
  */
-decoder::decoder() {}
-decoder::decoder(const char* buffer, size_t size) { decode(buffer, size); }
-decoder::decoder(const std::string& buffer) { decode(buffer); }
-decoder::~decoder() {}
-
 static const std::string prefix("decode: ");
 decode_error::decode_error(const std::string& msg) throw() : error(prefix+msg) {}
 
@@ -48,10 +43,10 @@ struct save_state {
     void cancel() { data = 0; }
 };
 
-struct Narrow {
+struct narrow {
     pn_data_t* data;
-    Narrow(pn_data_t* d) : data(d) { pn_data_narrow(d); }
-    ~Narrow() { pn_data_widen(data); }
+    narrow(pn_data_t* d) : data(d) { pn_data_narrow(d); }
+    ~narrow() { pn_data_widen(data); }
 };
 
 template <class T> T check(T result) {
@@ -63,10 +58,10 @@ template <class T> T check(T result) {
 }
 
 void decoder::decode(const char* i, size_t size) {
-    save_state ss(data_);
+    save_state ss(pn_cast(this));
     const char* end = i + size;
     while (i < end) {
-        i += check(pn_data_decode(data_, i, end - i));
+        i += check(pn_data_decode(pn_cast(this), i, end - i));
     }
 }
 
@@ -75,10 +70,16 @@ void decoder::decode(const std::string& buffer) {
 }
 
 bool decoder::more() const {
-    save_state ss(data_);
-    return pn_data_next(data_);
+    save_state ss(pn_cast(this));
+    return pn_data_next(pn_cast(this));
 }
 
+void decoder::rewind() { ::pn_data_rewind(pn_cast(this)); }
+
+void decoder::backup() { ::pn_data_prev(pn_cast(this)); }
+
+data& decoder::data() { return *data::cast(pn_cast(this)); }
+
 namespace {
 
 void bad_type(type_id want, type_id got) {
@@ -109,24 +110,23 @@ void decoder::check_type(type_id want) {
 }
 
 type_id decoder::type() const {
-    save_state ss(data_);
-    return pre_get(data_);
+    save_state ss(pn_cast(this));
+    return pre_get(pn_cast(this));
 }
 
 decoder& operator>>(decoder& d, start& s) {
-    save_state ss(d.data_);
-    s.type = pre_get(d.data_);
+    save_state ss(pn_cast(&d));
+    s.type = pre_get(pn_cast(&d));
     switch (s.type) {
       case ARRAY:
-        s.size = pn_data_get_array(d.data_);
-        s.element = type_id(pn_data_get_array_type(d.data_));
-        s.is_described = pn_data_is_array_described(d.data_);
+        s.size = pn_data_get_array(pn_cast(&d));
+        s.element = type_id(pn_data_get_array_type(pn_cast(&d))); s.is_described = pn_data_is_array_described(pn_cast(&d));
         break;
       case LIST:
-        s.size = pn_data_get_list(d.data_);
+        s.size = pn_data_get_list(pn_cast(&d));
         break;
       case MAP:
-        s.size = pn_data_get_map(d.data_);
+        s.size = pn_data_get_map(pn_cast(&d));
         break;
       case DESCRIBED:
         s.is_described = true;
@@ -135,191 +135,191 @@ decoder& operator>>(decoder& d, start& s) {
       default:
         throw decode_error(MSG("" << s.type << " is not a container type"));
     }
-    pn_data_enter(d.data_);
+    pn_data_enter(pn_cast(&d));
     ss.cancel();
     return d;
 }
 
-decoder& operator>>(decoder& d, finish) { pn_data_exit(d.data_); return d; }
+decoder& operator>>(decoder& d, finish) { pn_data_exit(pn_cast(&d)); return d; }
 
-decoder& operator>>(decoder& d, skip) { pn_data_next(d.data_); return d; }
+decoder& operator>>(decoder& d, skip) { pn_data_next(pn_cast(&d)); return d; }
 
 decoder& operator>>(decoder& d, rewind) { d.rewind(); return d; }
 
-decoder& operator>>(decoder& d, value& v) {
-    if (d.data_ == v.values_.data_) throw decode_error("extract into self");
-    pn_data_clear(v.values_.data_);
+decoder& operator>>(decoder& d, data& v) {
+    if (pn_cast(&d) == pn_cast(&v)) throw decode_error("extract into self");
+    v.clear();
     {
-        Narrow n(d.data_);
-        check(pn_data_appendn(v.values_.data_, d.data_, 1));
+        narrow n(pn_cast(&d));
+        check(pn_data_appendn(pn_cast(&v), pn_cast(&d), 1));
     }
-    if (!pn_data_next(d.data_)) throw decode_error("no more data");
+    if (!pn_data_next(pn_cast(&d))) throw decode_error("no more data");
     return d;
 }
 
 
 decoder& operator>>(decoder& d, amqp_null) {
-    save_state ss(d.data_);
-    bad_type(NULl_, pre_get(d.data_));
+    save_state ss(pn_cast(&d));
+    bad_type(NULL_, pre_get(pn_cast(&d)));
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_bool& value) {
-    extract(d.data_, value, pn_data_get_bool);
+    extract(pn_cast(&d), value, pn_data_get_bool);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_ubyte& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case UBYTE: value = pn_data_get_ubyte(d.data_); break;
-      default: bad_type(UBYTE, type_id(type_id(pn_data_type(d.data_))));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case UBYTE: value = pn_data_get_ubyte(pn_cast(&d)); break;
+      default: bad_type(UBYTE, type_id(type_id(pn_data_type(pn_cast(&d)))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_byte& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case BYTE: value = pn_data_get_byte(d.data_); break;
-      default: bad_type(BYTE, type_id(type_id(pn_data_type(d.data_))));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case BYTE: value = pn_data_get_byte(pn_cast(&d)); break;
+      default: bad_type(BYTE, type_id(type_id(pn_data_type(pn_cast(&d)))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_ushort& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case UBYTE: value = pn_data_get_ubyte(d.data_); break;
-      case USHORT: value = pn_data_get_ushort(d.data_); break;
-      default: bad_type(USHORT, type_id(type_id(pn_data_type(d.data_))));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case UBYTE: value = pn_data_get_ubyte(pn_cast(&d)); break;
+      case USHORT: value = pn_data_get_ushort(pn_cast(&d)); break;
+      default: bad_type(USHORT, type_id(type_id(pn_data_type(pn_cast(&d)))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_short& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case BYTE: value = pn_data_get_byte(d.data_); break;
-      case SHORT: value = pn_data_get_short(d.data_); break;
-      default: bad_type(SHORT, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case BYTE: value = pn_data_get_byte(pn_cast(&d)); break;
+      case SHORT: value = pn_data_get_short(pn_cast(&d)); break;
+      default: bad_type(SHORT, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_uint& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case UBYTE: value = pn_data_get_ubyte(d.data_); break;
-      case USHORT: value = pn_data_get_ushort(d.data_); break;
-      case UINT: value = pn_data_get_uint(d.data_); break;
-      default: bad_type(UINT, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case UBYTE: value = pn_data_get_ubyte(pn_cast(&d)); break;
+      case USHORT: value = pn_data_get_ushort(pn_cast(&d)); break;
+      case UINT: value = pn_data_get_uint(pn_cast(&d)); break;
+      default: bad_type(UINT, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_int& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case BYTE: value = pn_data_get_byte(d.data_); break;
-      case SHORT: value = pn_data_get_short(d.data_); break;
-      case INT: value = pn_data_get_int(d.data_); break;
-      default: bad_type(INT, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case BYTE: value = pn_data_get_byte(pn_cast(&d)); break;
+      case SHORT: value = pn_data_get_short(pn_cast(&d)); break;
+      case INT: value = pn_data_get_int(pn_cast(&d)); break;
+      default: bad_type(INT, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_ulong& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case UBYTE: value = pn_data_get_ubyte(d.data_); break;
-      case USHORT: value = pn_data_get_ushort(d.data_); break;
-      case UINT: value = pn_data_get_uint(d.data_); break;
-      case ULONG: value = pn_data_get_ulong(d.data_); break;
-      default: bad_type(ULONG, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case UBYTE: value = pn_data_get_ubyte(pn_cast(&d)); break;
+      case USHORT: value = pn_data_get_ushort(pn_cast(&d)); break;
+      case UINT: value = pn_data_get_uint(pn_cast(&d)); break;
+      case ULONG: value = pn_data_get_ulong(pn_cast(&d)); break;
+      default: bad_type(ULONG, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_long& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case BYTE: value = pn_data_get_byte(d.data_); break;
-      case SHORT: value = pn_data_get_short(d.data_); break;
-      case INT: value = pn_data_get_int(d.data_); break;
-      case LONG: value = pn_data_get_long(d.data_); break;
-      default: bad_type(LONG, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case BYTE: value = pn_data_get_byte(pn_cast(&d)); break;
+      case SHORT: value = pn_data_get_short(pn_cast(&d)); break;
+      case INT: value = pn_data_get_int(pn_cast(&d)); break;
+      case LONG: value = pn_data_get_long(pn_cast(&d)); break;
+      default: bad_type(LONG, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_char& value) {
-    extract(d.data_, value, pn_data_get_char);
+    extract(pn_cast(&d), value, pn_data_get_char);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_timestamp& value) {
-    extract(d.data_, value, pn_data_get_timestamp);
+    extract(pn_cast(&d), value, pn_data_get_timestamp);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_float& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case FLOAT: value = pn_data_get_float(d.data_); break;
-      case DOUBLE: value = pn_data_get_double(d.data_); break;
-      default: bad_type(FLOAT, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case FLOAT: value = pn_data_get_float(pn_cast(&d)); break;
+      case DOUBLE: value = pn_data_get_double(pn_cast(&d)); break;
+      default: bad_type(FLOAT, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_double& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case FLOAT: value = pn_data_get_float(d.data_); break;
-      case DOUBLE: value = pn_data_get_double(d.data_); break;
-      default: bad_type(DOUBLE, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case FLOAT: value = pn_data_get_float(pn_cast(&d)); break;
+      case DOUBLE: value = pn_data_get_double(pn_cast(&d)); break;
+      default: bad_type(DOUBLE, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_decimal32& value) {
-    extract(d.data_, value, pn_data_get_decimal32);
+    extract(pn_cast(&d), value, pn_data_get_decimal32);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_decimal64& value) {
-    extract(d.data_, value, pn_data_get_decimal64);
+    extract(pn_cast(&d), value, pn_data_get_decimal64);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_decimal128& value)  {
-    extract(d.data_, value, pn_data_get_decimal128);
+    extract(pn_cast(&d), value, pn_data_get_decimal128);
     return d;
 }
 
 decoder& operator>>(decoder& d, amqp_uuid& value)  {
-    extract(d.data_, value, pn_data_get_uuid);
+    extract(pn_cast(&d), value, pn_data_get_uuid);
     return d;
 }
 
 decoder& operator>>(decoder& d, std::string& value) {
-    save_state ss(d.data_);
-    switch (pre_get(d.data_)) {
-      case STRING: value = str(pn_data_get_string(d.data_)); break;
-      case BINARY: value = str(pn_data_get_binary(d.data_)); break;
-      case SYMBOL: value = str(pn_data_get_symbol(d.data_)); break;
-      default: bad_type(STRING, type_id(pn_data_type(d.data_)));
+    save_state ss(pn_cast(&d));
+    switch (pre_get(pn_cast(&d))) {
+      case STRING: value = str(pn_data_get_string(pn_cast(&d))); break;
+      case BINARY: value = str(pn_data_get_binary(pn_cast(&d))); break;
+      case SYMBOL: value = str(pn_data_get_symbol(pn_cast(&d))); break;
+      default: bad_type(STRING, type_id(pn_data_type(pn_cast(&d))));
     }
     ss.cancel();
     return d;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/delivery.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/delivery.cpp b/proton-c/bindings/cpp/src/delivery.cpp
index 93b4349..1962fa2 100644
--- a/proton-c/bindings/cpp/src/delivery.cpp
+++ b/proton-c/bindings/cpp/src/delivery.cpp
@@ -24,12 +24,15 @@
 
 namespace proton {
 
-delivery::delivery(pn_delivery_t *p) : wrapper<pn_delivery_t>(p) {}
+bool delivery::settled() { return pn_delivery_settled(pn_cast(this)); }
 
-bool delivery::settled() { return pn_delivery_settled(get()); }
+void delivery::settle() { pn_delivery_settle(pn_cast(this)); }
 
-void delivery::settle() { pn_delivery_settle(get()); }
+void delivery::update(delivery::state state) { pn_delivery_update(pn_cast(this), state); }
 
-void delivery::update(delivery::state state) { pn_delivery_update(get(), state); }
+void delivery::settle(delivery::state state) {
+    update(state);
+    settle();
+}
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/encoder.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/encoder.cpp b/proton-c/bindings/cpp/src/encoder.cpp
index 9c32f58..9904b2a 100644
--- a/proton-c/bindings/cpp/src/encoder.cpp
+++ b/proton-c/bindings/cpp/src/encoder.cpp
@@ -18,16 +18,13 @@
  */
 
 #include "proton/encoder.hpp"
-#include "proton/value.hpp"
+#include "proton/data.hpp"
 #include <proton/codec.h>
 #include "proton_bits.hpp"
 #include "msg.hpp"
 
 namespace proton {
 
-encoder::encoder() {}
-encoder::~encoder() {}
-
 static const std::string prefix("encode: ");
 encode_error::encode_error(const std::string& msg) throw() : error(prefix+msg) {}
 
@@ -47,19 +44,19 @@ void check(int result, pn_data_t* data) {
 }
 
 bool encoder::encode(char* buffer, size_t& size) {
-    save_state ss(data_);               // In case of error
-    ssize_t result = pn_data_encode(data_, buffer, size);
+    save_state ss(pn_cast(this)); // In case of error
+    ssize_t result = pn_data_encode(pn_cast(this), buffer, size);
     if (result == PN_OVERFLOW) {
-        result = pn_data_encoded_size(data_);
+        result = pn_data_encoded_size(pn_cast(this));
         if (result >= 0) {
             size = result;
             return false;
         }
     }
-    check(result, data_);
+    check(result, pn_cast(this));
     size = result;
     ss.cancel();                // Don't restore state, all is well.
-    pn_data_clear(data_);
+    pn_data_clear(pn_cast(this));
     return true;
 }
 
@@ -77,21 +74,23 @@ std::string encoder::encode() {
     return s;
 }
 
+data& encoder::data() { return *data::cast(pn_cast(this)); }
+
 encoder& operator<<(encoder& e, const start& s) {
     switch (s.type) {
-      case ARRAY: pn_data_put_array(e.data_, s.is_described, pn_type_t(s.element)); break;
-      case MAP: pn_data_put_map(e.data_); break;
-      case LIST: pn_data_put_list(e.data_); break;
-      case DESCRIBED: pn_data_put_described(e.data_); break;
+      case ARRAY: pn_data_put_array(pn_cast(&e), s.is_described, pn_type_t(s.element)); break;
+      case MAP: pn_data_put_map(pn_cast(&e)); break;
+      case LIST: pn_data_put_list(pn_cast(&e)); break;
+      case DESCRIBED: pn_data_put_described(pn_cast(&e)); break;
       default:
         throw encode_error(MSG("" << s.type << " is not a container type"));
     }
-    pn_data_enter(e.data_);
+    pn_data_enter(pn_cast(&e));
     return e;
 }
 
 encoder& operator<<(encoder& e, finish) {
-    pn_data_exit(e.data_);
+    pn_data_exit(pn_cast(&e));
     return e;
 }
 
@@ -105,37 +104,31 @@ encoder& insert(encoder& e, pn_data_t* data, T& value, int (*put)(pn_data_t*, U)
 }
 }
 
-encoder& operator<<(encoder& e, amqp_null) { pn_data_put_null(e.data_); return e; }
-encoder& operator<<(encoder& e, amqp_bool value) { return insert(e, e.data_, value, pn_data_put_bool); }
-encoder& operator<<(encoder& e, amqp_ubyte value) { return insert(e, e.data_, value, pn_data_put_ubyte); }
-encoder& operator<<(encoder& e, amqp_byte value) { return insert(e, e.data_, value, pn_data_put_byte); }
-encoder& operator<<(encoder& e, amqp_ushort value) { return insert(e, e.data_, value, pn_data_put_ushort); }
-encoder& operator<<(encoder& e, amqp_short value) { return insert(e, e.data_, value, pn_data_put_short); }
-encoder& operator<<(encoder& e, amqp_uint value) { return insert(e, e.data_, value, pn_data_put_uint); }
-encoder& operator<<(encoder& e, amqp_int value) { return insert(e, e.data_, value, pn_data_put_int); }
-encoder& operator<<(encoder& e, amqp_char value) { return insert(e, e.data_, value, pn_data_put_char); }
-encoder& operator<<(encoder& e, amqp_ulong value) { return insert(e, e.data_, value, pn_data_put_ulong); }
-encoder& operator<<(encoder& e, amqp_long value) { return insert(e, e.data_, value, pn_data_put_long); }
-encoder& operator<<(encoder& e, amqp_timestamp value) { return insert(e, e.data_, value, pn_data_put_timestamp); }
-encoder& operator<<(encoder& e, amqp_float value) { return insert(e, e.data_, value, pn_data_put_float); }
-encoder& operator<<(encoder& e, amqp_double value) { return insert(e, e.data_, value, pn_data_put_double); }
-encoder& operator<<(encoder& e, amqp_decimal32 value) { return insert(e, e.data_, value, pn_data_put_decimal32); }
-encoder& operator<<(encoder& e, amqp_decimal64 value) { return insert(e, e.data_, value, pn_data_put_decimal64); }
-encoder& operator<<(encoder& e, amqp_decimal128 value) { return insert(e, e.data_, value, pn_data_put_decimal128); }
-encoder& operator<<(encoder& e, amqp_uuid value) { return insert(e, e.data_, value, pn_data_put_uuid); }
-encoder& operator<<(encoder& e, amqp_string value) { return insert(e, e.data_, value, pn_data_put_string); }
-encoder& operator<<(encoder& e, amqp_symbol value) { return insert(e, e.data_, value, pn_data_put_symbol); }
-encoder& operator<<(encoder& e, amqp_binary value) { return insert(e, e.data_, value, pn_data_put_binary); }
-
-encoder& operator<<(encoder& e, const value& v) {
-    if (e.data_ == v.values_.data_) throw encode_error("cannot insert into self");
-    check(pn_data_appendn(e.data_, v.values_.data_, 1), e.data_);
-    return e;
-}
-
-encoder& operator<<(encoder& e, const values& v) {
-    if (e.data_ == v.data_) throw encode_error("cannot insert into self");
-    check(pn_data_append(e.data_, v.data_), e.data_);
+encoder& operator<<(encoder& e, amqp_null) { pn_data_put_null(pn_cast(&e)); return e; }
+encoder& operator<<(encoder& e, amqp_bool value) { return insert(e, pn_cast(&e), value, pn_data_put_bool); }
+encoder& operator<<(encoder& e, amqp_ubyte value) { return insert(e, pn_cast(&e), value, pn_data_put_ubyte); }
+encoder& operator<<(encoder& e, amqp_byte value) { return insert(e, pn_cast(&e), value, pn_data_put_byte); }
+encoder& operator<<(encoder& e, amqp_ushort value) { return insert(e, pn_cast(&e), value, pn_data_put_ushort); }
+encoder& operator<<(encoder& e, amqp_short value) { return insert(e, pn_cast(&e), value, pn_data_put_short); }
+encoder& operator<<(encoder& e, amqp_uint value) { return insert(e, pn_cast(&e), value, pn_data_put_uint); }
+encoder& operator<<(encoder& e, amqp_int value) { return insert(e, pn_cast(&e), value, pn_data_put_int); }
+encoder& operator<<(encoder& e, amqp_char value) { return insert(e, pn_cast(&e), value, pn_data_put_char); }
+encoder& operator<<(encoder& e, amqp_ulong value) { return insert(e, pn_cast(&e), value, pn_data_put_ulong); }
+encoder& operator<<(encoder& e, amqp_long value) { return insert(e, pn_cast(&e), value, pn_data_put_long); }
+encoder& operator<<(encoder& e, amqp_timestamp value) { return insert(e, pn_cast(&e), value, pn_data_put_timestamp); }
+encoder& operator<<(encoder& e, amqp_float value) { return insert(e, pn_cast(&e), value, pn_data_put_float); }
+encoder& operator<<(encoder& e, amqp_double value) { return insert(e, pn_cast(&e), value, pn_data_put_double); }
+encoder& operator<<(encoder& e, amqp_decimal32 value) { return insert(e, pn_cast(&e), value, pn_data_put_decimal32); }
+encoder& operator<<(encoder& e, amqp_decimal64 value) { return insert(e, pn_cast(&e), value, pn_data_put_decimal64); }
+encoder& operator<<(encoder& e, amqp_decimal128 value) { return insert(e, pn_cast(&e), value, pn_data_put_decimal128); }
+encoder& operator<<(encoder& e, amqp_uuid value) { return insert(e, pn_cast(&e), value, pn_data_put_uuid); }
+encoder& operator<<(encoder& e, amqp_string value) { return insert(e, pn_cast(&e), value, pn_data_put_string); }
+encoder& operator<<(encoder& e, amqp_symbol value) { return insert(e, pn_cast(&e), value, pn_data_put_symbol); }
+encoder& operator<<(encoder& e, amqp_binary value) { return insert(e, pn_cast(&e), value, pn_data_put_binary); }
+
+encoder& operator<<(encoder& e, const data& v) {
+    if (pn_cast(&e) == pn_cast(&v)) throw encode_error("cannot insert into self");
+    check(pn_data_append(pn_cast(&e), pn_cast(&v)), pn_cast(&e));
     return e;
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/endpoint.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/endpoint.cpp b/proton-c/bindings/cpp/src/endpoint.cpp
index 2b7d645..6c46c7c 100644
--- a/proton-c/bindings/cpp/src/endpoint.cpp
+++ b/proton-c/bindings/cpp/src/endpoint.cpp
@@ -26,10 +26,6 @@
 
 namespace proton {
 
-endpoint::endpoint() {}
-
-endpoint::~endpoint() {}
-
 const int endpoint::LOCAL_UNINIT = PN_LOCAL_UNINIT;
 const int endpoint::REMOTE_UNINIT = PN_REMOTE_UNINIT;
 const int endpoint::LOCAL_ACTIVE = PN_LOCAL_ACTIVE;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/event.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/event.cpp b/proton-c/bindings/cpp/src/event.cpp
index d773878..d7a99dc 100644
--- a/proton-c/bindings/cpp/src/event.cpp
+++ b/proton-c/bindings/cpp/src/event.cpp
@@ -22,11 +22,12 @@
 #include "proton/reactor.h"
 #include "proton/event.h"
 
+#include "proton/delivery.hpp"
+#include "proton/error.hpp"
 #include "proton/event.hpp"
 #include "proton/handler.hpp"
-#include "proton/error.hpp"
-#include "proton/sender.hpp"
 #include "proton/receiver.hpp"
+#include "proton/sender.hpp"
 
 #include "msg.hpp"
 #include "contexts.hpp"
@@ -38,28 +39,28 @@ event::event() {}
 event::~event() {}
 
 
-class container &event::container() {
+container &event::container() {
     // Subclasses to override as appropriate
     throw error(MSG("No container context for event"));
 }
 
-class connection &event::connection() {
+connection &event::connection() {
     throw error(MSG("No connection context for event"));
 }
 
-class sender event::sender() {
+sender& event::sender() {
     throw error(MSG("No sender context for event"));
 }
 
-class receiver event::receiver() {
+receiver& event::receiver() {
     throw error(MSG("No receiver context for event"));
 }
 
-class link event::link() {
+link& event::link() {
     throw error(MSG("No link context for event"));
 }
 
-class delivery event::delivery() {
+delivery& event::delivery() {
     throw error(MSG("No link context for event"));
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/facade.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/facade.cpp b/proton-c/bindings/cpp/src/facade.cpp
new file mode 100644
index 0000000..c537720
--- /dev/null
+++ b/proton-c/bindings/cpp/src/facade.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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/facade.hpp"
+#include <proton/object.h>
+#include <assert.h>
+
+// For empty check.
+#include "proton/acceptor.hpp"
+#include "proton/connection.hpp"
+#include "proton/data.hpp"
+#include "proton/decoder.hpp"
+#include "proton/delivery.hpp"
+#include "proton/encoder.hpp"
+#include "proton/facade.hpp"
+#include "proton/link.hpp"
+#include "proton/message.hpp"
+#include "proton/session.hpp"
+#include "proton/terminus.hpp"
+#include "proton/transport.hpp"
+
+namespace proton {
+
+void incref(const pn_counted* p) {
+    if (p) pn_incref(const_cast<pn_counted*>(p)); 
+}
+
+void decref(const pn_counted* p) {
+    if (p) pn_decref(const_cast<pn_counted*>(p));
+}
+
+counted::counted() : refcount_(0) {}
+counted::~counted() {}
+
+// FIX ME aconway 2015-08-27: atomic operations.
+
+void incref(const counted* p) {
+    if (p) const_cast<counted*>(p)->refcount_ += 1;
+}
+void decref(const counted* p) {
+    if (p && --const_cast<counted*>(p)->refcount_ == 0) delete p;
+}
+
+#if PN_USE_CPP11
+// Make sure facade types are empty.
+#define CHECK_EMPTY(T) static_assert(std::is_empty<T>::value,  "facade " #T " not empty")
+
+CHECK_EMPTY(acceptor);
+CHECK_EMPTY(connection);
+CHECK_EMPTY(data);
+CHECK_EMPTY(decoder);
+CHECK_EMPTY(delivery);
+CHECK_EMPTY(encoder);
+CHECK_EMPTY(link);
+CHECK_EMPTY(message);
+CHECK_EMPTY(session);
+CHECK_EMPTY(terminus);
+CHECK_EMPTY(transport);
+
+#endif
+}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/fetcher.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/fetcher.cpp b/proton-c/bindings/cpp/src/fetcher.cpp
index 165a018..ec716f4 100644
--- a/proton-c/bindings/cpp/src/fetcher.cpp
+++ b/proton-c/bindings/cpp/src/fetcher.cpp
@@ -43,7 +43,7 @@ void fetcher::decref() {
 }
 
 void fetcher::on_link_init(event &e) {
-    pn_link_ = e.link().get();
+    pn_link_ = pn_cast(&e.link());
     pn_incref(pn_link_);
 }
 
@@ -55,8 +55,8 @@ void fetcher::on_message(event &e) {
 }
 
 void fetcher::on_link_error(event &e) {
-    link lnk = e.link();
-    if (pn_link_state(lnk.get()) & PN_LOCAL_ACTIVE) {
+    link& lnk = e.link();
+    if (pn_link_state(pn_cast(&lnk)) & PN_LOCAL_ACTIVE) {
         lnk.close();
         throw error(MSG("Link detached: " << lnk.name()));
     }
@@ -73,8 +73,8 @@ bool fetcher::has_message() {
 message fetcher::pop() {
     if (messages_.empty())
         throw error(MSG("blocking_receiver has no messages"));
-    delivery &dlv(deliveries_.front());
-    if (!dlv.settled())
+    counted_ptr<delivery> dlv(deliveries_.front());
+    if (!dlv->settled())
         unsettled_.push_back(dlv);
     message m = messages_.front();
     messages_.pop_front();
@@ -83,10 +83,10 @@ message fetcher::pop() {
 }
 
 void fetcher::settle(delivery::state state) {
-    delivery &dlv = unsettled_.front();
+    counted_ptr<delivery> dlv = unsettled_.front();
     if (state)
-        dlv.update(state);
-    dlv.settle();
+        dlv->update(state);
+    dlv->settle();
 }
 
 } // namespace

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/fetcher.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/fetcher.hpp b/proton-c/bindings/cpp/src/fetcher.hpp
index 85200fe..bb83a63 100644
--- a/proton-c/bindings/cpp/src/fetcher.hpp
+++ b/proton-c/bindings/cpp/src/fetcher.hpp
@@ -35,8 +35,8 @@ class fetcher : public messaging_handler {
   private:
     blocking_connection connection_;
     std::deque<message> messages_;
-    std::deque<delivery> deliveries_;
-    std::deque<delivery> unsettled_;
+    std::deque<counted_ptr<delivery> > deliveries_;
+    std::deque<counted_ptr<delivery> > unsettled_;
     int refcount_;
     pn_link_t *pn_link_;
   public:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/interop_test.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/interop_test.cpp b/proton-c/bindings/cpp/src/interop_test.cpp
index a8c0fe1..99123f7 100644
--- a/proton-c/bindings/cpp/src/interop_test.cpp
+++ b/proton-c/bindings/cpp/src/interop_test.cpp
@@ -19,9 +19,8 @@
 
 #include "proton/decoder.hpp"
 #include "proton/encoder.hpp"
-#include "proton/value.hpp"
-#include "msg.hpp"
-#include <stdexcept>
+#include "proton/data.hpp"
+#include "test_bits.hpp"
 #include <string>
 #include <sstream>
 #include <fstream>
@@ -33,13 +32,6 @@ using namespace proton;
 
 std::string tests_dir;
 
-struct Fail : public logic_error { Fail(const string& what) : logic_error(what) {} };
-#define FAIL(WHAT) throw Fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT))
-#define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false)
-#define ASSERT_EQUAL(WANT, GOT) if ((WANT) != (GOT)) \
-        FAIL(#WANT << " !=  " << #GOT << ": " << WANT << " != " << GOT)
-
-
 string read(string filename) {
     filename = tests_dir+string("/interop/")+filename+string(".amqp");
     ifstream ifs(filename.c_str());
@@ -57,13 +49,16 @@ template <class T> std::string str(const T& value) {
 
 // Test data ostream operator
 void test_data_ostream() {
-    decoder d(read("primitives"));
-    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(d));
+    data_value dv;
+    dv.decoder().decode(read("primitives"));
+    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(dv));
 }
 
 // Test extracting to exact AMQP types works corectly, extrating to invalid types fails.
 void test_decoder_primitves_exact() {
-    decoder d(read("primitives"));
+    data_value dv;
+    dv.decoder().decode(read("primitives"));
+    decoder& d(dv.decoder());
     ASSERT(d.more());
     try { get<std::int8_t>(d); FAIL("got bool as byte"); } catch(decode_error){}
     ASSERT_EQUAL(true, get<bool>(d));
@@ -87,47 +82,34 @@ void test_decoder_primitves_exact() {
 
 // Test inserting primitive sand encoding as AMQP.
 void test_encoder_primitives() {
-    encoder e;
+    data_value dv;
+    encoder& e = dv.encoder();
     e << true << false;
     e << std::uint8_t(42);
     e << std::uint16_t(42) << std::int16_t(-42);
     e << std::uint32_t(12345) << std::int32_t(-12345);
     e << std::uint64_t(12345) << std::int64_t(-12345);
     e << float(0.125) << double(0.125);
-    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(e));
+    ASSERT_EQUAL("true, false, 42, 42, -42, 12345, -12345, 12345, -12345, 0.125, 0.125", str(e.data()));
     std::string data = e.encode();
     ASSERT_EQUAL(read("primitives"), data);
 }
 
 // Test type conversions.
 void test_value_conversions() {
-    value v;
+    data_value v;
     ASSERT_EQUAL(true, bool(v = true));
     ASSERT_EQUAL(2, int(v=amqp_byte(2)));
     ASSERT_EQUAL(3, long(v=amqp_byte(3)));
     ASSERT_EQUAL(3, long(v=amqp_byte(3)));
     ASSERT_EQUAL(1.0, double(v=amqp_float(1.0)));
     ASSERT_EQUAL(1.0, float(v=amqp_double(1.0)));
-    try { bool(v = amqp_byte(1)); FAIL("got byte as bool"); } catch (decode_error) {}
-    try { float(v = true); FAIL("got bool as float"); } catch (decode_error) {}
-}
-
-int run_test(void (*testfn)(), const char* name) {
-    try {
-        testfn();
-        return 0;
-    } catch(const Fail& e) {
-        cout << "FAIL " << name << endl << e.what();
-    } catch(const std::exception& e) {
-        cout << "ERROR " << name << endl << e.what();
-    }
-    return 1;
+    try { (void)bool(v = amqp_byte(1)); FAIL("got byte as bool"); } catch (decode_error) {}
+    try { (void)float(v = true); FAIL("got bool as float"); } catch (decode_error) {}
 }
 
 // TODO aconway 2015-06-11: interop test is not complete.
 
-#define RUN_TEST(T) run_test(&T, #T)
-
 int main(int argc, char** argv) {
     int failed = 0;
     if (argc != 2) FAIL("Usage: " << argv[0] << " tests-dir");

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/link.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/link.cpp b/proton-c/bindings/cpp/src/link.cpp
index 95c0ed8..25bd3f3 100644
--- a/proton-c/bindings/cpp/src/link.cpp
+++ b/proton-c/bindings/cpp/src/link.cpp
@@ -21,7 +21,6 @@
 #include "proton/link.hpp"
 #include "proton/error.hpp"
 #include "proton/connection.hpp"
-#include "connection_impl.hpp"
 #include "msg.hpp"
 #include "contexts.hpp"
 
@@ -31,55 +30,49 @@
 
 namespace proton {
 
-link::link(pn_link_t* p) : wrapper<pn_link_t>(p) {}
-
 void link::open() {
-    pn_link_open(get());
+    pn_link_open(pn_cast(this));
 }
 
 void link::close() {
-    pn_link_close(get());
-}
-
-bool link::is_sender() {
-    return pn_link_is_sender(get());
+    pn_link_close(pn_cast(this));
 }
 
-bool link::is_receiver() { return !is_sender(); }
+bool link::is_sender() { return pn_link_is_sender(pn_cast(this)); }
+bool link::is_receiver() { return pn_link_is_receiver(pn_cast(this)); }
 
-int link::credit() {
-    return pn_link_credit(get());
+sender& link::sender() {
+    if (!is_sender()) throw error("link is not a sender");
+    return *reinterpret_cast<class sender*>(this);
 }
 
-terminus link::source() {
-    return terminus(pn_link_source(get()), get());
+receiver& link::receiver() {
+    if (!is_receiver()) throw error("link is not a receiver");
+    return *reinterpret_cast<class receiver*>(this);
 }
 
-terminus link::target() {
-    return terminus(pn_link_target(get()), get());
+int link::credit() {
+    return pn_link_credit(pn_cast(this));
 }
 
-terminus link::remote_source() {
-    return terminus(pn_link_remote_source(get()), get());
-}
+bool link::has_source() { return pn_link_source(pn_cast(this)); }
+bool link::has_target() { return pn_link_target(pn_cast(this)); }
+bool link::has_remote_source() { return pn_link_remote_source(pn_cast(this)); }
+bool link::has_remote_target() { return pn_link_remote_target(pn_cast(this)); }
 
-terminus link::remote_target() {
-    return terminus(pn_link_remote_target(get()), get());
-}
+terminus& link::source() { return *terminus::cast(pn_link_source(pn_cast(this))); }
+terminus& link::target() { return *terminus::cast(pn_link_target(pn_cast(this))); }
+terminus& link::remote_source() { return *terminus::cast(pn_link_remote_source(pn_cast(this))); }
+terminus& link::remote_target() { return *terminus::cast(pn_link_remote_target(pn_cast(this))); }
 
-std::string link::name() {
-    return std::string(pn_link_name(get()));
-}
+std::string link::name() { return std::string(pn_link_name(pn_cast(this)));}
 
 class connection &link::connection() {
-    pn_session_t *s = pn_link_session(get());
-    pn_connection_t *c = pn_session_connection(s);
-    return connection_impl::reactor_reference(c);
+    return *connection::cast(pn_session_connection(pn_link_session(pn_cast(this))));
 }
 
-link link::next(endpoint::state mask) {
-
-    return link(pn_link_next(get(), (pn_state_t) mask));
+link* link::next(endpoint::state mask) {
+    return link::cast(pn_link_next(pn_cast(this), (pn_state_t) mask));
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/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 2e1165d..2e6ce46 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -35,11 +35,9 @@
 
 namespace proton {
 
-message::message() : impl_(::pn_message()), body_(0) { assert(impl_); }
+void message::operator delete(void *p) { ::pn_message_free(reinterpret_cast<pn_message_t*>(p)); }
 
-message::message(pn_message_t *p) : impl_(p), body_(0) { assert(impl_); }
-
-message::message(const message& m) : impl_(::pn_message()), body_(0) { *this = m; }
+PN_UNIQUE_OR_AUTO_PTR<message> message::create() { return PN_UNIQUE_OR_AUTO_PTR<message>(cast(::pn_message())); }
 
 message& message::operator=(const message& m) {
     // TODO aconway 2015-08-10: need more efficient pn_message_copy function
@@ -49,148 +47,124 @@ message& message::operator=(const message& m) {
     return *this;
 }
 
-message::~message() { if (impl_) pn_message_free(impl_); }
-
-void message::clear() { pn_message_clear(impl_); }
+void message::clear() { pn_message_clear(pn_cast(this)); }
 
 namespace {
 void check(int err) {
     if (err) throw error(error_str(err));
 }
 
-void set_value(pn_data_t* d, const value& v) {
-    values values(d);
-    values.clear();
-    values << v;
-}
-
-value get_value(pn_data_t* d) {
-    if (d) {
-        values vals(d);
-        vals.rewind();
-        if (vals.more())
-            return vals.get<value>();
-    }
-    return value();
-}
 } // namespace
 
-void message::id(const value& id) {
-    set_value(pn_message_id(impl_), id);
-}
+void message::id(const data& id) { *data::cast(pn_message_id(pn_cast(this))) = id; }
+const data& message::id() const { return *data::cast(pn_message_id(pn_cast(this))); }
+data& message::id() { return *data::cast(pn_message_id(pn_cast(this))); }
 
-value message::id() const {
-    return get_value(pn_message_id(impl_));
-}
 void message::user(const std::string &id) {
-    check(pn_message_set_user_id(impl_, pn_bytes(id)));
+    check(pn_message_set_user_id(pn_cast(this), pn_bytes(id)));
 }
 
 std::string message::user() const {
-    return str(pn_message_get_user_id(impl_));
+    return str(pn_message_get_user_id(pn_cast(this)));
 }
 
 void message::address(const std::string &addr) {
-    check(pn_message_set_address(impl_, addr.c_str()));
+    check(pn_message_set_address(pn_cast(this), addr.c_str()));
 }
 
 std::string message::address() const {
-    const char* addr = pn_message_get_address(impl_);
+    const char* addr = pn_message_get_address(pn_cast(this));
     return addr ? std::string(addr) : std::string();
 }
 
 void message::subject(const std::string &s) {
-    check(pn_message_set_subject(impl_, s.c_str()));
+    check(pn_message_set_subject(pn_cast(this), s.c_str()));
 }
 
 std::string message::subject() const {
-    const char* s = pn_message_get_subject(impl_);
+    const char* s = pn_message_get_subject(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
 void message::reply_to(const std::string &s) {
-    check(pn_message_set_reply_to(impl_, s.c_str()));
+    check(pn_message_set_reply_to(pn_cast(this), s.c_str()));
 }
 
 std::string message::reply_to() const {
-    const char* s = pn_message_get_reply_to(impl_);
+    const char* s = pn_message_get_reply_to(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
-void message::correlation_id(const value& id) {
-    set_value(pn_message_correlation_id(impl_), id);
+void message::correlation_id(const data& id) {
+    *data::cast(pn_message_correlation_id(pn_cast(this))) = id;
 }
 
-value message::correlation_id() const {
-    return get_value(pn_message_correlation_id(impl_));
+const data& message::correlation_id() const {
+    return *data::cast(pn_message_correlation_id(pn_cast(this)));
+}
+
+data& message::correlation_id() {
+    return *data::cast(pn_message_correlation_id(pn_cast(this)));
 }
 
 void message::content_type(const std::string &s) {
-    check(pn_message_set_content_type(impl_, s.c_str()));
+    check(pn_message_set_content_type(pn_cast(this), s.c_str()));
 }
 
 std::string message::content_type() const {
-    const char* s = pn_message_get_content_type(impl_);
+    const char* s = pn_message_get_content_type(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
 void message::content_encoding(const std::string &s) {
-    check(pn_message_set_content_encoding(impl_, s.c_str()));
+    check(pn_message_set_content_encoding(pn_cast(this), s.c_str()));
 }
 
 std::string message::content_encoding() const {
-    const char* s = pn_message_get_content_encoding(impl_);
+    const char* s = pn_message_get_content_encoding(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
 void message::expiry(amqp_timestamp t) {
-    pn_message_set_expiry_time(impl_, t.milliseconds);
+    pn_message_set_expiry_time(pn_cast(this), t.milliseconds);
 }
 amqp_timestamp message::expiry() const {
-    return amqp_timestamp(pn_message_get_expiry_time(impl_));
+    return amqp_timestamp(pn_message_get_expiry_time(pn_cast(this)));
 }
 
 void message::creation_time(amqp_timestamp t) {
-    pn_message_set_creation_time(impl_, t);
+    pn_message_set_creation_time(pn_cast(this), t);
 }
 amqp_timestamp message::creation_time() const {
-    return pn_message_get_creation_time(impl_);
+    return pn_message_get_creation_time(pn_cast(this));
 }
 
 void message::group_id(const std::string &s) {
-    check(pn_message_set_group_id(impl_, s.c_str()));
+    check(pn_message_set_group_id(pn_cast(this), s.c_str()));
 }
 
 std::string message::group_id() const {
-    const char* s = pn_message_get_group_id(impl_);
+    const char* s = pn_message_get_group_id(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
 void message::reply_to_group_id(const std::string &s) {
-    check(pn_message_set_reply_to_group_id(impl_, s.c_str()));
+    check(pn_message_set_reply_to_group_id(pn_cast(this), s.c_str()));
 }
 
 std::string message::reply_to_group_id() const {
-    const char* s = pn_message_get_reply_to_group_id(impl_);
+    const char* s = pn_message_get_reply_to_group_id(pn_cast(this));
     return s ? std::string(s) : std::string();
 }
 
-void message::body(const value& v) {
-    set_value(pn_message_body(impl_), v);
-}
-
-void message::body(const values& v) {
-    pn_data_copy(pn_message_body(impl_), v.data_);
-}
+void message::body(const data& v) { body() = v; }
 
-const values& message::body() const {
-    body_.view(pn_message_body(impl_));
-    return body_;
+const data& message::body() const {
+    return *data::cast(pn_message_body(pn_cast(this)));
 }
 
-values& message::body() {
-    body_.view(pn_message_body(impl_));
-    return body_;
+data& message::body() {
+    return *data::cast(pn_message_body(pn_cast(this)));
 }
 
 void message::encode(std::string &s) const {
@@ -198,7 +172,7 @@ void message::encode(std::string &s) const {
     if (sz < 512) sz = 512;
     while (true) {
         s.resize(sz);
-        int err = pn_message_encode(impl_, (char *) s.data(), &sz);
+        int err = pn_message_encode(pn_cast(this), (char *) s.data(), &sz);
         if (err) {
             if (err != PN_OVERFLOW)
                 check(err);
@@ -217,25 +191,17 @@ std::string message::encode() const {
 }
 
 void message::decode(const std::string &s) {
-    check(pn_message_decode(impl_, s.data(), s.size()));
-}
-
-pn_message_t *message::get() { return impl_; }
-
-pn_message_t *message::release() {
-    pn_message_t *result = impl_;
-    impl_ = 0;
-    return result;
+    check(pn_message_decode(pn_cast(this), s.data(), s.size()));
 }
 
-void message::decode(proton::link link, proton::delivery delivery) {
+void message::decode(proton::link &link, proton::delivery &delivery) {
     std::string buf;
-    buf.resize(pn_delivery_pending(delivery.get()));
-    ssize_t n = pn_link_recv(link.get(), (char *) buf.data(), buf.size());
+    buf.resize(pn_delivery_pending(pn_cast(&delivery)));
+    ssize_t n = pn_link_recv(pn_cast(&link), (char *) buf.data(), buf.size());
     if (n != (ssize_t) buf.size()) throw error(MSG("link read failure"));
     clear();
     decode(buf);
-    pn_link_advance(link.get());
+    pn_link_advance(pn_cast(&link));
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/messaging_adapter.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_adapter.cpp b/proton-c/bindings/cpp/src/messaging_adapter.cpp
index 7a6ef77..9a66433 100644
--- a/proton-c/bindings/cpp/src/messaging_adapter.cpp
+++ b/proton-c/bindings/cpp/src/messaging_adapter.cpp
@@ -72,7 +72,7 @@ void messaging_adapter::on_delivery(event &e) {
             if (!pn_delivery_partial(dlv) && pn_delivery_readable(dlv)) {
                 // generate on_message
                 messaging_event mevent(messaging_event::MESSAGE, *pe);
-                mevent.message_.decode(link(lnk), delivery(dlv));
+                mevent.message_.decode(*reinterpret_cast<link*>(lnk), *reinterpret_cast<delivery*>(dlv));
                 if (pn_link_state(lnk) & PN_LOCAL_CLOSED) {
                     if (auto_accept_) {
                         pn_delivery_update(dlv, PN_RELEASED);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/messaging_event.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/messaging_event.cpp b/proton-c/bindings/cpp/src/messaging_event.cpp
index f302a3b..7befc25 100644
--- a/proton-c/bindings/cpp/src/messaging_event.cpp
+++ b/proton-c/bindings/cpp/src/messaging_event.cpp
@@ -58,7 +58,7 @@ connection &messaging_event::connection() {
     throw error(MSG("No connection context for event"));
 }
 
-sender messaging_event::sender() {
+sender& messaging_event::sender() {
     if (type_ == messaging_event::PROTON)
         return proton_event::sender();
     if (parent_event_)
@@ -66,7 +66,7 @@ sender messaging_event::sender() {
     throw error(MSG("No sender context for event"));
 }
 
-receiver messaging_event::receiver() {
+receiver& messaging_event::receiver() {
     if (type_ == messaging_event::PROTON)
         return proton_event::receiver();
     if (parent_event_)
@@ -74,7 +74,7 @@ receiver messaging_event::receiver() {
     throw error(MSG("No receiver context for event"));
 }
 
-link messaging_event::link() {
+link& messaging_event::link() {
     if (type_ == messaging_event::PROTON)
         return proton_event::link();
     if (parent_event_)
@@ -82,7 +82,7 @@ link messaging_event::link() {
     throw error(MSG("No link context for event"));
 }
 
-delivery messaging_event::delivery() {
+delivery& messaging_event::delivery() {
     if (type_ == messaging_event::PROTON)
         return proton_event::delivery();
     if (parent_event_)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/msg.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/msg.hpp b/proton-c/bindings/cpp/src/msg.hpp
index b5d2a51..66c01cb 100644
--- a/proton-c/bindings/cpp/src/msg.hpp
+++ b/proton-c/bindings/cpp/src/msg.hpp
@@ -27,7 +27,7 @@
 
 namespace proton {
 
-/** A simple wrapper for std::ostringstream that allows
+/** A simple facade for std::ostringstream that allows
  * in place construction of a message and automatic conversion
  * to string.
  * E.g.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/proton_event.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_event.cpp b/proton-c/bindings/cpp/src/proton_event.cpp
index 1c1788c..723fdaa 100644
--- a/proton-c/bindings/cpp/src/proton_event.cpp
+++ b/proton-c/bindings/cpp/src/proton_event.cpp
@@ -23,14 +23,14 @@
 #include "proton/event.h"
 #include "proton/link.h"
 
+#include "proton/container.hpp"
+#include "proton/delivery.hpp"
+#include "proton/error.hpp"
 #include "proton/proton_event.hpp"
 #include "proton/proton_handler.hpp"
-#include "proton/error.hpp"
-#include "proton/container.hpp"
-#include "proton/sender.hpp"
 #include "proton/receiver.hpp"
+#include "proton/sender.hpp"
 
-#include "connection_impl.hpp"
 #include "msg.hpp"
 #include "contexts.hpp"
 
@@ -52,44 +52,25 @@ connection &proton_event::connection() {
     pn_connection_t *conn = pn_event_connection(pn_event());
     if (!conn)
         throw error(MSG("No connection context for this event"));
-    return connection_impl::reactor_reference(conn);
+    return *connection::cast(conn);
 }
 
-sender proton_event::sender() {
-    pn_link_t *lnk = pn_event_link(pn_event());
-    if (lnk && pn_link_is_sender(lnk))
-        return proton::sender(lnk);
-    throw error(MSG("No sender context for this event"));
+link& proton_event::link() {
+    class link *lnk = link::cast(pn_event_link(pn_event()));
+    if (!lnk) throw error(MSG("No link context for this event"));
+    return *lnk;
 }
 
-receiver proton_event::receiver() {
-    pn_link_t *lnk = pn_event_link(pn_event());
-    if (lnk && pn_link_is_receiver(lnk))
-        return proton::receiver(lnk);
-    throw error(MSG("No receiver context for this event"));
-}
+sender& proton_event::sender() { return link().sender(); }
 
-link proton_event::link() {
-    pn_link_t *lnk = pn_event_link(pn_event());
-    if (lnk) {
-        if (pn_link_is_sender(lnk))
-            return proton::sender(lnk);
-        else
-            return proton::receiver(lnk);
-    }
-    throw error(MSG("No link context for this event"));
-}
+receiver& proton_event::receiver() { return link().receiver(); }
 
-delivery proton_event::delivery() {
-    pn_delivery_t *dlv = pn_event_delivery(pn_event());
-    if (dlv)
-        return proton::delivery(dlv);
-    throw error(MSG("No delivery context for this event"));
+delivery& proton_event::delivery() {
+    class delivery *dlv = delivery::cast(pn_event_delivery(pn_event()));
+    if (!dlv) throw error(MSG("No delivery context for this event"));
+    return *dlv;
 }
 
-
-
-
 void proton_event::dispatch(handler &h) {
     proton_handler *handler = dynamic_cast<proton_handler*>(&h);
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/receiver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/receiver.cpp b/proton-c/bindings/cpp/src/receiver.cpp
index 12f2c31..8d1fdbe 100644
--- a/proton-c/bindings/cpp/src/receiver.cpp
+++ b/proton-c/bindings/cpp/src/receiver.cpp
@@ -29,20 +29,8 @@
 
 namespace proton {
 
-namespace {
-
-pn_link_t* verify(pn_link_t* l) {
-    if (l && !link(l).is_receiver())
-        throw error(MSG("Creating receiver from sender link"));
-    return l;
-}
-
-}
-
-receiver::receiver(link lnk) : link(verify(lnk.get())) {}
-
 void receiver::flow(int count) {
-    pn_link_flow(get(), count);
+    pn_link_flow(pn_cast(this), count);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/sender.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sender.cpp b/proton-c/bindings/cpp/src/sender.cpp
index a8945b2..5c1d26f 100644
--- a/proton-c/bindings/cpp/src/sender.cpp
+++ b/proton-c/bindings/cpp/src/sender.cpp
@@ -37,33 +37,21 @@
 namespace proton {
 
 namespace {
-
-pn_link_t* verify(pn_link_t* l) {
-    if (l && !link(l).is_sender())
-        throw error(MSG("Creating sender from receiver link"));
-    return l;
-}
 // TODO: revisit if thread safety required
 std::uint64_t tag_counter = 0;
-
 }
 
-sender::sender(link lnk) : link(verify(lnk.get())) {}
-
-delivery sender::send(message &message) {
-    char tag[8];
-    void *ptr = &tag;
+delivery& sender::send(message &message) {
     std::uint64_t id = ++tag_counter;
-    *((std::uint64_t *) ptr) = id;
-    pn_delivery_t *dlv = pn_delivery(get(), pn_dtag(tag, 8));
+    pn_delivery_t *dlv =
+        pn_delivery(pn_cast(this), pn_dtag(reinterpret_cast<const char*>(&id), sizeof(id)));
     std::string buf;
     message.encode(buf);
-    pn_link_t *link = get();
-    pn_link_send(link, buf.data(), buf.size());
-    pn_link_advance(link);
-    if (pn_link_snd_settle_mode(link) == PN_SND_SETTLED)
+    pn_link_send(pn_cast(this), buf.data(), buf.size());
+    pn_link_advance(pn_cast(this));
+    if (pn_link_snd_settle_mode(pn_cast(this)) == PN_SND_SETTLED)
         pn_delivery_settle(dlv);
-    return delivery(dlv);
+    return *delivery::cast(dlv);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/session.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/session.cpp b/proton-c/bindings/cpp/src/session.cpp
index 9154975..43c0cd0 100644
--- a/proton-c/bindings/cpp/src/session.cpp
+++ b/proton-c/bindings/cpp/src/session.cpp
@@ -25,29 +25,23 @@
 #include "proton/session.h"
 #include "proton/session.hpp"
 #include "proton/connection.hpp"
-#include "connection_impl.hpp"
 
 namespace proton {
 
-session::session(pn_session_t *p) : wrapper<pn_session_t>(p) {}
-
 void session::open() {
-    pn_session_open(get());
+    pn_session_open(pn_cast(this));
 }
 
 connection &session::connection() {
-    pn_connection_t *c = pn_session_connection(get());
-    return connection_impl::reactor_reference(c);
+    return *proton::connection::cast(pn_session_connection(pn_cast(this)));
 }
 
-receiver session::create_receiver(const std::string& name) {
-    pn_link_t *link = pn_receiver(get(), name.c_str());
-    return receiver(link);
+receiver& session::create_receiver(const std::string& name) {
+    return *reinterpret_cast<receiver*>(pn_receiver(pn_cast(this), name.c_str()));
 }
 
-sender session::create_sender(const std::string& name) {
-    pn_link_t *link = pn_sender(get(), name.c_str());
-    return sender(link);
+sender& session::create_sender(const std::string& name) {
+    return *reinterpret_cast<sender*>(pn_sender(pn_cast(this), name.c_str()));
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/sync_request_response.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/sync_request_response.cpp b/proton-c/bindings/cpp/src/sync_request_response.cpp
index b20c3a3..5098a6f 100644
--- a/proton-c/bindings/cpp/src/sync_request_response.cpp
+++ b/proton-c/bindings/cpp/src/sync_request_response.cpp
@@ -29,9 +29,9 @@ namespace {
 amqp_ulong global_correlation_id = 0;
 
 struct response_received {
-    response_received(std::auto_ptr<message>& m, amqp_ulong id) : message_(m), id_(id) {}
+    response_received(PN_UNIQUE_OR_AUTO_PTR<message>& m, amqp_ulong id) : message_(m), id_(id) {}
     bool operator()() { return message_.get() && message_->correlation_id() == id_; }
-    std::auto_ptr<message>& message_;
+    PN_UNIQUE_OR_AUTO_PTR<message>& message_;
     value id_;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/terminus.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/terminus.cpp b/proton-c/bindings/cpp/src/terminus.cpp
index cff2fa5..2c960d6 100644
--- a/proton-c/bindings/cpp/src/terminus.cpp
+++ b/proton-c/bindings/cpp/src/terminus.cpp
@@ -24,47 +24,45 @@
 
 namespace proton {
 
-terminus::terminus(pn_terminus_t *p, pn_link_t* l) : wrapper<pn_terminus_t>(p), link_(l) {}
-
 terminus::type_t terminus::type() {
-    return (type_t) pn_terminus_get_type(get());
+    return (type_t) pn_terminus_get_type(pn_cast(this));
 }
 
 void terminus::type(type_t type) {
-    pn_terminus_set_type(get(), (pn_terminus_type_t) type);
+    pn_terminus_set_type(pn_cast(this), (pn_terminus_type_t) type);
 }
 
 terminus::expiry_policy_t terminus::expiry_policy() {
-    return (expiry_policy_t) pn_terminus_get_type(get());
+    return (expiry_policy_t) pn_terminus_get_type(pn_cast(this));
 }
 
 void terminus::expiry_policy(expiry_policy_t policy) {
-    pn_terminus_set_expiry_policy(get(), (pn_expiry_policy_t) policy);
+    pn_terminus_set_expiry_policy(pn_cast(this), (pn_expiry_policy_t) policy);
 }
 
 terminus::distribution_mode_t terminus::distribution_mode() {
-    return (distribution_mode_t) pn_terminus_get_type(get());
+    return (distribution_mode_t) pn_terminus_get_type(pn_cast(this));
 }
 
 void terminus::distribution_mode(distribution_mode_t mode) {
-    pn_terminus_set_distribution_mode(get(), (pn_distribution_mode_t) mode);
+    pn_terminus_set_distribution_mode(pn_cast(this), (pn_distribution_mode_t) mode);
 }
 
 std::string terminus::address() {
-    const char *addr = pn_terminus_get_address(get());
+    const char *addr = pn_terminus_get_address(pn_cast(this));
     return addr ? std::string(addr) : std::string();
 }
 
 void terminus::address(const std::string &addr) {
-    pn_terminus_set_address(get(), addr.c_str());
+    pn_terminus_set_address(pn_cast(this), addr.c_str());
 }
 
 bool terminus::is_dynamic() {
-    return (type_t) pn_terminus_is_dynamic(get());
+    return (type_t) pn_terminus_is_dynamic(pn_cast(this));
 }
 
 void terminus::dynamic(bool d) {
-    pn_terminus_set_dynamic(get(), d);
+    pn_terminus_set_dynamic(pn_cast(this), d);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/test_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/test_bits.hpp b/proton-c/bindings/cpp/src/test_bits.hpp
new file mode 100644
index 0000000..bd94b8e
--- /dev/null
+++ b/proton-c/bindings/cpp/src/test_bits.hpp
@@ -0,0 +1,48 @@
+#ifndef TEST_BITS_HPP
+#define TEST_BITS_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 <stdexcept>
+#include <iostream>
+#include "msg.hpp"
+
+namespace {
+
+struct fail : public std::logic_error { fail(const std::string& what) : logic_error(what) {} };
+#define FAIL(WHAT) throw fail(MSG(__FILE__ << ":" << __LINE__ << ": " << WHAT))
+#define ASSERT(TEST) do { if (!(TEST)) FAIL("assert failed: " << #TEST); } while(false)
+#define ASSERT_EQUAL(WANT, GOT) if ((WANT) != (GOT)) \
+        FAIL(#WANT << " !=  " << #GOT << ": " << WANT << " != " << GOT)
+
+int run_test(void (*testfn)(), const char* name) {
+    try {
+        testfn();
+        return 0;
+    } catch(const fail& e) {
+        std::cout << "FAIL " << name << std::endl << e.what();
+    } catch(const std::exception& e) {
+        std::cout << "ERROR " << name << std::endl << e.what();
+    }
+    return 1;
+}
+
+#define RUN_TEST(TEST) run_test(TEST, #TEST)
+}
+#endif // TEST_BITS_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/transport.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/transport.cpp b/proton-c/bindings/cpp/src/transport.cpp
index b386f7b..e128492 100644
--- a/proton-c/bindings/cpp/src/transport.cpp
+++ b/proton-c/bindings/cpp/src/transport.cpp
@@ -20,19 +20,12 @@
  */
 #include "proton/transport.hpp"
 #include "proton/connection.hpp"
-
 #include "proton/transport.h"
 
 namespace proton {
 
-
-transport::transport() : connection_(0), pn_transport_(::pn_transport()) {}
-
-transport::~transport() { ::pn_decref(pn_transport_); }
-
-void transport::bind(class connection &c) {
-    connection_ = &c;
-    pn_transport_bind(pn_transport_, c.pn_connection());
+connection* transport::connection() {
+    return connection::cast(pn_transport_connection(pn_cast(this)));
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/types.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/types.cpp b/proton-c/bindings/cpp/src/types.cpp
index dcebc6f..916e2fb 100644
--- a/proton-c/bindings/cpp/src/types.cpp
+++ b/proton-c/bindings/cpp/src/types.cpp
@@ -45,7 +45,7 @@ std::ostream& operator<<(std::ostream& o, const amqp_uuid& u) {
 
 std::string type_name(type_id t) {
     switch (t) {
-      case NULl_: return "null";
+      case NULL_: return "null";
       case BOOL: return "bool";
       case UBYTE: return "ubyte";
       case BYTE: return "byte";
@@ -91,6 +91,6 @@ start::start(type_id t, type_id e, bool d, size_t s) : type(t), element(e), is_d
 start start::array(type_id element, bool described) { return start(ARRAY, element, described); }
 start start::list() { return start(LIST); }
 start start::map() { return start(MAP); }
-start start::described() { return start(DESCRIBED, NULl_, true); }
+start start::described() { return start(DESCRIBED, NULL_, true); }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/value.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/value.cpp b/proton-c/bindings/cpp/src/value.cpp
deleted file mode 100644
index ff95e2e..0000000
--- a/proton-c/bindings/cpp/src/value.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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/value.hpp"
-#include "proton_bits.hpp"
-#include <proton/codec.h>
-#include <ostream>
-#include <algorithm>
-
-namespace proton {
-
-value::value() { *this = amqp_null(); }
-value::value(const value& v) { *this = v; }
-value::~value() {}
-
-value& value::operator=(const value& v) { values_ = v.values_; return *this; }
-
-type_id value::type() const {
-    const_cast<values&>(values_).rewind();
-    return values_.type();
-}
-
-namespace {
-template <class T> T check(T result) {
-    if (result < 0)
-        throw encode_error("encode: " + error_str(result));
-    return result;
-}
-}
-
-std::ostream& operator<<(std::ostream& o, const value& v) {
-    return o << v.values_;
-}
-
-namespace {
-
-// Compare nodes, return -1 if a<b, 0 if a==b, +1 if a>b
-// Forward-declare so we can use it recursively.
-int compare_next(values& a, values& b);
-
-template <class T> int compare(const T& a, const T& b) {
-    if (a < b) return -1;
-    else if (a > b) return +1;
-    else return 0;
-}
-
-int compare_container(values& a, values& b) {
-    decoder::scope sa(a), sb(b);
-    // Compare described vs. not-described.
-    int cmp = compare(sa.is_described, sb.is_described);
-    if (cmp) return cmp;
-    // Lexical sort (including descriptor if there is one)
-    size_t min_size = std::min(sa.size, sb.size) + int(sa.is_described);
-    for (size_t i = 0; i < min_size; ++i) {
-        cmp = compare_next(a, b);
-        if (cmp) return cmp;
-    }
-    return compare(sa.size, sb.size);
-}
-
-template <class T> int compare_simple(values& a, values& b) {
-    T va, vb;
-    a >> va;
-    b >> vb;
-    return compare(va, vb);
-}
-
-int compare_next(values& a, values& b) {
-    // Sort by type_id first.
-    type_id ta = a.type(), tb = b.type();
-    int cmp = compare(ta, tb);
-    if (cmp) return cmp;
-
-    switch (ta) {
-      case NULl_: return 0;
-      case ARRAY:
-      case LIST:
-      case MAP:
-      case DESCRIBED:
-        return compare_container(a, b);
-      case BOOL: return compare_simple<amqp_bool>(a, b);
-      case UBYTE: return compare_simple<amqp_ubyte>(a, b);
-      case BYTE: return compare_simple<amqp_byte>(a, b);
-      case USHORT: return compare_simple<amqp_ushort>(a, b);
-      case SHORT: return compare_simple<amqp_short>(a, b);
-      case UINT: return compare_simple<amqp_uint>(a, b);
-      case INT: return compare_simple<amqp_int>(a, b);
-      case CHAR: return compare_simple<amqp_char>(a, b);
-      case ULONG: return compare_simple<amqp_ulong>(a, b);
-      case LONG: return compare_simple<amqp_long>(a, b);
-      case TIMESTAMP: return compare_simple<amqp_timestamp>(a, b);
-      case FLOAT: return compare_simple<amqp_float>(a, b);
-      case DOUBLE: return compare_simple<amqp_double>(a, b);
-      case DECIMAL32: return compare_simple<amqp_decimal32>(a, b);
-      case DECIMAL64: return compare_simple<amqp_decimal64>(a, b);
-      case DECIMAL128: return compare_simple<amqp_decimal128>(a, b);
-      case UUID: return compare_simple<amqp_uuid>(a, b);
-      case BINARY: return compare_simple<amqp_binary>(a, b);
-      case STRING: return compare_simple<amqp_string>(a, b);
-      case SYMBOL: return compare_simple<amqp_symbol>(a, b);
-    }
-    // Invalid but equal type_id, treat as equal.
-    return 0;
-}
-
-} // namespace
-
-bool value::operator==(const value& v) const {
-    values_.rewind();
-    v.values_.rewind();
-    return compare_next(values_, v.values_) == 0;
-}
-
-bool value::operator<(const value& v) const {
-    values_.rewind();
-    v.values_.rewind();
-    return compare_next(values_, v.values_) < 0;
-}
-
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/values.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/values.cpp b/proton-c/bindings/cpp/src/values.cpp
deleted file mode 100644
index 4c8cda1..0000000
--- a/proton-c/bindings/cpp/src/values.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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/value.hpp"
-#include "proton_bits.hpp"
-#include <proton/codec.h>
-#include <ostream>
-
-namespace proton {
-
-values::values() {}
-values::values(const values& v) { *this = v; }
-values::values(pn_data_t* d) : data(d) {}
-
-values::~values() {}
-values& values::operator=(const values& v) { data::operator=(v); return *this; }
-
-std::ostream& operator<<(std::ostream& o, const values& v) {
-    return o << static_cast<const encoder&>(v);
-}
-
-}


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


Mime
View raw message