You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2015/08/31 19:32:57 UTC

[1/3] qpid-proton git commit: PROTON-865: 0-overhead facades, reference counting and smart ptr support.

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


[3/3] qpid-proton git commit: PROTON-865: 0-overhead facades, reference counting and smart ptr support.

Posted by ac...@apache.org.
PROTON-865: 0-overhead facades, reference counting and smart ptr support.

See proton/facade.hpp doc comments for details. The highlights:

- 0 overhead facade classes, facade pointers point directly at C structs.
- proton::counted_ptr for automated refcounting of proton objects in any C++ version.
- std:: and boost:: smart pointers supported as alternative to proton::counted_ptr.
- APIs take/return foo& for facade foo, facade can convert to smart pointer.

Tested with g++ and clang++ in c++03 and c++11 mode. Not tested on windows.

This is simpler and more obvious than the proposal floated on the proton list
but has essentially the same properties.


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

Branch: refs/heads/cjansen-cpp-client
Commit: 9bb9c442c3b83df249c2da7411ec74128f27e6b4
Parents: c696258
Author: Alan Conway <ac...@redhat.com>
Authored: Thu Aug 27 10:37:11 2015 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Mon Aug 31 13:32:45 2015 -0400

----------------------------------------------------------------------
 CMakeLists.txt                                  |   1 -
 docs/markdown/memory_management.md              | 113 ++++++++
 examples/cpp/CMakeLists.txt                     |   4 +-
 examples/cpp/broker.cpp                         |  40 ++-
 examples/cpp/client.cpp                         |  16 +-
 examples/cpp/direct_recv.cpp                    |   8 +-
 examples/cpp/direct_send.cpp                    |  10 +-
 examples/cpp/encode_decode.cpp                  | 146 +++++-----
 examples/cpp/example_test.py                    |  26 +-
 examples/cpp/helloworld.cpp                     |   6 +-
 examples/cpp/helloworld_blocking.cpp            |  11 +-
 examples/cpp/helloworld_direct.cpp              |   6 +-
 examples/cpp/server.cpp                         |  12 +-
 examples/cpp/server_direct.cpp                  |  15 +-
 examples/cpp/simple_recv.cpp                    |   7 +-
 examples/cpp/simple_send.cpp                    |   9 +-
 examples/cpp/sync_client.cpp                    |   6 +-
 proton-c/bindings/cpp/CMakeLists.txt            |  38 +--
 proton-c/bindings/cpp/docs/mainpage.md          |   2 +-
 proton-c/bindings/cpp/docs/tutorial.hpp         |   6 +-
 .../bindings/cpp/include/proton/acceptor.hpp    |   6 +-
 proton-c/bindings/cpp/include/proton/acking.hpp |  52 ----
 .../cpp/include/proton/blocking_connection.hpp  |   8 +-
 .../cpp/include/proton/blocking_link.hpp        |   1 -
 .../cpp/include/proton/blocking_sender.hpp      |   3 +-
 .../bindings/cpp/include/proton/comparable.hpp  |  44 ++++
 proton-c/bindings/cpp/include/proton/config.hpp |  27 +-
 .../bindings/cpp/include/proton/connection.hpp  |  35 +--
 .../bindings/cpp/include/proton/container.hpp   |  42 ++-
 .../bindings/cpp/include/proton/cstdint.hpp     |   4 +-
 proton-c/bindings/cpp/include/proton/data.hpp   | 103 ++++++--
 .../bindings/cpp/include/proton/decoder.hpp     |  24 +-
 .../bindings/cpp/include/proton/delivery.hpp    |  23 +-
 .../bindings/cpp/include/proton/encoder.hpp     |  24 +-
 .../bindings/cpp/include/proton/endpoint.hpp    |   4 -
 proton-c/bindings/cpp/include/proton/event.hpp  |  12 +-
 proton-c/bindings/cpp/include/proton/export.hpp |   3 +-
 proton-c/bindings/cpp/include/proton/facade.hpp | 263 +++++++++++++++++++
 proton-c/bindings/cpp/include/proton/handle.hpp |  66 -----
 .../bindings/cpp/include/proton/handler.hpp     |  10 +-
 proton-c/bindings/cpp/include/proton/link.hpp   |  54 ++--
 .../bindings/cpp/include/proton/message.hpp     | 167 ++++++++----
 .../cpp/include/proton/messaging_adapter.hpp    |   2 +-
 .../cpp/include/proton/messaging_event.hpp      |  12 +-
 .../cpp/include/proton/messaging_handler.hpp    |   3 +-
 .../cpp/include/proton/proton_event.hpp         |   8 +-
 .../bindings/cpp/include/proton/receiver.hpp    |   5 +-
 proton-c/bindings/cpp/include/proton/sender.hpp |   7 +-
 .../bindings/cpp/include/proton/session.hpp     |  12 +-
 .../include/proton/sync_request_response.hpp    |   3 +-
 .../bindings/cpp/include/proton/terminus.hpp    |   8 +-
 .../bindings/cpp/include/proton/transport.hpp   |  22 +-
 .../bindings/cpp/include/proton/type_traits.hpp |   5 +-
 proton-c/bindings/cpp/include/proton/types.hpp  |  19 +-
 proton-c/bindings/cpp/include/proton/url.hpp    |  10 +-
 proton-c/bindings/cpp/include/proton/value.hpp  |  94 -------
 proton-c/bindings/cpp/include/proton/values.hpp |  53 ----
 .../bindings/cpp/include/proton/wrapper.hpp     |  67 -----
 proton-c/bindings/cpp/src/acceptor.cpp          |   4 +-
 proton-c/bindings/cpp/src/acking.cpp            |  48 ----
 .../bindings/cpp/src/blocking_connection.cpp    |   8 +-
 .../cpp/src/blocking_connection_impl.hpp        |   2 +-
 proton-c/bindings/cpp/src/blocking_link.cpp     |   8 +-
 proton-c/bindings/cpp/src/blocking_receiver.cpp |   8 +-
 proton-c/bindings/cpp/src/blocking_sender.cpp   |  10 +-
 proton-c/bindings/cpp/src/connection.cpp        |  62 +++--
 proton-c/bindings/cpp/src/connection_impl.cpp   | 140 ----------
 proton-c/bindings/cpp/src/connection_impl.hpp   |  74 ------
 proton-c/bindings/cpp/src/connector.cpp         |  17 +-
 proton-c/bindings/cpp/src/connector.hpp         |   3 +-
 proton-c/bindings/cpp/src/container.cpp         |  31 +--
 proton-c/bindings/cpp/src/container_impl.cpp    | 112 +++-----
 proton-c/bindings/cpp/src/container_impl.hpp    |  21 +-
 proton-c/bindings/cpp/src/contexts.cpp          |  80 ++++--
 proton-c/bindings/cpp/src/contexts.hpp          |  28 +-
 proton-c/bindings/cpp/src/conversion_test.cpp   |  83 ++++++
 proton-c/bindings/cpp/src/data.cpp              | 126 +++++++--
 proton-c/bindings/cpp/src/decoder.cpp           | 200 +++++++-------
 proton-c/bindings/cpp/src/delivery.cpp          |  11 +-
 proton-c/bindings/cpp/src/encoder.cpp           |  85 +++---
 proton-c/bindings/cpp/src/endpoint.cpp          |   4 -
 proton-c/bindings/cpp/src/event.cpp             |  17 +-
 proton-c/bindings/cpp/src/facade.cpp            |  77 ++++++
 proton-c/bindings/cpp/src/fetcher.cpp           |  16 +-
 proton-c/bindings/cpp/src/fetcher.hpp           |   4 +-
 proton-c/bindings/cpp/src/interop_test.cpp      |  46 +---
 proton-c/bindings/cpp/src/link.cpp              |  55 ++--
 proton-c/bindings/cpp/src/message.cpp           | 124 ++++-----
 proton-c/bindings/cpp/src/messaging_adapter.cpp |   2 +-
 proton-c/bindings/cpp/src/messaging_event.cpp   |   8 +-
 proton-c/bindings/cpp/src/msg.hpp               |   2 +-
 proton-c/bindings/cpp/src/proton_event.cpp      |  49 ++--
 proton-c/bindings/cpp/src/receiver.cpp          |  14 +-
 proton-c/bindings/cpp/src/sender.cpp            |  26 +-
 proton-c/bindings/cpp/src/session.cpp           |  18 +-
 .../bindings/cpp/src/sync_request_response.cpp  |   4 +-
 proton-c/bindings/cpp/src/terminus.cpp          |  22 +-
 proton-c/bindings/cpp/src/test_bits.hpp         |  48 ++++
 proton-c/bindings/cpp/src/transport.cpp         |  11 +-
 proton-c/bindings/cpp/src/types.cpp             |   4 +-
 proton-c/bindings/cpp/src/value.cpp             | 136 ----------
 proton-c/bindings/cpp/src/values.cpp            |  38 ---
 102 files changed, 1799 insertions(+), 1874 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 209f18d..0b30ad0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,7 +151,6 @@ if (ENABLE_VALGRIND)
 endif (ENABLE_VALGRIND)
 
 mark_as_advanced (VALGRIND_EXE)
-message("FIXME VG ${VALGRIND_ENV}")
 
 add_subdirectory(proton-c)
 add_subdirectory(examples)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/docs/markdown/memory_management.md
----------------------------------------------------------------------
diff --git a/docs/markdown/memory_management.md b/docs/markdown/memory_management.md
new file mode 100644
index 0000000..5a70911
--- /dev/null
+++ b/docs/markdown/memory_management.md
@@ -0,0 +1,113 @@
+Proton memory mangement
+=======================
+
+Proton is a collection of libraries in different programming langauges. Some of
+the libraries (e.g. C and Java) are written directly in those langauges. Some
+(e.g. python and ruby) are "bindings", native libraries that that internally use
+the C library. All the libraries provide a "native" memory management
+experience, you don't need to know anything about C or the proton C library to
+use them.
+
+If you only program in java, python, ruby or a similar garbage-collected
+language then you may be wondering "what is *memory management*?"  Don't worry,
+the proton library takes care of it. However, as usual, you are responsible for
+some non-memory *resource* management. For example if you fail to `close()` a
+proton connection there won't be memory leaks but the remote end will get a rude
+"connection failed" error instead of an orderly connection close.
+
+If you are a C programmer, you are probably rolling your eyes and wondering why
+the kids these days expect their memory to be managed for them. Don't worry, the
+C API offers the standard C experience: you must call `pn_X_free` on a `pn_X_t*`
+when the time is right and you must know when a `pn_X_t*` can become invalid as
+a side effect of some other call. Read the doc, learn the rules and get it
+right. You are a C programmer!
+
+If you are a modern C++11 programmer and always use `shared_ptr` and
+`unique_ptr` to write leak-safe code, then the C++ binding is leak-safe. If you
+are stuck on C++03, the binding supports `boost::shared_ptr` and
+`boost::intrusive_ptr`. If you cannot even use boost, the binding provides a
+simple (type safe, intrusive) smart pointer of its own which can help you.
+
+If you are a Go programmer, you know that Go takes care of *Go-allocated* memory
+but you are responsible other resource cleanup, e.g. closing connections.  Go
+does not have object-scoped cleanup (or indeed objects) but as a crafty Go
+programmer you know that function-scoped cleanup is all you really need, and
+`defer` is your friend. The Go binding internally starts goroutines and
+allocates memory that is not tracked by Go, so proper cleanup is important (but
+you knew that.)
+
+Proton reference counting in C
+------------------------------
+
+Internally, the proton C library uses reference counting, and you can
+*optionally* use it in your code. You should choose *either* reference counting
+*or* `pn_X_free` in your code, *not both*. It might work, but it is the sort of
+Bad Idea that might break your code in the future and will hurt your head in the
+present. `pn_X_free` is all you really need to write an AMQP application in C.
+
+However, proton is designed to be embedded and integrated. If you are
+integrating proton with a new programming language, or some other kind of
+framwork, reference counts may be useful. If your integration target has some
+form of automatic clean-up *and* some way for you to hook into it (finalizers,
+destructors or the like) then reference counts may help (e.g. python, ruby and
+C++). As a counter-example the Go langauge *is* garbage collected but does *not*
+have finalizers, and the Go binding does *not* use reference counts, it is
+written like a "normal" C application with `pn_X_free`.
+
+If you are mixing your own C code with code using a reference-counted proton
+binding (e.g. C++ or python) then you may need to at least be aware of reference
+counting.
+
+You can even use reference counts in plain C code if you find that helpful (I
+don't see how it would be but you never know.)
+
+The proton C API has standard reference counting rules (but see [1] below)
+
+- A pointer *returned* by a `pn_` function is either *borrowed* by the caller,
+  or the caller *owns* a reference (the API doc says which.)
+- The owner of a reference must call `pn_decref()` exactly once to
+  release it.
+- To keep a borrowed pointer, call `pn_incref()`. This adds a new
+  reference, which you now own.
+- A pointer *passed* to a `pn_` function has no change of ownership. If you
+  owned a reference you still do, if you didn't you still don't.
+- An object is never freed while there are still references to it.
+- An object is freed when all references to it are released.
+
+A *borrowed* pointer is valid within some scope (typically the scope of an event
+handling function) but beyond that scope you cannot assume it is valid unless
+you make a new reference with `pn_incref`. The API documentation for the
+function that returned the pointer should tell you what the scope is.
+
+There are "container" relationships in proton: e.g. a connection contains
+sessions, a session contains links. Containers hold a reference to their
+contents. Freeing a container *releases* that reference. For example freeing a
+connection releases its sessions.
+
+If you don't use reference counts, then freeing a container *frees* the contents
+in traditional C style. However if you add a reference to a contained object it
+will *not* be freed till you release your reference, even if all references to
+container are released [1]. This is useful for bindings to langauges with
+"finalizers" or "destructors". You can use reference counts to "pin" proton C
+objects in memory for as long as any binding object needs them.
+
+For example: if you call `pn_message()` then you *own* a reference to the
+newly-created `pn_message_t` and you must call `pn_decref` when you are
+done [2]. If you call `pn_event_link()` in an event handler then you get a
+*borrowed* reference to the link. You can use it in the scope of the event
+handler, but if you want to save it for later you must call `pn_incref`
+to add a reference and of course call `pn_decref` when you are done with
+that reference.
+
+[1] *Internally* the proton library plays tricks with reference counts to
+implement 'weak' pointers and manage circular containment relationships. You do
+*not* need to understand this to use proton, even if you are writing bindings or
+doing funky mixed-language development. However if you are working on the
+implementation of the proton C library itself you may need to learn more, ask on
+proton@qpid.apache.org.
+
+[2] Actually if you call `pn_message()` then you must *either* call
+`pn_decref()` *or* `pn_message_free()`, definitely not both. It is
+possible to mix reference couting and 'free' style memory management in the same
+codebase (`free` is sort-of an alias for `decref`) but it is probably not a good
+idea.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt
index 77ab816..40925f9 100644
--- a/examples/cpp/CMakeLists.txt
+++ b/examples/cpp/CMakeLists.txt
@@ -24,13 +24,13 @@ include_directories(
 foreach(example
     broker
     helloworld
-    helloworld_blocking
+    # helloworld_blocking
     helloworld_direct
     simple_recv
     simple_send
     direct_recv
     direct_send
-    sync_client
+    # sync_client
     client
     server
     server_direct

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/broker.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp
index a57fff9..7752645 100644
--- a/examples/cpp/broker.cpp
+++ b/examples/cpp/broker.cpp
@@ -35,8 +35,8 @@
 class queue {
   public:
     bool dynamic;
-    typedef std::deque<proton::message> message_queue;
-    typedef std::list<proton::sender> sender_list;
+    typedef std::deque<proton::message_value> message_queue;
+    typedef std::list<proton::counted_ptr<proton::sender> > sender_list;
     message_queue messages;
     sender_list consumers;
 
@@ -51,14 +51,13 @@ class queue {
         return (consumers.size() == 0 && (dynamic || messages.size() == 0));
     }
 
-    void publish(proton::message &m) {
+    void publish(const proton::message_value &m) {
         messages.push_back(m);
         dispatch(0);
     }
 
     void dispatch(proton::sender *s) {
-        while (deliver_to(s)) {
-        }
+        while (deliver_to(s)) {}
     }
 
     bool deliver_to(proton::sender *consumer) {
@@ -67,7 +66,8 @@ class queue {
         if (!count) return false;
         bool result = false;
         sender_list::iterator it = consumers.begin();
-        if (!consumer && count) consumer = &*it;
+        if (!consumer && count)
+            consumer = it->get();
 
         while (messages.size()) {
             if (consumer->credit()) {
@@ -118,10 +118,10 @@ class broker : public proton::messaging_handler {
     }
 
     void on_link_opening(proton::event &e) {
-        proton::link lnk = e.link();
+        proton::link& lnk = e.link();
         if (lnk.is_sender()) {
-            proton::sender sender(lnk);
-            proton::terminus remote_source(lnk.remote_source());
+            proton::sender &sender(lnk.sender());
+            proton::terminus &remote_source(lnk.remote_source());
             if (remote_source.is_dynamic()) {
                 std::string address = queue_name();
                 lnk.source().address(address);
@@ -157,10 +157,9 @@ class broker : public proton::messaging_handler {
     }
 
     void on_link_closing(proton::event &e) {
-        proton::link lnk = e.link();
+        proton::link &lnk = e.link();
         if (lnk.is_sender()) {
-            proton::sender s(lnk);
-            unsubscribe(s);
+            unsubscribe(lnk.sender());
         }
     }
 
@@ -173,26 +172,25 @@ class broker : public proton::messaging_handler {
     }
 
     void remove_stale_consumers(proton::connection &connection) {
-        proton::link l = connection.link_head(proton::endpoint::REMOTE_ACTIVE);
+        proton::link *l = connection.link_head(proton::endpoint::REMOTE_ACTIVE);
         while (l) {
-            if (l.is_sender()) {
-                proton::sender s(l);
-                unsubscribe(s);
+            if (l->is_sender()) {
+                unsubscribe(l->sender());
             }
-            l = l.next(proton::endpoint::REMOTE_ACTIVE);
+            l = l->next(proton::endpoint::REMOTE_ACTIVE);
         }
     }
 
     void on_sendable(proton::event &e) {
-        proton::link lnk = e.link();
-        proton::sender sender(lnk);
+        proton::link& lnk = e.link();
         std::string addr = lnk.source().address();
-        get_queue(addr).dispatch(&sender);
+        proton::sender &s(lnk.sender());
+        get_queue(addr).dispatch(&s);
     }
 
     void on_message(proton::event &e) {
         std::string addr = e.link().target().address();
-        proton::message msg = e.message();
+        proton::message_value msg = e.message();
         get_queue(addr).publish(msg);
     }
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp
index 4c34ce7..e58311a 100644
--- a/examples/cpp/client.cpp
+++ b/examples/cpp/client.cpp
@@ -33,8 +33,8 @@ class client : public proton::messaging_handler {
   private:
     proton::url url;
     std::vector<std::string> requests;
-    proton::sender sender;
-    proton::receiver receiver;
+    proton::counted_ptr<proton::sender> sender;
+    proton::counted_ptr<proton::receiver> receiver;
 
   public:
     client(const proton::url &u, const std::vector<std::string>& r) : url(u), requests(r) {}
@@ -42,24 +42,24 @@ class client : public proton::messaging_handler {
     void on_start(proton::event &e) {
         sender = e.container().create_sender(url);
         // Create a receiver with a dynamically chosen unique address.
-        receiver = e.container().create_receiver(sender.connection(), "", true/*dynamic*/);
+        receiver = e.container().create_receiver(sender->connection(), "", true/*dynamic*/);
     }
 
     void send_request() {
-        proton::message req;
+        proton::message_value req;
         req.body(requests.front());
-        req.reply_to(receiver.remote_source().address());
-        sender.send(req);
+        req.reply_to(receiver->remote_source().address());
+        sender->send(req);
     }
 
     void on_link_opened(proton::event &e) {
-        if (e.link() == receiver) 
+        if (&e.link() == receiver.get()) 
             send_request();
     }
 
     void on_message(proton::event &e) {
         if (requests.empty()) return; // Spurious extra message!
-        proton::message response = e.message();
+        proton::message& response = e.message();
         std::cout << '"' << requests.front() << '"' << " => " << response.body() << std::endl;
         requests.erase(requests.begin());
         if (!requests.empty()) {

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/direct_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/direct_recv.cpp b/examples/cpp/direct_recv.cpp
index 9eead92..94cc943 100644
--- a/examples/cpp/direct_recv.cpp
+++ b/examples/cpp/direct_recv.cpp
@@ -37,7 +37,7 @@ class direct_recv : public proton::messaging_handler {
     proton::url url;
     int expected;
     int received;
-    proton::acceptor acceptor;
+    proton::counted_ptr<proton::acceptor> acceptor;
 
   public:
     direct_recv(const std::string &s, int c) : url(s), expected(c), received(0) {}
@@ -48,8 +48,8 @@ class direct_recv : public proton::messaging_handler {
     }
 
     void on_message(proton::event &e) {
-        proton::message msg = e.message();
-        proton::value id = msg.id();
+        proton::message& msg = e.message();
+        proton::data_value id = msg.id();
         if (id.type() == proton::ULONG) {
             if (id.get<int>() < received)
                 return; // ignore duplicate
@@ -61,7 +61,7 @@ class direct_recv : public proton::messaging_handler {
         if (received == expected) {
             e.receiver().close();
             e.connection().close();
-            if (acceptor) acceptor.close();
+            if (acceptor) acceptor->close();
         }
     }
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/direct_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/direct_send.cpp b/examples/cpp/direct_send.cpp
index a4e572c..1302ac7 100644
--- a/examples/cpp/direct_send.cpp
+++ b/examples/cpp/direct_send.cpp
@@ -39,7 +39,7 @@ class simple_send : public proton::messaging_handler {
     int sent;
     int confirmed;
     int total;
-    proton::acceptor acceptor;
+    proton::counted_ptr<proton::acceptor> acceptor;
   public:
 
     simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {}
@@ -50,10 +50,10 @@ class simple_send : public proton::messaging_handler {
     }
 
     void on_sendable(proton::event &e) {
-        proton::sender sender = e.sender();
+        proton::sender& sender = e.sender();
         while (sender.credit() && sent < total) {
-            proton::message msg;
-            msg.id(proton::value(sent + 1));
+            proton::message_value msg;
+            msg.id(proton::data_value(sent + 1));
             std::map<std::string, int> m;
             m["sequence"] = sent+1;
             msg.body(proton::as<proton::MAP>(m));
@@ -67,7 +67,7 @@ class simple_send : public proton::messaging_handler {
         if (confirmed == total) {
             std::cout << "all messages confirmed" << std::endl;
             e.connection().close();
-            acceptor.close();
+            acceptor->close();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/encode_decode.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/encode_decode.cpp b/examples/cpp/encode_decode.cpp
index ea0f471..5657e73 100644
--- a/examples/cpp/encode_decode.cpp
+++ b/examples/cpp/encode_decode.cpp
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-#include <proton/value.hpp>
+#include <proton/data.hpp>
 #include <algorithm>
 #include <iostream>
 #include <iterator>
@@ -32,55 +32,55 @@ using namespace std;
 
 // Print is defined at the end as an example of how to query and extract complex
 // values in terms of their simple components.
-void print(proton::values& values);
+void print(proton::data&);
 
 // Inserting and extracting simple C++ values.
 void simple_insert_extract() {
-    proton::values vv;
     cout << endl << "== Simple values: int, string, bool" << endl;
-    vv << 42 << "foo" << true;
-    print(vv);
+    proton::data_value dv;
+    dv.encoder() << 42 << "foo" << true;
+    print(dv);
     int i;
     string s;
     bool b;
-    vv.rewind();
-    vv >> i >> s >> b;
+    dv.decoder().rewind();
+    dv.decoder() >> i >> s >> b;
     cout << "Extracted: " << i << ", " << s << ", " << b << endl;
     // Encode and decode as AMQP
-    string amqp_data = vv.encode();
+    string amqp_data = dv.encoder().encode();
     cout << "Encoded as AMQP in " << amqp_data.size() << " bytes" << endl;
-    proton::values vv2;
-    vv2.decode(amqp_data);
-    vv2 >> i >> s >> b;
+    proton::data_value  dt2;
+    dt2.decoder().decode(amqp_data);
+    dt2.decoder() >> i >> s >> b;
     cout << "Decoded: " << i << ", " << s << ", " << b << endl;
 }
 
 // Inserting values as a specific AMQP type
 void simple_insert_extract_exact_type() {
-    proton::values vv;
+    proton::data_value dv;
     cout << endl << "== Specific AMQP types: byte, long, symbol" << endl;
-    vv << proton::amqp_byte('x') << proton::amqp_long(123456789123456789) << proton::amqp_symbol("bar");
-    print(vv);
-    vv.rewind();
+    dv.encoder() << proton::amqp_byte('x') << proton::amqp_long(123456789123456789) << proton::amqp_symbol("bar");
+    print(dv);
+    dv.decoder().rewind();
     // Check that we encoded the correct types, but note that decoding will
     // still convert to standard C++ types, in particular any AMQP integer type
     // can be converted to a long-enough C++ integer type..
     int64_t i1, i2;
     string s;
-    vv >> i1 >> i2 >> s;
+    dv.decoder() >> i1 >> i2 >> s;
     cout << "Extracted (with conversion) " << i1 << ", " << i2 << ", " << s << endl;
 
     // Now use the as() function to fail unless we extract the exact AMQP type expected.
-    vv.rewind();            // amqp_byte(1) << amqp_long(2) << amqp_symbol("bar");
+    dv.decoder().rewind(); // amqp_byte(1) << amqp_long(2) << amqp_symbol("bar");
     proton::amqp_long l;
     // Fails, extracting amqp_byte as amqp_long
-    try { vv >> proton::as<proton::LONG>(l); throw logic_error("expected error"); } catch (proton::decode_error) {}
+    try { dv.decoder() >> proton::as<proton::LONG>(l); throw logic_error("expected error"); } catch (proton::decode_error) {}
     proton::amqp_byte b;
-    vv >> proton::as<proton::BYTE>(b) >> proton::as<proton::LONG>(l); // OK, extract amqp_byte as amqp_byte, amqp_long as amqp_long.
+    dv.decoder() >> proton::as<proton::BYTE>(b) >> proton::as<proton::LONG>(l); // OK, extract amqp_byte as amqp_byte, amqp_long as amqp_long.
     string str;
     // Fails, extracting amqp_symbol as amqp_string.
-    try { vv >> proton::as<proton::STRING>(str); throw logic_error("expected error"); } catch (proton::decode_error) {}
-    vv >> proton::as<proton::SYMBOL>(str);       // OK, extract amqp_symbol as amqp_symbol
+    try { dv.decoder() >> proton::as<proton::STRING>(str); throw logic_error("expected error"); } catch (proton::decode_error) {}
+    dv.decoder() >> proton::as<proton::SYMBOL>(str);       // OK, extract amqp_symbol as amqp_symbol
     cout << "Extracted (exact) " << b << ", " << l << ", " << str << endl;
 }
 
@@ -118,54 +118,54 @@ void insert_extract_containers() {
     m["one"] = 1;
     m["two"] = 2;
 
-    proton::values vv;
-    vv << proton::as<proton::ARRAY>(a) << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
-    print(vv);
+    proton::data_value dv;
+    dv.encoder() << proton::as<proton::ARRAY>(a) << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
+    print(dv);
 
     vector<int> a1, l1;
     map<string, int> m1;
-    vv.rewind();
-    vv >> proton::as<proton::ARRAY>(a1) >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
+    dv.decoder().rewind();
+    dv.decoder() >> proton::as<proton::ARRAY>(a1) >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
     cout << "Extracted: " << a1 << ", " << l1 << ", " << m1 << endl;
 }
 
 // Containers with mixed types, use value to represent arbitrary AMQP types.
 void mixed_containers() {
     cout << endl << "== List and map of mixed type values." << endl;
-    vector<proton::value> l;
-    l.push_back(proton::value(42));
-    l.push_back(proton::value(proton::amqp_string("foo")));
-    map<proton::value, proton::value> m;
-    m[proton::value("five")] = proton::value(5);
-    m[proton::value(4)] = proton::value("four");
-    proton::values vv;
-    vv << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
-    print(vv);
+    vector<proton::data_value> l;
+    l.push_back(proton::data_value(42));
+    l.push_back(proton::data_value(proton::amqp_string("foo")));
+    map<proton::data_value, proton::data_value> m;
+    m[proton::data_value("five")] = proton::data_value(5);
+    m[proton::data_value(4)] = proton::data_value("four");
+    proton::data_value dv;
+    dv.encoder() << proton::as<proton::LIST>(l) << proton::as<proton::MAP>(m);
+    print(dv);
 
-    vector<proton::value> l1;
-    map<proton::value, proton::value> m1;
-    vv.rewind();
-    vv >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
+    vector<proton::data_value> l1;
+    map<proton::data_value, proton::data_value> m1;
+    dv.decoder().rewind();
+    dv.decoder() >> proton::as<proton::LIST>(l1) >> proton::as<proton::MAP>(m1);
     cout << "Extracted: " << l1 << ", " << m1 << endl;
 }
 
 // Insert using stream operators (see print_next for example of extracting with stream ops.)
 void insert_extract_stream_operators() {
     cout << endl << "== Insert with stream operators." << endl;
-    proton::values vv;
+    proton::data_value dv;
     // Note: array elements must be encoded with the exact type, they are not
     // automaticlly converted. Mismatched types for array elements will not
-    // be detected until vv.encode() is called.
-    vv << proton::start::array(proton::INT) << proton::amqp_int(1) << proton::amqp_int(2) << proton::amqp_int(3) << proton::finish();
-    print(vv);
+    // be detected until dv.encode() is called.
+    dv.encoder() << proton::start::array(proton::INT) << proton::amqp_int(1) << proton::amqp_int(2) << proton::amqp_int(3) << proton::finish();
+    print(dv);
 
-    vv.clear();
-    vv << proton::start::list() << proton::amqp_int(42) << false << proton::amqp_symbol("x") << proton::finish();
-    print(vv);
+    dv.clear();
+    dv.encoder() << proton::start::list() << proton::amqp_int(42) << false << proton::amqp_symbol("x") << proton::finish();
+    print(dv);
 
-    vv.clear();
-    vv << proton::start::map() << "k1" << proton::amqp_int(42) << proton::amqp_symbol("k2") << false << proton::finish();
-    print(vv);
+    dv.clear();
+    dv.encoder() << proton::start::map() << "k1" << proton::amqp_int(42) << proton::amqp_symbol("k2") << false << proton::finish();
+    print(dv);
 }
 
 int main(int, char**) {
@@ -187,75 +187,75 @@ int main(int, char**) {
 // NOTE this is for example puroses only: There is a built in ostream operator<< for values.
 //
 //
-void print_next(proton::values& vv) {
-    proton::type_id type = vv.type();
+void print_next(proton::data& dv) {
+    proton::type_id type = dv.type();
     proton::start s;
     switch (type) {
       case proton::ARRAY: {
-          vv >> s;
+          dv.decoder() >> s;
           cout << "array<" << s.element;
           if (s.is_described) {
               cout  << ", descriptor=";
-              print_next(vv);
+              print_next(dv);
           }
           cout << ">[";
           for (size_t i = 0; i < s.size; ++i) {
               if (i) cout << ", ";
-              print_next(vv);
+              print_next(dv);
           }
           cout << "]";
-          vv >> proton::finish();
+          dv.decoder() >> proton::finish();
           break;
       }
       case proton::LIST: {
-          vv >> s;
+          dv.decoder() >> s;
           cout << "list[";
           for (size_t i = 0; i < s.size; ++i) {
               if (i) cout << ", ";
-              print_next(vv);
+              print_next(dv);
           }
           cout << "]";
-          vv >> proton::finish();
+          dv.decoder() >> proton::finish();
           break;
       }
       case proton::MAP: {
-          vv >> s;
+          dv.decoder() >> s;
           cout << "map{";
           for (size_t i = 0; i < s.size/2; ++i) {
               if (i) cout << ", ";
-              print_next(vv);
+              print_next(dv);
               cout << ":";        // key:value
-              print_next(vv);
+              print_next(dv);
           }
           cout << "}";
-          vv >> proton::finish();
+          dv.decoder() >> proton::finish();
           break;
       }
       case proton::DESCRIBED: {
-          vv >> s;
+          dv.decoder() >> s;
           cout << "described(";
-          print_next(vv);      // Descriptor
-          print_next(vv);      // value
-          vv >> proton::finish();
+          print_next(dv);      // Descriptor
+          print_next(dv);      // value
+          dv.decoder() >> proton::finish();
           break;
       }
       default:
         // A simple type. We could continue the switch for all AMQP types but
         // instead we us the `value` type which can hold and print any AMQP
         // value.
-        proton::value v;
-        vv >> v;
+        proton::data_value v;
+        dv.decoder() >> v;
         cout << type << "(" << v << ")";
     }
 }
 
 // Print all the values with print_next
-void print(proton::values& vv) {
-    vv.rewind();
+void print(proton::data& dv) {
+    dv.decoder().rewind();
     cout << "Values: ";
-    while (vv.more()) {
-        print_next(vv);
-        if (vv.more()) cout << ", ";
+    while (dv.decoder().more()) {
+        print_next(dv);
+        if (dv.decoder().more()) cout << ", ";
     }
     cout << endl;
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/example_test.py
----------------------------------------------------------------------
diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py
index f244516..5059678 100644
--- a/examples/cpp/example_test.py
+++ b/examples/cpp/example_test.py
@@ -78,7 +78,7 @@ def wait_addr(addr, timeout=10):
 
 def pick_addr():
     """Pick a new host:port address."""
-    # FIXME aconway 2015-07-14: need a safer way to pick ports.
+    # TODO aconway 2015-07-14: need a safer way to pick ports.
     p =  randrange(10000, 20000)
     return "127.0.0.1:%s" % p
 
@@ -119,10 +119,11 @@ class ExampleTest(unittest.TestCase):
         hw = execute("helloworld", b.addr)
         self.assertEqual('"Hello World!"\n', hw)
 
-    def test_helloworld_blocking(self):
-        b = Broker.get()
-        hw = execute("helloworld_blocking", b.addr, b.addr)
-        self.assertEqual('"Hello World!"\n', hw)
+        # FIXME aconway 2015-08-28: Restore blocking code and examples
+    # def test_helloworld_blocking(self):
+    #     b = Broker.get()
+    #     hw = execute("helloworld_blocking", b.addr, b.addr)
+    #     self.assertEqual('"Hello World!"\n', hw)
 
     def test_helloworld_direct(self):
         addr = pick_addr()
@@ -179,13 +180,14 @@ class ExampleTest(unittest.TestCase):
         finally:
             server.kill()
 
-    def test_sync_request_response(self):
-        b = Broker.get()
-        server = background("server", "-a", b.addr)
-        try:
-            self.assertEqual(execute("sync_client", "-a", b.addr), self.CLIENT_EXPECT)
-        finally:
-            server.kill()
+        # FIXME aconway 2015-08-28: Restore blocking code and examples
+    # def test_sync_request_response(self):
+    #     b = Broker.get()
+    #     server = background("server", "-a", b.addr)
+    #     try:
+    #         self.assertEqual(execute("sync_client", "-a", b.addr), self.CLIENT_EXPECT)
+    #     finally:
+    #         server.kill()
 
     def test_request_response_direct(self):
         addr = pick_addr()

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/helloworld.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld.cpp b/examples/cpp/helloworld.cpp
index 34e5076..4f73432 100644
--- a/examples/cpp/helloworld.cpp
+++ b/examples/cpp/helloworld.cpp
@@ -34,20 +34,20 @@ class hello_world : public proton::messaging_handler {
     hello_world(const proton::url& u) : url(u) {}
 
     void on_start(proton::event &e) {
-        proton::connection conn = e.container().connect(url);
+        proton::connection& conn = e.container().connect(url);
         e.container().create_receiver(conn, url.path());
         e.container().create_sender(conn, url.path());
     }
 
     void on_sendable(proton::event &e) {
-        proton::message m;
+        proton::message_value m;
         m.body("Hello World!");
         e.sender().send(m);
         e.sender().close();
     }
 
     void on_message(proton::event &e) {
-        proton::value body(e.message().body());
+        proton::data& body(e.message().body());
         std::cout << body << std::endl;
         e.connection().close();
     }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/helloworld_blocking.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld_blocking.cpp b/examples/cpp/helloworld_blocking.cpp
index 9f56fa2..39cc10d 100644
--- a/examples/cpp/helloworld_blocking.cpp
+++ b/examples/cpp/helloworld_blocking.cpp
@@ -19,7 +19,6 @@
  *
  */
 
-#include "proton/container.hpp"
 #include "proton/messaging_handler.hpp"
 #include "proton/blocking_sender.hpp"
 #include "proton/blocking_receiver.hpp"
@@ -34,13 +33,13 @@ int main(int argc, char **argv) {
         proton::blocking_receiver receiver = conn.create_receiver(url.path());
         proton::blocking_sender sender = conn.create_sender(url.path());
 
-        proton::message m;
-        m.body("Hello World!");
-        sender.send(m);
+        proton::message_value m;
+        m->body("Hello World!");
+        sender.send(*m);
 
         proton::duration timeout(30000);
-        proton::message m2 = receiver.receive(timeout);
-        std::cout << m2.body() << std::endl;
+        proton::message_value m2 = receiver.receive(timeout);
+        std::cout << m2->body() << std::endl;
         receiver.accept();
 
         conn.close();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/helloworld_direct.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/helloworld_direct.cpp b/examples/cpp/helloworld_direct.cpp
index 2c7792e..3240586 100644
--- a/examples/cpp/helloworld_direct.cpp
+++ b/examples/cpp/helloworld_direct.cpp
@@ -28,7 +28,7 @@
 class hello_world_direct : public proton::messaging_handler {
   private:
     proton::url url;
-    proton::acceptor acceptor;
+    proton::counted_ptr<proton::acceptor> acceptor;
   public:
 
     hello_world_direct(const proton::url& u) : url(u) {}
@@ -39,7 +39,7 @@ class hello_world_direct : public proton::messaging_handler {
     }
 
     void on_sendable(proton::event &e) {
-        proton::message m;
+        proton::message_value m;
         m.body("Hello World!");
         e.sender().send(m);
         e.sender().close();
@@ -54,7 +54,7 @@ class hello_world_direct : public proton::messaging_handler {
     }
 
     void on_connection_closed(proton::event &e) {
-        acceptor.close();
+        acceptor->close();
     }
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/server.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server.cpp b/examples/cpp/server.cpp
index bad49d3..08c4376 100644
--- a/examples/cpp/server.cpp
+++ b/examples/cpp/server.cpp
@@ -31,9 +31,9 @@
 
 class server : public proton::messaging_handler {
   private:
-    typedef std::map<std::string, proton::sender> sender_map;
+    typedef std::map<std::string, proton::counted_ptr<proton::sender> > sender_map;
     proton::url url;
-    proton::connection connection;
+    proton::counted_ptr<proton::connection> connection;
     sender_map senders;
 
   public:
@@ -42,7 +42,7 @@ class server : public proton::messaging_handler {
 
     void on_start(proton::event &e) {
         connection = e.container().connect(url);
-        e.container().create_receiver(connection, url.path());
+        e.container().create_receiver(*connection, url.path());
         std::cout << "server connected to " << url << std::endl;
     }
 
@@ -56,13 +56,13 @@ class server : public proton::messaging_handler {
     void on_message(proton::event &e) {
         std::cout << "Received " << e.message().body() << std::endl;
         std::string reply_to = e.message().reply_to();
-        proton::message reply;
+        proton::message_value reply;
         reply.address(reply_to);
         reply.body(to_upper(e.message().body().get<std::string>()));
         reply.correlation_id(e.message().correlation_id());
         if (!senders[reply_to])
-            senders[reply_to] = e.container().create_sender(connection, reply_to);
-        senders[reply_to].send(reply);
+            senders[reply_to] = e.container().create_sender(*connection, reply_to);
+        senders[reply_to]->send(reply);
     }
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/server_direct.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/server_direct.cpp b/examples/cpp/server_direct.cpp
index a2571ca..c89edca 100644
--- a/examples/cpp/server_direct.cpp
+++ b/examples/cpp/server_direct.cpp
@@ -32,9 +32,8 @@
 
 class server : public proton::messaging_handler {
   private:
-    typedef std::map<std::string, proton::sender> sender_map;
+    typedef std::map<std::string, proton::counted_ptr<proton::sender> > sender_map;
     proton::url url;
-    proton::connection connection;
     sender_map senders;
     int address_counter;
 
@@ -61,10 +60,10 @@ class server : public proton::messaging_handler {
     }
 
     void on_link_opening(proton::event& e) {
-        proton::link link = e.link();
-        if (link.is_sender() && link.remote_source() && link.remote_source().is_dynamic()) {
+        proton::link& link = e.link();
+        if (link.is_sender() && link.has_remote_source() && link.remote_source().is_dynamic()) {
             link.source().address(generate_address());
-            senders[link.source().address()] = link;
+            senders[link.source().address()] = link.sender();
         }
     }
 
@@ -75,12 +74,12 @@ class server : public proton::messaging_handler {
         if (it == senders.end()) {
             std::cout << "No link for reply_to: " << reply_to << std::endl;
         } else {
-            proton::sender sender = it->second;
-            proton::message reply;
+            proton::counted_ptr<proton::sender> sender = it->second;
+            proton::message_value reply;
             reply.address(reply_to);
             reply.body(to_upper(e.message().body().get<std::string>()));
             reply.correlation_id(e.message().correlation_id());
-            sender.send(reply);
+            sender->send(reply);
         }
     }
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/simple_recv.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp
index 94cd398..88eb48c 100644
--- a/examples/cpp/simple_recv.cpp
+++ b/examples/cpp/simple_recv.cpp
@@ -36,6 +36,7 @@
 class simple_recv : public proton::messaging_handler {
   private:
     proton::url url;
+    proton::counted_ptr<proton::receiver> receiver;
     int expected;
     int received;
   public:
@@ -43,13 +44,13 @@ class simple_recv : public proton::messaging_handler {
     simple_recv(const std::string &s, int c) : url(s), expected(c), received(0) {}
 
     void on_start(proton::event &e) {
-        e.container().create_receiver(url);
+        receiver = e.container().create_receiver(url);
         std::cout << "simple_recv listening on " << url << std::endl;
     }
 
     void on_message(proton::event &e) {
-        proton::message msg = e.message();
-        proton::value id = msg.id();
+        proton::message& msg = e.message();
+        proton::data_value id = msg.id();
         if (id.type() == proton::ULONG) {
             if (id.get<int>() < received)
                 return; // ignore duplicate

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/simple_send.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp
index 0bac49b..1db94af 100644
--- a/examples/cpp/simple_send.cpp
+++ b/examples/cpp/simple_send.cpp
@@ -36,6 +36,7 @@
 class simple_send : public proton::messaging_handler {
   private:
     proton::url url;
+    proton::counted_ptr<proton::sender> sender;
     int sent;
     int confirmed;
     int total;
@@ -44,14 +45,14 @@ class simple_send : public proton::messaging_handler {
     simple_send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {}
 
     void on_start(proton::event &e) {
-        e.container().create_sender(url);
+        sender = e.container().create_sender(url);
     }
 
     void on_sendable(proton::event &e) {
-        proton::sender sender = e.sender();
+        proton::sender& sender = e.sender();
         while (sender.credit() && sent < total) {
-            proton::message msg;
-            msg.id(proton::value(sent + 1));
+            proton::message_value msg;
+            msg.id(proton::data_value(sent + 1));
             std::map<std::string, int> m;
             m["sequence"] = sent+1;
             msg.body(proton::as<proton::MAP>(m));

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/examples/cpp/sync_client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/sync_client.cpp b/examples/cpp/sync_client.cpp
index d0ad6fc..2bcb5c5 100644
--- a/examples/cpp/sync_client.cpp
+++ b/examples/cpp/sync_client.cpp
@@ -52,9 +52,9 @@ int main(int argc, char **argv) {
         proton::blocking_connection conn(url, proton::duration(timeout));
         proton::sync_request_response client(conn, url.path());
         for (std::vector<std::string>::const_iterator i=requests.begin(); i != requests.end(); i++) {
-            proton::message request;
-            request.body(*i);
-            proton::message response = client.call(request);
+            proton::message_value request;
+            request->body(*i);
+            proton::message_value response(client.call(*request));
             std::cout << request.body() << " => " << response.body() << std::endl;
         }
         return 0;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt
index 519eb4e..5e116da 100644
--- a/proton-c/bindings/cpp/CMakeLists.txt
+++ b/proton-c/bindings/cpp/CMakeLists.txt
@@ -26,6 +26,12 @@ if (HAVE_LONG_LONG)
   add_definitions(-DPN_HAVE_LONG_LONG=1)
 endif()
 
+# Check for boost
+find_path(BOOST_INCLUDE_DIR boost/shared_ptr.hpp PATH_SUFFIXES include)
+if (BOOST_INCLUDE_DIR)
+  set(CXX_BOOST_FLAGS "-DPN_USE_BOOST")
+endif()
+
 include_directories(
   "${CMAKE_SOURCE_DIR}/proton-c/include"
   "${CMAKE_CURRENT_SOURCE_DIR}/include"
@@ -33,12 +39,17 @@ include_directories(
 
 set(qpid-proton-cpp-source
   src/acceptor.cpp
-  src/acking.cpp
+  # FIXME aconway 2015-08-28: Restore blocking code and examples
+  # src/blocking_connection.cpp
+  # src/blocking_connection_impl.cpp
+  # src/blocking_link.cpp
+  # src/blocking_receiver.cpp
+  # src/blocking_sender.cpp
   src/connection.cpp
-  src/connection_impl.cpp
   src/connector.cpp
   src/container.cpp
   src/container_impl.cpp
+  src/contexts.cpp
   src/data.cpp
   src/decoder.cpp
   src/delivery.cpp
@@ -47,38 +58,34 @@ set(qpid-proton-cpp-source
   src/endpoint.cpp
   src/error.cpp
   src/event.cpp
+  # FIXME aconway 2015-08-28: Restore blocking code and examples
+  # src/fetcher.cpp
   src/handler.cpp
   src/link.cpp
   src/message.cpp
   src/messaging_adapter.cpp
   src/messaging_event.cpp
   src/messaging_handler.cpp
+  src/proton_bits.cpp
   src/proton_event.cpp
   src/proton_handler.cpp
   src/receiver.cpp
   src/sender.cpp
   src/session.cpp
+  # FIXME aconway 2015-08-28: Restore blocking code and examples
+  # src/sync_request_response.cpp
   src/terminus.cpp
   src/transport.cpp
-  src/url.cpp
-  src/value.cpp
-  src/values.cpp
-  src/proton_bits.cpp
-  src/fetcher.cpp
-  src/blocking_connection.cpp
-  src/blocking_connection_impl.cpp
-  src/blocking_link.cpp
-  src/blocking_sender.cpp
-  src/blocking_receiver.cpp
-  src/sync_request_response.cpp
-  src/contexts.cpp
   src/types.cpp
+  src/url.cpp
+  src/facade.cpp
   )
 
+
 set_source_files_properties (
   ${qpid-proton-cpp-source}
   PROPERTIES
-  COMPILE_FLAGS "${CXX_WARNING_FLAGS}"
+  COMPILE_FLAGS "${CXX_WARNING_FLAGS} ${CXX_BOOST_FLAGS}"
   )
 
 add_library(qpid-proton-cpp SHARED ${qpid-proton-cpp-source})
@@ -113,6 +120,7 @@ macro(add_cpp_test test)
 endmacro(add_cpp_test)
 
 add_cpp_test(interop_test ${CMAKE_SOURCE_DIR}/tests)
+add_cpp_test(conversion_test ${CMAKE_SOURCE_DIR}/tests)
 
 ## Install
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/docs/mainpage.md
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/mainpage.md b/proton-c/bindings/cpp/docs/mainpage.md
index 70db98b..b370b13 100644
--- a/proton-c/bindings/cpp/docs/mainpage.md
+++ b/proton-c/bindings/cpp/docs/mainpage.md
@@ -67,7 +67,7 @@ Commonly used classes
 
 A brief summary of some of the key classes follows.
 
-The `proton::container` class is a convenient entry point into the API, allowing
+The `proton::container` class is the main entry point into the API, allowing
 connections and links to be established. Applications are structured as one or
 more event handlers.
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/docs/tutorial.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/docs/tutorial.hpp b/proton-c/bindings/cpp/docs/tutorial.hpp
index 6df7593..56f3e9f 100644
--- a/proton-c/bindings/cpp/docs/tutorial.hpp
+++ b/proton-c/bindings/cpp/docs/tutorial.hpp
@@ -3,9 +3,7 @@
 // that shows messed-up line numbers in \skip \until code extracts so this file
 // is markdown wrapped in a C++ comment - which works.
 
-/** \page tutorial Tutorial
-Tutorial 
-========
+/*! \page tutorial Tutorial
 
 This is a brief tutorial that will walk you through the fundamentals of building
 messaging applications in incremental steps. There are further examples, in
@@ -103,7 +101,7 @@ code at \ref helloworld_direct.cpp
 
 The first difference, is that rather than creating a receiver on the same
 connection as our sender, we listen for incoming connections by invoking the
-`proton::container::listen()` method on the container.
+`proton::container::Xblisten()` method on the container.
 
 \skip on_start
 \until }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/acceptor.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/acceptor.hpp b/proton-c/bindings/cpp/include/proton/acceptor.hpp
index 6339a08..ed7c852 100644
--- a/proton-c/bindings/cpp/include/proton/acceptor.hpp
+++ b/proton-c/bindings/cpp/include/proton/acceptor.hpp
@@ -24,18 +24,16 @@
 
 #include "proton/reactor.h"
 #include "proton/export.hpp"
-#include "proton/wrapper.hpp"
+#include "proton/facade.hpp"
 
 struct pn_connection_t;
 
 namespace proton {
 
 /** acceptor accepts connections. @see container::listen */
-class acceptor : public wrapper<pn_acceptor_t>
+class acceptor : public counted_facade<pn_acceptor_t, acceptor>
 {
   public:
-    PN_CPP_EXTERN acceptor(pn_acceptor_t * = 0);
-
     /** close the acceptor */
     PN_CPP_EXTERN void close();
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/acking.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/acking.hpp b/proton-c/bindings/cpp/include/proton/acking.hpp
deleted file mode 100644
index 0001a4d..0000000
--- a/proton-c/bindings/cpp/include/proton/acking.hpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef PROTON_CPP_ACKING_H
-#define PROTON_CPP_ACKING_H
-
-/*
- *
- * 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/export.hpp"
-#include "proton/delivery.hpp"
-
-namespace proton {
-
-
-/** acking provides simple functions to acknowledge, or settle, a delivery */
-class acking
-{
-  public:
-    /** accept a delivery */
-    PN_CPP_EXTERN virtual void accept(delivery &d);
-    /** reject a delivery */
-    PN_CPP_EXTERN virtual void reject(delivery &d);
-    /** release a delivery. Mark it delivery::MODIFIED if it has already been delivered,
-     * delivery::RELEASED otherwise.
-     */
-    PN_CPP_EXTERN virtual void release(delivery &d, bool delivered=true);
-    /** settle a delivery with the given delivery::state */
-    PN_CPP_EXTERN virtual void settle(delivery &d, delivery::state s = delivery::REJECTED);
-};
-
-
-}
-
-#endif  /*!PROTON_CPP_ACKING_H*/
-
-

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/blocking_connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/blocking_connection.hpp b/proton-c/bindings/cpp/include/proton/blocking_connection.hpp
index e82a2ee..c9a5133 100644
--- a/proton-c/bindings/cpp/include/proton/blocking_connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/blocking_connection.hpp
@@ -22,20 +22,14 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/handle.hpp"
-#include "proton/endpoint.hpp"
-#include "proton/container.hpp"
+#include "proton/facade.hpp"
 #include "proton/duration.hpp"
-#include "proton/messaging_handler.hpp"
-#include "proton/types.h"
 #include <string>
 
 struct pn_connection_t;
 
 namespace proton {
 class url;
-class container;
-class blocking_connection_impl;
 class ssl_domain;
 class blocking_sender;
 class blocking_receiver;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/blocking_link.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/blocking_link.hpp b/proton-c/bindings/cpp/include/proton/blocking_link.hpp
index 0fe5e9a..3ec945a 100644
--- a/proton-c/bindings/cpp/include/proton/blocking_link.hpp
+++ b/proton-c/bindings/cpp/include/proton/blocking_link.hpp
@@ -22,7 +22,6 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/handle.hpp"
 #include "proton/endpoint.hpp"
 #include "proton/container.hpp"
 #include "proton/duration.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/blocking_sender.hpp b/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
index 9b3c1a1..55e340e 100644
--- a/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
+++ b/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
@@ -22,7 +22,6 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/handle.hpp"
 #include "proton/endpoint.hpp"
 #include "proton/container.hpp"
 #include "proton/duration.hpp"
@@ -44,7 +43,7 @@ class blocking_sender : public blocking_link
     PN_CPP_EXTERN delivery send(message &msg);
     PN_CPP_EXTERN delivery send(message &msg, duration timeout);
   private:
-    PN_CPP_EXTERN blocking_sender(blocking_connection &c, sender l);
+    PN_CPP_EXTERN blocking_sender(blocking_connection &c, sender &l);
     friend class blocking_connection;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/comparable.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/comparable.hpp b/proton-c/bindings/cpp/include/proton/comparable.hpp
new file mode 100644
index 0000000..b409859
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/comparable.hpp
@@ -0,0 +1,44 @@
+#ifndef COMPARABLE_HPP
+#define COMPARABLE_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.
+ */
+
+namespace proton {
+
+///@cond INTERNAL
+
+/// Internal base class to provide comparison operators.
+template <class T> struct comparable {
+};
+
+template<class T> bool operator<(const comparable<T>& a, const comparable<T>& b) {
+    return static_cast<const T&>(a) < static_cast<const T&>(b); // operator < provided by type T
+}
+
+template<class T> bool operator>(const comparable<T>& a, const comparable<T>& b) { return b < a; }
+template<class T> bool operator<=(const comparable<T>& a, const comparable<T>& b) { return !(a > b); }
+template<class T> bool operator>=(const comparable<T>& a, const comparable<T>& b) { return !(a < b); }
+template<class T> bool operator==(const comparable<T>& a, const comparable<T>& b) { return a <= b && b <= a; }
+template<class T> bool operator!=(const comparable<T>& a, const comparable<T>& b) { return !(a == b); }
+
+///@endcond
+
+}
+
+#endif // COMPARABLE_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/config.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/config.hpp b/proton-c/bindings/cpp/include/proton/config.hpp
index 70260b7..322ca1a 100644
--- a/proton-c/bindings/cpp/include/proton/config.hpp
+++ b/proton-c/bindings/cpp/include/proton/config.hpp
@@ -20,11 +20,32 @@
  */
 
 /**@file
- * @internal
+ *
+ * Configuration macros. If set before this file is included (e.g. via -D
+ * options to the compiler) they will not be altered, otherwise we will enable
+ * everything possible.
+ *
+ * The macros are:
+ * - PN_USE_CPP11 - assume a C++11 or greater compiler. Defaulted from compiler settings.
+ * - PN_USE_BOOST - include support for boost smart pointers, default 0.
  */
 
-#if (defined(__cplusplus) && __cplusplus >= 201100) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729)
-#define USE_CPP11
+
+#ifndef PN_USE_CPP11
+#if ((defined(__cplusplus) && __cplusplus >= 201100) || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 150030729))
+#define PN_USE_CPP11 1
+#else
+#define PN_USE_CPP11 0
+#endif
 #endif
 
+#if PN_USE_CPP11
+// Simple ownership pointer, use std::unique_ptr in C++11 std::auto_ptr otherwise.
+#define PN_UNIQUE_OR_AUTO_PTR std::unique_ptr
+#else
+// Simple ownership pointer, use std::unique_ptr in C++11 std::auto_ptr otherwise.
+#define PN_UNIQUE_OR_AUTO_PTR std::auto_ptr
+#endif
+
+
 #endif // CONFIG_HPP

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/connection.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/connection.hpp b/proton-c/bindings/cpp/include/proton/connection.hpp
index af3c585..d9369b6 100644
--- a/proton-c/bindings/cpp/include/proton/connection.hpp
+++ b/proton-c/bindings/cpp/include/proton/connection.hpp
@@ -22,7 +22,6 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/handle.hpp"
 #include "proton/endpoint.hpp"
 #include "proton/container.hpp"
 #include "proton/types.h"
@@ -34,31 +33,17 @@ namespace proton {
 
 class handler;
 class transport;
-class connection_impl;
 
-/** connection is the local end of a connectoin to a remote AMQP peer. */
-class connection : public endpoint, public handle<connection_impl>
+/** connection to a remote AMQP peer. */
+class connection : public counted_facade<pn_connection_t, connection>, public endpoint
 {
   public:
-    PN_CPP_EXTERN connection();
-    PN_CPP_EXTERN connection(connection_impl *);
-    PN_CPP_EXTERN connection(const connection& c);
-    PN_CPP_EXTERN connection(class container &c, handler *h = 0);
-    PN_CPP_EXTERN ~connection();
-
-    PN_CPP_EXTERN connection& operator=(const connection& c);
-
     ///@name getters @{
     PN_CPP_EXTERN class transport& transport();
-    PN_CPP_EXTERN handler *override();
-    PN_CPP_EXTERN pn_connection_t *pn_connection();
-    PN_CPP_EXTERN class container &container();
+    PN_CPP_EXTERN class container& container();
     PN_CPP_EXTERN std::string hostname();
     ///@}
 
-    /** override the handler for this connection */
-    PN_CPP_EXTERN void override(handler *h);
-
     /** Initiate local open, not complete till messaging_handler::on_connection_opened()
      * or proton_handler::on_connection_remote_open()
      */
@@ -69,15 +54,17 @@ class connection : public endpoint, public handle<connection_impl>
      */
     PN_CPP_EXTERN void close();
 
+    /** Create a new session */
+    PN_CPP_EXTERN class session& create_session();
+
+    /** Default session is created on first call and re-used for the lifeime of the connection */
+    PN_CPP_EXTERN class session& default_session();
+
     /** Get the first link on this connection matching the state mask.
+     * Return 0 if none. Don't delete returned pointer.
      * @see link::next, endpoint::state
      */
-    PN_CPP_EXTERN link link_head(endpoint::state mask);
-
-  private:
-   friend class private_impl_ref<connection>;
-   friend class connector;
-   friend class connection_impl;
+    PN_CPP_EXTERN link* link_head(endpoint::state mask);
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/container.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/container.hpp b/proton-c/bindings/cpp/include/proton/container.hpp
index a0ca59a..014d2c0 100644
--- a/proton-c/bindings/cpp/include/proton/container.hpp
+++ b/proton-c/bindings/cpp/include/proton/container.hpp
@@ -21,11 +21,12 @@
  * under the License.
  *
  */
-#include "proton/export.hpp"
-#include "proton/handle.hpp"
 #include "proton/acceptor.hpp"
 #include "proton/duration.hpp"
+#include "proton/export.hpp"
+#include "proton/facade.hpp"
 #include "proton/url.hpp"
+
 #include <proton/reactor.h>
 #include <string>
 
@@ -41,26 +42,20 @@ class sender;
 class receiver;
 class link;
 class handler;
+class container_impl;
 
-/** Top level container for connections and other objects, runs the event loop */ 
-class container : public handle<container_impl>
+/**
+ * Top level container for connections and other objects, runs the event loop.
+ */
+class container
 {
   public:
-    ///@name internal @internal @{
-    PN_CPP_EXTERN container(container_impl *);
-    PN_CPP_EXTERN container(const container& c);
-    PN_CPP_EXTERN container& operator=(const container& c);
-    PN_CPP_EXTERN ~container();
-    ///@}
-
-    /** Create a container */
     PN_CPP_EXTERN container();
-
-    /** Create a container and set the top-level messaging_handler */
-    PN_CPP_EXTERN container(messaging_handler &mhandler);
+    PN_CPP_EXTERN container(messaging_handler& mhandler);
+    PN_CPP_EXTERN ~container();
 
     /** Locally open a connection @see connection::open  */
-    PN_CPP_EXTERN connection connect(const proton::url&, handler *h=0);
+    PN_CPP_EXTERN connection& connect(const proton::url&, handler *h=0);
 
     /** Run the event loop, return when all connections and acceptors are closed. */
     PN_CPP_EXTERN void run();
@@ -75,19 +70,19 @@ class container : public handle<container_impl>
     PN_CPP_EXTERN void stop();
 
     /** Create a sender on connection with target=addr and optional handler h */
-    PN_CPP_EXTERN sender create_sender(connection &connection, const std::string &addr, handler *h=0);
+    PN_CPP_EXTERN sender& create_sender(connection &connection, const std::string &addr, handler *h=0);
 
     /** Open a connection to url and create a sender with target=url.path() */
-    PN_CPP_EXTERN sender create_sender(const proton::url &);
+    PN_CPP_EXTERN sender& create_sender(const proton::url &);
 
     /** Create a receiver on connection with target=addr and optional handler h */
-    PN_CPP_EXTERN receiver create_receiver(connection &connection, const std::string &addr, bool dynamic=false, handler *h=0);
+    PN_CPP_EXTERN receiver& create_receiver(connection &connection, const std::string &addr, bool dynamic=false, handler *h=0);
 
     /** Create a receiver on connection with source=url.path() */
-    PN_CPP_EXTERN receiver create_receiver(const url &);
+    PN_CPP_EXTERN receiver& create_receiver(const url &);
 
     /** Open a connection to url and create a receiver with source=url.path() */
-    PN_CPP_EXTERN acceptor listen(const proton::url &);
+    PN_CPP_EXTERN acceptor& listen(const proton::url &);
 
     /// Identifier for the container
     PN_CPP_EXTERN std::string container_id();
@@ -104,8 +99,9 @@ class container : public handle<container_impl>
     PN_CPP_EXTERN void wakeup();
     PN_CPP_EXTERN bool is_quiesced();
     PN_CPP_EXTERN void yield();
-private:
-   friend class private_impl_ref<container>;
+
+  private:
+    PN_UNIQUE_OR_AUTO_PTR<container_impl> impl_;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/cstdint.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/cstdint.hpp b/proton-c/bindings/cpp/include/proton/cstdint.hpp
index e6404d1..9fb6d37 100644
--- a/proton-c/bindings/cpp/include/proton/cstdint.hpp
+++ b/proton-c/bindings/cpp/include/proton/cstdint.hpp
@@ -19,7 +19,7 @@
  * under the License.
  */
 
-///@cond INTERNAL_DETAIL
+///@cond INTERNAL
 
 /**@file
  *
@@ -27,7 +27,7 @@
  * Not the full cstdint, just the type needed by proton.
  */
 
-#ifdef USE_CPP11
+#if PN_USE_CPP11
 #include <cstdint>
 #else
 #include <proton/type_compat.h>

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/data.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/data.hpp b/proton-c/bindings/cpp/include/proton/data.hpp
index 83b3bff..f91270c 100644
--- a/proton-c/bindings/cpp/include/proton/data.hpp
+++ b/proton-c/bindings/cpp/include/proton/data.hpp
@@ -20,49 +20,108 @@
  */
 
 #include "proton/export.hpp"
+#include "proton/facade.hpp"
+#include "proton/decoder.hpp"
+#include "proton/encoder.hpp"
 #include <iosfwd>
 
 struct pn_data_t;
 
 namespace proton {
 
-/** Base for classes that hold AMQP data, not for direct use. @see value, values, encoder, decoder. */
-class data {
+class data;
+
+/**
+ * Holds a sequence of AMQP values, allows inserting and extracting via encoder() and decoder().
+ * Cannot be directly instantiated, use `data_value`
+ */
+class data : public facade<pn_data_t, data>, public comparable<data> {
   public:
-    PN_CPP_EXTERN explicit data();
-    PN_CPP_EXTERN data(const data&);
-    PN_CPP_EXTERN virtual ~data();
+    PN_CPP_EXTERN static PN_UNIQUE_OR_AUTO_PTR<data> create();
+
     PN_CPP_EXTERN data& operator=(const data&);
+    template<class T> data& operator=(const T &t) {
+        clear(); encoder() << t; decoder().rewind(); return *this;
+    }
 
     /** Clear the data. */
     PN_CPP_EXTERN void clear();
 
-    /** Rewind to the start of the data. */
-    PN_CPP_EXTERN void rewind();
-
     /** True if there are no values. */
     PN_CPP_EXTERN bool empty() const;
 
-    /** The underlying pn_data_t */
-    PN_CPP_EXTERN pn_data_t* pn_data() { return data_; }
+    /** Encoder to encode into this value */
+    PN_CPP_EXTERN class encoder& encoder();
 
-    /** True if this data object owns it's own pn_data_t, false if it is acting as a "view" */
-    PN_CPP_EXTERN bool own() const { return own_; }
+    /** Decoder to decode from this value */
+    PN_CPP_EXTERN class decoder& decoder();
 
-    PN_CPP_EXTERN void swap(data&);
+    /** Type of the current value*/
+    PN_CPP_EXTERN type_id type() { return decoder().type(); }
 
-    /** Human readable representation of data. */
-    friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const data&);
+    /** Get the current value, don't move the decoder pointer. */
+    template<class T> void get(T &t) { decoder() >> t; decoder().backup(); }
 
-  protected:
-    /** Does not take ownership, just a view on the data */
-    PN_CPP_EXTERN explicit data(pn_data_t*);
+    /** Get the current value */
+    template<class T> T get() { T t; get(t); return t; }
 
-    /** Does not take ownership, just a view on the data */
-    PN_CPP_EXTERN  void view(pn_data_t*);
+    bool operator==(const data& x) const;
+    bool operator<(const data& x) const;
 
-    mutable pn_data_t* data_;
-    bool own_;
+    void operator delete(void *);
+
+    /** Human readable representation of data. */
+  friend PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const data&);
+};
+
+/** data with normal value semantics: copy, assign etc. */
+class data_value : public comparable<data_value> {
+  public:
+    data_value() : data_(data::create()) {}
+    data_value(const data_value& x) : data_(data::create()) { *data_ = *x.data_; }
+    data_value(const data& x) : data_(data::create()) { *data_ = x; }
+    template <class T> data_value(const T& x) : data_(data::create()) { *data_ = x; }
+
+    operator data&() { return *data_; }
+    operator const data&() const { return *data_; }
+
+    data_value& operator=(const data_value& x) { *data_ = *x.data_; return *this; }
+    data_value& operator=(const data& x) { *data_ = x; return *this; }
+    template <class T> data_value& operator=(const T& x) { *data_ = x; return *this; }
+
+    void clear() { data_->clear(); }
+    bool empty() const { return data_->empty(); }
+
+    /** Encoder to encode into this value */
+    class encoder& encoder() { return data_->encoder(); }
+
+    /** Decoder to decode from this value */
+    class decoder& decoder() { return data_->decoder(); }
+
+    /** Type of the current value*/
+    type_id type() { return decoder().type(); }
+
+    /** Get the current value, don't move the decoder pointer. */
+    template<class T> void get(T &t) { decoder() >> t; decoder().backup(); }
+
+    /** Get the current value */
+    template<class T> T get() { T t; get(t); return t; }
+    template<class T> operator T() { return get<T>(); }
+
+    bool operator==(const data_value& x) const { return *data_ == *x.data_; }
+    bool operator<(const data_value& x) const { return *data_ < *x.data_; }
+
+  friend inline class encoder& operator<<(class encoder& e, const data_value& dv) {
+      return e << *dv.data_;
+  }
+  friend inline class decoder& operator>>(class decoder& d, data_value& dv) {
+      return d >> *dv.data_;
+  }
+  friend inline std::ostream& operator<<(std::ostream& o, const data_value& dv) {
+      return o << *dv.data_;
+  }
+  private:
+    PN_UNIQUE_OR_AUTO_PTR<data> data_;
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/decoder.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/decoder.hpp b/proton-c/bindings/cpp/include/proton/decoder.hpp
index 6761653..ebca61b 100644
--- a/proton-c/bindings/cpp/include/proton/decoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/decoder.hpp
@@ -19,15 +19,17 @@
  * under the License.
  */
 
-#include "proton/data.hpp"
 #include "proton/error.hpp"
 #include "proton/type_traits.hpp"
 #include "proton/types.hpp"
+#include "proton/facade.hpp"
 #include <iosfwd>
 
+struct pn_data_t;
+
 namespace proton {
 
-class value;
+class data;
 
 /** Raised by decoder operations on error.*/
 struct decode_error : public error { PN_CPP_EXTERN explicit decode_error(const std::string&) throw(); };
@@ -66,12 +68,8 @@ struct rewind{};
  * You can also extract container values element-by-element, see decoder::operator>>(decoder&, start&)
  *
 */
-class decoder : public virtual data {
+class decoder : public facade<pn_data_t, decoder> {
   public:
-
-    PN_CPP_EXTERN decoder();
-    PN_CPP_EXTERN ~decoder();
-
     /** Copy AMQP data from a byte buffer into the decoder. */
     PN_CPP_EXTERN decoder(const char* buffer, size_t size);
 
@@ -92,6 +90,14 @@ class decoder : public virtual data {
      */
     PN_CPP_EXTERN type_id type() const;
 
+    /** Rewind to the start of the data. */
+    PN_CPP_EXTERN void rewind();
+
+    /** Back up by one value */
+    PN_CPP_EXTERN void backup(); 
+
+    PN_CPP_EXTERN class data& data();
+
     /** @name Extract simple types
      * Overloads to extract simple types.
      * @throw error if the decoder is empty or the current value has an incompatible type.
@@ -116,7 +122,7 @@ class decoder : public virtual data {
     PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_decimal128&);
     PN_CPP_EXTERN friend decoder& operator>>(decoder&, amqp_uuid&);
     PN_CPP_EXTERN friend decoder& operator>>(decoder&, std::string&);
-    PN_CPP_EXTERN friend decoder& operator>>(decoder&, value&);
+    PN_CPP_EXTERN friend decoder& operator>>(decoder&, class data&);
     ///@}
 
     /** Extract and return a value of type T. */
@@ -178,10 +184,8 @@ class decoder : public virtual data {
     PN_CPP_EXTERN friend decoder& operator>>(decoder&, struct rewind);
 
   private:
-    template <class T> decoder& extract(T& value);
     PN_CPP_EXTERN void check_type(type_id);
 
-  friend class value;
   friend class encoder;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/delivery.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/delivery.hpp b/proton-c/bindings/cpp/include/proton/delivery.hpp
index cc74498..5528677 100644
--- a/proton-c/bindings/cpp/include/proton/delivery.hpp
+++ b/proton-c/bindings/cpp/include/proton/delivery.hpp
@@ -22,7 +22,7 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/wrapper.hpp"
+#include "proton/facade.hpp"
 
 #include "proton/delivery.h"
 #include "proton/disposition.h"
@@ -30,9 +30,7 @@
 namespace proton {
 
 /** delivery status of a message */
-class delivery : public wrapper<pn_delivery_t>
-{
-  public:
+class delivery : public counted_facade<pn_delivery_t, delivery> {
 
     /** Delivery state of a message */
     enum state {
@@ -44,8 +42,6 @@ class delivery : public wrapper<pn_delivery_t>
         MODIFIED = PN_MODIFIED  ///< Settled as modified
     };  // AMQP spec 3.4 delivery State
 
-    PN_CPP_EXTERN delivery(pn_delivery_t * = 0);
-
     /** Return true if the delivery has been settled. */
     PN_CPP_EXTERN bool settled();
 
@@ -54,6 +50,21 @@ class delivery : public wrapper<pn_delivery_t>
 
     /** Set the local state of the delivery. */
     PN_CPP_EXTERN void update(delivery::state state);
+
+    /** update and settle a delivery with the given delivery::state */
+    PN_CPP_EXTERN void settle(delivery::state s);
+
+    /** settle with ACCEPTED state */
+    PN_CPP_EXTERN void accept() { settle(ACCEPTED); }
+
+    /** settle with REJECTED state */
+    PN_CPP_EXTERN void reject() { settle(REJECTED); }
+
+    /** settle with REJECTED state */
+    PN_CPP_EXTERN void release() { settle(RELEASED); }
+
+    /** settle with MODIFIED state */
+    PN_CPP_EXTERN void modifiy() { settle(MODIFIED); }
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/encoder.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/encoder.hpp b/proton-c/bindings/cpp/include/proton/encoder.hpp
index b3e2ab4..52309bf 100644
--- a/proton-c/bindings/cpp/include/proton/encoder.hpp
+++ b/proton-c/bindings/cpp/include/proton/encoder.hpp
@@ -19,18 +19,17 @@
  * under the License.
  */
 
-#include "proton/data.hpp"
 #include "proton/error.hpp"
 #include "proton/types.hpp"
 #include "proton/type_traits.hpp"
+#include "proton/facade.hpp"
 #include <iosfwd>
 
 struct pn_data_t;
 
 namespace proton {
 
-class value;
-class values;
+class data;
 
 /** Raised by encoder operations on error */
 struct encode_error : public error { PN_CPP_EXTERN explicit encode_error(const std::string&) throw(); };
@@ -59,11 +58,8 @@ struct encode_error : public error { PN_CPP_EXTERN explicit encode_error(const s
  *
  *@throw decoder::error if the curent value is not a container type.
  */
-class encoder : public virtual data {
+class encoder : public facade<pn_data_t, encoder> {
   public:
-    PN_CPP_EXTERN encoder();
-    PN_CPP_EXTERN ~encoder();
-
     /**
      * Encode the current values into buffer and update size to reflect the number of bytes encoded.
      *
@@ -83,6 +79,8 @@ class encoder : public virtual data {
     /** Encode the current values into a std::string. Clears the encoder. */
     PN_CPP_EXTERN std::string encode();
 
+    PN_CPP_EXTERN class data& data();
+
     /** @name Insert simple types.
      *@{
      */
@@ -107,8 +105,7 @@ class encoder : public virtual data {
   friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_string);
   friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_symbol);
   friend PN_CPP_EXTERN encoder& operator<<(encoder&, amqp_binary);
-  friend PN_CPP_EXTERN encoder& operator<<(encoder&, const value&);
-  friend PN_CPP_EXTERN encoder& operator<<(encoder&, const values&);
+  friend PN_CPP_EXTERN encoder& operator<<(encoder&, const class data&);
     ///@}
 
     /**
@@ -139,11 +136,6 @@ class encoder : public virtual data {
 
     /** Copy data from a raw pn_data_t */
   friend PN_CPP_EXTERN encoder& operator<<(encoder&, pn_data_t*);
-
-  private:
-    PN_CPP_EXTERN encoder(pn_data_t* pd);
-
-  friend class value;
 };
 
 // Need to disambiguate char* conversion to bool and std::string as amqp_string.
@@ -185,11 +177,11 @@ template <class T> encoder& operator<<(encoder& e, cref<T, MAP> m){
     e << finish();
     return e;
 }
-//@internal Convert a ref to a cref.
+///@cond INTERNAL Convert a ref to a cref.
 template <class T, type_id A> encoder& operator<<(encoder& e, ref<T, A> ref) {
     return e << cref<T,A>(ref);
 }
-
+///@endcond
 
 }
 #endif // ENCODER_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/endpoint.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/endpoint.hpp b/proton-c/bindings/cpp/include/proton/endpoint.hpp
index 11970c7..665ab0c 100644
--- a/proton-c/bindings/cpp/include/proton/endpoint.hpp
+++ b/proton-c/bindings/cpp/include/proton/endpoint.hpp
@@ -58,10 +58,6 @@ class endpoint
      ///@}
 
     // TODO: condition, remote_condition, update_condition, get/handler
-
-  protected:
-    PN_CPP_EXTERN endpoint();
-    PN_CPP_EXTERN ~endpoint();
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/event.hpp b/proton-c/bindings/cpp/include/proton/event.hpp
index a9cbedd..5c7b5b1 100644
--- a/proton-c/bindings/cpp/include/proton/event.hpp
+++ b/proton-c/bindings/cpp/include/proton/event.hpp
@@ -46,16 +46,14 @@ class event {
     /// Get connection.
     virtual PN_CPP_EXTERN class connection &connection();
     /// Get sender @throws error if no sender.
-    virtual PN_CPP_EXTERN class sender sender();
+    virtual PN_CPP_EXTERN class sender& sender();
     /// Get receiver @throws error if no receiver.
-    virtual PN_CPP_EXTERN class receiver receiver();
+    virtual PN_CPP_EXTERN class receiver& receiver();
     /// Get link @throws error if no link.
-    virtual PN_CPP_EXTERN class link link();
+    virtual PN_CPP_EXTERN class link& link();
     /// Get delivey @throws error if no delivery.
-    virtual PN_CPP_EXTERN class delivery delivery();
-    /** Get message @throws error if no message.
-     * Refernece is valid only till end of event dispatch. Copy or swap the message to keep it.
-     */
+    virtual PN_CPP_EXTERN class delivery& delivery();
+    /** Get message @throws error if no message. */
     virtual PN_CPP_EXTERN class message &message();
 
   protected:

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/export.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/export.hpp b/proton-c/bindings/cpp/include/proton/export.hpp
index bb211ae..27071ed 100644
--- a/proton-c/bindings/cpp/include/proton/export.hpp
+++ b/proton-c/bindings/cpp/include/proton/export.hpp
@@ -22,7 +22,8 @@
  *
  */
 
-/// Internal: import/export macros @cond INTERNAL
+/// @cond INTERNAL
+/// import/export macros 
 #if defined(WIN32) && !defined(PN_CPP_DECLARE_STATIC)
   //
   // Import and Export definitions for Windows:


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


[2/3] qpid-proton git commit: PROTON-865: 0-overhead facades, reference counting and smart ptr support.

Posted by ac...@apache.org.
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/facade.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/facade.hpp b/proton-c/bindings/cpp/include/proton/facade.hpp
new file mode 100644
index 0000000..6dc7a71
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/facade.hpp
@@ -0,0 +1,263 @@
+#ifndef PROTON_CPP_FACADE_H
+#define PROTON_CPP_FACADE_H
+
+/*
+ *
+ * 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.
+ *
+ */
+
+/*! \page c-and-cpp C and memory management.
+ *\brief
+ *
+ * The C++ API is a very thin wrapper over the C API.  The C API consists of a
+ * set of `struct` types and associated C functions.  For each there is a a C++
+ * `facade` that provides C++ member functions to call the corresponding C
+ * functions on the underlying C struct. Facade classes derive from the
+ * `proton::facade` template.
+ *
+ * The facade class occupies no additional memory. The C+ facade pointer points
+ * directly to the underlying C++ struct, calling C++ member functions corresponds
+ * directly to calling the C function.
+ *
+ * If you want to mix C and C++ code (which should be done carefully!) you can
+ * cast between a facade pointer and a C struct pointer with `proton::pn_cast`
+ * and `foo::cast()` where `foo` is some C++ facade class.
+ *
+ * Deleting a facade object calls the appropriate `pn_foo_free` function or
+ * `pn_decref` as appropriate.
+ *
+ * Some proton structs are reference counted, the facade classes for these
+ * derive from the `proton::counted_facade` template. Most proton functions that
+ * return facade objects return a reference to an object that is owned by the
+ * called object. Such references are only valid in a limited scope (for example
+ * in an event handler function.) To keep a reference outside that scope, you
+ * can assign it to a proton::counted_ptr, std::shared_ptr, boost::shared_ptr,
+ * boost::intrusive_ptr or std::unique_ptr. You can also call
+ * `proton::counted_facade::new_reference` to get a raw pointer which you must
+ * delete when you are done (e.g. using `std::auto_ptr`)
+ */
+
+/**@file
+ * Classes and templates used by object facades.
+ */
+
+#include "proton/export.hpp"
+#include "proton/config.hpp"
+#include "proton/comparable.hpp"
+#include <memory>
+#if PN_USE_BOOST
+#include "boost/shared_ptr.hpp"
+#include "boost/intrusive_ptr.hpp"
+#endif
+
+namespace proton {
+
+/**
+ * Base class for C++ facades of proton C struct types.
+ *
+ * @see \ref c-and-cpp
+ */
+template <class P, class T> class facade {
+  public:
+    /// The underlying C struct type.
+    typedef P pn_type;
+
+    /// Cast the C struct pointer to a C++ facade pointer.
+    static T* cast(P* p) { return reinterpret_cast<T*>(p); }
+
+#if PN_USE_CPP11
+    facade() = delete;
+    facade(const facade&) = delete;
+    facade& operator=(const facade&) = delete;
+    void operator delete(void* p) = delete; // Defined by type T.
+#else
+  private:
+    facade();
+    facade(const facade&);
+    facade& operator=(const facade&);
+    void operator delete(void* p);
+#endif
+};
+
+///@cond INTERNAL Cast from a C++ facade type to the corresponding proton C struct type.
+/// Allow casting away const, the underlying pn structs have not constness.
+template <class T> typename T::pn_type* pn_cast(const T* p) {
+    return reinterpret_cast<typename T::pn_type*>(const_cast<T*>(p));
+}
+///@endcond
+
+/**
+ * Smart pointer for object derived from `proton::counted_facade`.
+ *
+ * You can use it in your own code if you or convert it to any of
+ * std::shared_ptr, boost::shared_ptr, boost::intrusive_ptr or std::unique_ptr
+ *
+ * Note a std::unique_ptr only takes ownership of a a
+ * *reference*, not the underlying struct itself.
+*/
+template <class T> class counted_ptr : public comparable<counted_ptr<T> > {
+  public:
+    typedef T element_type;
+
+    explicit counted_ptr(T *p = 0, bool add_ref = true) : ptr_(p) { if (p && add_ref) incref(ptr_); }
+
+    counted_ptr(const counted_ptr<T>& p) : ptr_(p.ptr_) { incref(ptr_); }
+
+    // TODO aconway 2015-08-20: C++11 move constructor
+
+    ~counted_ptr() { decref(ptr_); }
+
+    void swap(counted_ptr& x) { std::swap(ptr_, x.ptr_); }
+
+    counted_ptr<T>& operator=(const counted_ptr<T>& p) {
+        counted_ptr<T>(p.get()).swap(*this);
+        return *this;
+    }
+
+    void reset(T* p=0, bool add_ref = true) {
+        counted_ptr<T>(p, add_ref).swap(*this);
+    }
+
+    T* release() {
+        T* ret = ptr_;
+        ptr_ = 0;
+        return ret;
+    }
+
+    T* get() const { return ptr_; }
+    T* operator->() const { return ptr_; }
+    T& operator*() const { return *ptr_; }
+    operator bool() const { return ptr_; }
+    bool operator!() const { return !ptr_; }
+
+    template <class U> operator counted_ptr<U>() const { return counted_ptr<U>(get()); }
+    template <class U> bool operator==(const counted_ptr<U>& x) { return get() == x.get(); }
+    template <class U> bool operator<(const counted_ptr<U>& x) { return get() < x.get(); }
+
+  private:
+    T* ptr_;
+};
+
+#if PN_USE_BOOST
+template <class T> inline void intrusive_ptr_add_ref(const T* p) { incref(p); }
+template <class T> inline void intrusive_ptr_release(const T* p) { decref(p); }
+#endif
+
+///@cond INTERNAL
+class pn_counted {};
+void incref(const pn_counted*);
+void decref(const pn_counted*);
+///@endcond
+
+/// Reference counted proton types are convertible to smart pointer types.
+template <class T> class ptr_convetible {
+ public:
+    operator counted_ptr<T>() { return counted_ptr<T>(static_cast<T*>(this)); }
+    operator counted_ptr<const T>() const { return counted_ptr<const T>(static_cast<const T*>(this)); }
+#if PN_USE_CPP11
+    // TODO aconway 2015-08-21: need weak pointer context for efficient shared_ptr
+    operator std::shared_ptr<T>() { return std::shared_ptr<T>(incref(this)); }
+    operator std::shared_ptr<const T>() const { return std::shared_ptr<const T>(incref(this)); }
+    operator std::unique_ptr<T>() { return std::unique_ptr<T>(incref(this)); }
+    operator std::unique_ptr<const T>() const { return std::unique_ptr<const T>(incref(this)); }
+#endif
+#if PN_USE_BOOST
+    // TODO aconway 2015-08-21: need weak pointer context for efficient shared_ptr
+    operator boost::shared_ptr<T>() { return boost::shared_ptr<T>(incref(this)); }
+    operator boost::shared_ptr<const T>() const { return boost::shared_ptr<const T>(incref(this)); }
+    operator boost::intrusive_ptr<T>() { return boost::intrusive_ptr<T>(this); }
+    operator boost::intrusive_ptr<const T>() const { return boost::intrusive_ptr<const T>(this); }
+#endif
+
+  private:
+    T* incref() { proton::incref(static_cast<T*>(this)); return static_cast<T*>(this); }
+    const T* incref() const { proton::incref(this); return static_cast<const T*>(this); }
+};
+
+/**
+ * Some proton C structs are reference counted. The C++ facade for such structs can be
+ * converted to any of the following smart pointers: std::shared_ptr, std::unique_ptr,
+ * boost::shared_ptr, boost::intrusive_ptr.
+ *
+ * unique_ptr takes ownership of a single *reference* not the underlying struct,
+ * so it is safe to have multiple unique_ptr to the same facade object or to mix
+ * unique_ptr with shared_ptr etc.
+ *
+ * Deleting a counted_facade subclass actually calls `pn_decref` to remove a reference.
+ */
+template <class P, class T> class counted_facade :
+        public facade<P, T>, public pn_counted, public ptr_convetible<T>
+{
+  public:
+
+    /// Deleting a counted_facade actually calls `pn_decref` to remove a reference.
+    void operator delete(void* p) { decref(reinterpret_cast<pn_counted*>(p)); }
+
+    operator counted_ptr<T>() { return counted_ptr<T>(static_cast<T*>(this)); }
+    operator counted_ptr<const T>() const { return counted_ptr<const T>(static_cast<const T*>(this)); }
+#if PN_USE_CPP11
+    // TODO aconway 2015-08-21: need weak pointer context for efficient shared_ptr
+    operator std::shared_ptr<T>() { return std::shared_ptr<T>(new_reference(this)); }
+    operator std::shared_ptr<const T>() const { return std::shared_ptr<const T>(new_reference(this)); }
+    operator std::unique_ptr<T>() { return std::unique_ptr<T>(new_reference(this)); }
+    operator std::unique_ptr<const T>() const { return std::unique_ptr<const T>(new_reference(this)); }
+#endif
+#if PN_USE_BOOST
+    // TODO aconway 2015-08-21: need weak pointer context for efficient shared_ptr
+    operator boost::shared_ptr<T>() { return boost::shared_ptr<T>(new_reference(this)); }
+    operator boost::shared_ptr<const T>() const { return boost::shared_ptr<const T>(new_reference(this)); }
+    operator boost::intrusive_ptr<T>() { return boost::intrusive_ptr<T>(this); }
+    operator boost::intrusive_ptr<const T>() const { return boost::intrusive_ptr<const T>(this); }
+#endif
+
+    /** Get a pointer to a new reference to the underlying object.
+     * You must delete the returned pointer to release the reference.
+     * It is safer to convert to one of the supported smart pointer types.
+     */
+    T* new_reference() { proton::incref(this); return static_cast<T*>(this); }
+    const T* new_reference() const { proton::incref(this); return static_cast<const T*>(this); }
+
+  private:
+    counted_facade(const counted_facade&);
+    counted_facade& operator=(const counted_facade&);
+};
+
+///@cond INTERNAL
+///Base class for reference counted objects other than proton struct facade types.
+class counted {
+  protected:
+    counted();
+    virtual ~counted();
+
+  private:
+    counted(const counted&);
+    counted& operator=(const counted&);
+    int refcount_;
+
+    friend void incref(const counted* p);
+    friend void decref(const counted* p);
+  template <class T> friend class counted_ptr;
+};
+
+void incref(const counted* p);
+void decref(const counted* p);
+///@endcond
+
+}
+#endif  /*!PROTON_CPP_FACADE_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/handle.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/handle.hpp b/proton-c/bindings/cpp/include/proton/handle.hpp
deleted file mode 100644
index acff27d..0000000
--- a/proton-c/bindings/cpp/include/proton/handle.hpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef PROTON_CPP_HANDLE_H
-#define PROTON_CPP_HANDLE_H
-
-/*
- *
- * 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/export.hpp"
-
-namespace proton {
-
-///@cond INTERNAL
-template <class> class private_impl_ref;
-///@endcond INTERNAL
-
-/**
- * A handle is like a pointer: refers to an underlying implementation object.
- * Copying the handle does not copy the object.
- *
- * A handle can be null, use `if (handle)` or `if (!handle)` to test for a null handle.
- */
-template <class T> class handle {
-  public:
-    operator bool() const { return impl_; }
-    bool operator !() const { return !impl_; }
-
-    /** Operator ==  equal if they point to same non-null object*/
-    bool operator ==(const handle<T>& other) const { return impl_ == other.impl_; }
-    bool operator !=(const handle<T>& other) const { return impl_ != other.impl_; }
-
-    void swap(handle<T>& h) { T* t = h.impl_; h.impl_ = impl_; impl_ = t; }
-
-  private:
-    // Not implemented, subclasses must implement.
-    handle(const handle&);
-    handle& operator=(const handle&);
-
-  protected:
-    typedef T Impl;
-    handle() : impl_() {}
-
-    mutable Impl* impl_;
-
-  friend class private_impl_ref<T>;
-};
-
-}
-
-#endif  /*!PROTON_CPP_HANDLE_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/handler.hpp b/proton-c/bindings/cpp/include/proton/handler.hpp
index cb4ff81..f5f40c1 100644
--- a/proton-c/bindings/cpp/include/proton/handler.hpp
+++ b/proton-c/bindings/cpp/include/proton/handler.hpp
@@ -28,8 +28,14 @@
 
 namespace proton {
 
-/// Base class for event handlers.
-/// Handlers form a tree, a handler is a vector of pointers to child handlers.
+/** Base class for event handlers.
+ *
+ * A handler can have child handlers which are called in order, after the parent handler.
+ *
+ * Note: Event handlers are not deleted by the proton library, they must not be
+ * deleted while they are still in use. You can allocate a handler with `new` and
+ * call `delete this` in the appropriate `on_*_closed` or `on_*_final` event if you wish.
+ */
 class handler : public std::vector<handler*> {
   public:
     PN_CPP_EXTERN handler();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/link.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/link.hpp b/proton-c/bindings/cpp/include/proton/link.hpp
index 05ca742..77d88ae 100644
--- a/proton-c/bindings/cpp/include/proton/link.hpp
+++ b/proton-c/bindings/cpp/include/proton/link.hpp
@@ -21,23 +21,24 @@
  * under the License.
  *
  */
-#include "proton/export.hpp"
-#include "proton/wrapper.hpp"
 #include "proton/endpoint.hpp"
+#include "proton/export.hpp"
+#include "proton/message.hpp"
 #include "proton/terminus.hpp"
 #include "proton/types.h"
-#include <string>
+#include "proton/facade.hpp"
 
-struct pn_connection_t;
+#include <string>
 
 namespace proton {
 
+class sender;
+class receiver;
+
 /** Messages are transferred across a link. Base class for sender, receiver. */
-class link : public endpoint, public wrapper<pn_link_t>
+class link : public counted_facade<pn_link_t, link>, public endpoint
 {
   public:
-    PN_CPP_EXTERN link(pn_link_t * = 0);
-
     /** Locally open the link, not complete till messaging_handler::on_link_opened or
      * proton_handler::link_remote_open
      */
@@ -52,23 +53,40 @@ class link : public endpoint, public wrapper<pn_link_t>
     PN_CPP_EXTERN bool is_sender();
     /** True if link is a receiver */
     PN_CPP_EXTERN bool is_receiver();
+    /** Return sender pointer. @throw if link is not a sender. */
+    PN_CPP_EXTERN class sender& sender();
+    /** Return receiver pointer. @throw if link is not a receiver. */
+    PN_CPP_EXTERN class receiver& receiver();
     /** Credit available on the link */
     PN_CPP_EXTERN int credit();
-    /** Local source of the link */
-    PN_CPP_EXTERN terminus source();
-    /** Local target of the link */
-    PN_CPP_EXTERN terminus target();
-    /** Remote source of the link */
-    PN_CPP_EXTERN terminus remote_source();
-    /** Remote target of the link */
-    PN_CPP_EXTERN terminus remote_target();
+
+    /** True if link has source */
+    PN_CPP_EXTERN bool has_source();
+    /** True if link has target */
+    PN_CPP_EXTERN bool has_target();
+    /** True if link has remote source */
+    PN_CPP_EXTERN bool has_remote_source();
+    /** True if link has remote target */
+    PN_CPP_EXTERN bool has_remote_target();
+
+    /** Local source of the link. @throw error if !has_source() */
+    PN_CPP_EXTERN terminus& source();
+    /** Local target of the link. @throw error if !has_target() */
+    PN_CPP_EXTERN terminus& target();
+    /** Remote source of the link. @throw error if !has_remote_source() */
+    PN_CPP_EXTERN terminus& remote_source();
+    /** Remote target of the link. @throw error if !has_remote_target() */
+    PN_CPP_EXTERN terminus& remote_target();
+
     /** Link name */
     PN_CPP_EXTERN std::string name();
 
-    /** Next link that matches state mask. @see endpoint::state */
-    PN_CPP_EXTERN link next(endpoint::state mask);
+    /** Next link that matches state mask. @see endpoint::state.
+     * @return 0 if none, do not delete returned pointer
+     */
+    PN_CPP_EXTERN link* next(endpoint::state mask);
 
-    /** Connection of the link */
+    /** Connection that owns this link */
     PN_CPP_EXTERN class connection &connection();
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/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 6f98fe8..43105a9 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -22,8 +22,8 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/value.hpp"
-#include "proton/message.hpp"
+#include "proton/data.hpp"
+#include "proton/facade.hpp"
 #include <string>
 
 struct pn_message_t;
@@ -33,35 +33,16 @@ namespace proton {
 class link;
 class delivery;
 
-/** An AMQP message.
- *
- * NOTE: This class has value semantics, unlike other proton wrapper types.  The
- * copy constructor and assignment make a copy of the underlying pn_message_t
- * object.  You can get at the underlying pn_message_t* by calling get() or
- * release(), or use std::swap to move the data from one proton::message to
- * another without copying.
- *
- // FIXME aconway 2015-08-12: support move semantics assignment for C++11
- */
+class message;
 
-class message
+/** An AMQP message. Not directly construct-able, use create() or value<message>.*/
+class message : public facade<pn_message_t, message>
 {
   public:
-    PN_CPP_EXTERN message();
-    /** Takes ownership of the pn_message_t, calls pn_message_free on destruction. */
-    PN_CPP_EXTERN message(pn_message_t *);
-    /// Makes a copy of the other message.
-    PN_CPP_EXTERN message(const message&);
-    /// Makes a copy of the other message.
-    PN_CPP_EXTERN message& operator=(const message&);
-
-    PN_CPP_EXTERN ~message();
+    PN_CPP_EXTERN static PN_UNIQUE_OR_AUTO_PTR<message> create();
 
-    /// Access the underlying pn_message_t, note it will be freed by ~message.
-    PN_CPP_EXTERN pn_message_t *get();
-
-    /// Forget the underlying pn_message_t, the message is cleared. Caller must call pn_message_free.
-    PN_CPP_EXTERN pn_message_t *release();
+    /// Copy data from m to this.
+    message& operator=(const message& m);
 
     /** Clear the message content */
     PN_CPP_EXTERN void clear();
@@ -70,9 +51,10 @@ class message
     ///@{
 
     /// Globally unique identifier, can be an a string, an unsigned long, a uuid or a binary value.
-    PN_CPP_EXTERN void id(const value& id);
+    PN_CPP_EXTERN void id(const data& id);
     /// Globally unique identifier, can be an a string, an unsigned long, a uuid or a binary value.
-    PN_CPP_EXTERN value id() const;
+    PN_CPP_EXTERN const data& id() const;
+    PN_CPP_EXTERN data& id();
 
     PN_CPP_EXTERN void user(const std::string &user);
     PN_CPP_EXTERN std::string user() const;
@@ -87,9 +69,10 @@ class message
     PN_CPP_EXTERN std::string reply_to() const;
 
     /// Correlation identifier, can be an a string, an unsigned long, a uuid or a binary value.
-    PN_CPP_EXTERN void correlation_id(const value&);
+    PN_CPP_EXTERN void correlation_id(const data&);
     /// Correlation identifier, can be an a string, an unsigned long, a uuid or a binary value.
-    PN_CPP_EXTERN value correlation_id() const;
+    PN_CPP_EXTERN const data& correlation_id() const;
+    PN_CPP_EXTERN data& correlation_id();
 
     PN_CPP_EXTERN void content_type(const std::string &s);
     PN_CPP_EXTERN std::string content_type() const;
@@ -110,24 +93,17 @@ class message
     PN_CPP_EXTERN std::string reply_to_group_id() const;
     ///@}
 
-    /** Set the body to a proton::value, copies the value. */
-    PN_CPP_EXTERN void body(const value&);
-
-    /** Set the body to any type T that can be converted to a proton::value */
-    template <class T> void body(const T& v) { body(value(v)); }
+    /** Set the body. If data has more than one value, each is encoded as an AMQP section. */
+    PN_CPP_EXTERN void body(const data&);
 
-    /** Set the body to a sequence of values, each value is encoded as an AMQP section. */
-    PN_CPP_EXTERN void body(const values&);
+    /** Set the body to any type T that can be converted to proton::data */
+    template <class T> void body(const T& v) { body().clear(); body().encoder() << v; }
 
-    /** Get the body values, there may be more than one.
-     * Note the reference will be invalidated by destroying the message or calling swap.
-     */
-    PN_CPP_EXTERN const values& body() const;
+    /** Get the body values. */
+    PN_CPP_EXTERN const data& body() const;
 
-    /** Get a reference to the body values, can be modified in-place.
-     * Note the reference will be invalidated by destroying the message or calling swap.
-     */
-    PN_CPP_EXTERN values& body();
+    /** Get a reference to the body data, can be modified in-place. */
+    PN_CPP_EXTERN data& body();
 
     // TODO aconway 2015-06-17: consistent and flexible treatment of buffers.
     // Allow convenient std::string encoding/decoding (with re-use of existing
@@ -142,13 +118,104 @@ class message
     PN_CPP_EXTERN void decode(const std::string &data);
 
     /// Decode the message from link corresponding to delivery.
-    PN_CPP_EXTERN void decode(proton::link link, proton::delivery);
+    PN_CPP_EXTERN void decode(proton::link&, proton::delivery&);
 
-  private:
-    pn_message_t *impl_;
-    mutable values body_;
+    void operator delete(void*);
 };
 
+
+/** A message with value semantics */
+class message_value {
+  public:
+    message_value() : message_(message::create()) {}
+    message_value(const message_value& x) : message_(message::create()) { *message_ = *x.message_; }
+    message_value(const message& x) : message_(message::create()) { *message_ = x; }
+    message_value& operator=(const message_value& x) { *message_ = *x.message_; return *this; }
+    message_value& operator=(const message& x) { *message_ = x; return *this; }
+
+    operator message&() { return *message_; }
+    operator const message&() const { return *message_; }
+
+    /** Clear the message content */
+    void clear() { message_->clear(); }
+
+    ///@name Message properties
+    ///@{
+
+    /// Globally unique identifier, can be an a string, an unsigned long, a uuid or a binary value.
+    void id(const data& id) { message_->id(id); }
+    /// Globally unique identifier, can be an a string, an unsigned long, a uuid or a binary value.
+    const data& id() const { return message_->id(); }
+    data& id() { return message_->id(); }
+
+    void user(const std::string &user) { message_->user(user); }
+    std::string user() const { return message_->user(); }
+
+    void address(const std::string &addr) { message_->address(addr); }
+    std::string address() const { return message_->address(); }
+
+    void subject(const std::string &s) { message_->subject(s); }
+    std::string subject() const { return message_->subject(); }
+
+    void reply_to(const std::string &s) { message_->reply_to(s); }
+    std::string reply_to() const { return message_->reply_to(); }
+
+    /// Correlation identifier, can be an a string, an unsigned long, a uuid or a binary value.
+    void correlation_id(const data& d) { message_->correlation_id(d); }
+    /// Correlation identifier, can be an a string, an unsigned long, a uuid or a binary value.
+    const data& correlation_id() const { return message_->correlation_id(); }
+    data& correlation_id() { return message_->correlation_id(); }
+
+    void content_type(const std::string &s) { message_->content_type(s); }
+    std::string content_type() const { return message_->content_type(); }
+
+    void content_encoding(const std::string &s) { message_->content_encoding(s); }
+    std::string content_encoding() const { return message_->content_encoding(); }
+
+    void expiry(amqp_timestamp t) { message_->expiry(t); }
+    amqp_timestamp expiry() const { return message_->expiry(); }
+
+    void creation_time(amqp_timestamp t) { message_->creation_time(t); }
+    amqp_timestamp creation_time() const { return message_->creation_time(); }
+
+    void group_id(const std::string &s) { message_->group_id(s); }
+    std::string group_id() const { return message_->group_id(); }
+
+    void reply_to_group_id(const std::string &s) { message_->reply_to_group_id(s); }
+    std::string reply_to_group_id() const { return message_->reply_to_group_id(); }
+    ///@}
+
+    /** Set the body. If data has more than one value, each is encoded as an AMQP section. */
+    void body(const data& d) { message_->body(d); }
+
+    /** Set the body to any type T that can be converted to proton::data */
+    template <class T> void body(const T& v) { message_->body(v); }
+
+    /** Get the body values. */
+    const data& body() const { return message_->body(); }
+
+    /** Get a reference to the body data, can be modified in-place. */
+    data& body() { return message_->body(); }
+
+    // TODO aconway 2015-06-17: consistent and flexible treatment of buffers.
+    // Allow convenient std::string encoding/decoding (with re-use of existing
+    // string capacity) but also need to allow encoding/decoding of non-string
+    // buffers. Introduce a buffer type with begin/end pointers?
+
+    /** Encode the message into string data */
+    void encode(std::string &data) const { message_->encode(data); }
+    /** Retrun encoded message as a string */
+    std::string encode() const { return message_->encode(); }
+    /** Decode from string data into the message. */
+    void decode(const std::string &data) { message_->decode(data); }
+
+    /// Decode the message from link corresponding to delivery.
+    void decode(proton::link& l, proton::delivery& d) { message_->decode(l, d); }
+
+  private:
+    PN_UNIQUE_OR_AUTO_PTR<message> message_;
+};
+    
 }
 
 #endif  /*!PROTON_CPP_MESSAGE_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/messaging_adapter.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/messaging_adapter.hpp b/proton-c/bindings/cpp/include/proton/messaging_adapter.hpp
index 06293c0..ded1309 100644
--- a/proton-c/bindings/cpp/include/proton/messaging_adapter.hpp
+++ b/proton-c/bindings/cpp/include/proton/messaging_adapter.hpp
@@ -22,7 +22,7 @@
  *
  */
 
-#include "proton/wrapper.hpp"
+#include "proton/facade.hpp"
 #include "proton/messaging_handler.hpp"
 
 #include "proton/messaging_event.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/messaging_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/messaging_event.hpp b/proton-c/bindings/cpp/include/proton/messaging_event.hpp
index 9eb4905..0dbe7e4 100644
--- a/proton-c/bindings/cpp/include/proton/messaging_event.hpp
+++ b/proton-c/bindings/cpp/include/proton/messaging_event.hpp
@@ -29,6 +29,7 @@ namespace proton {
 class handler;
 class container;
 class connection;
+class message;
 
 /** An event for the proton::messaging_handler */
 class messaging_event : public proton_event
@@ -85,18 +86,19 @@ class messaging_event : public proton_event
 
     virtual PN_CPP_EXTERN void dispatch(handler &h);
     virtual PN_CPP_EXTERN class connection &connection();
-    virtual PN_CPP_EXTERN class sender sender();
-    virtual PN_CPP_EXTERN class receiver receiver();
-    virtual PN_CPP_EXTERN class link link();
+    virtual PN_CPP_EXTERN class sender& sender();
+    virtual PN_CPP_EXTERN class receiver& receiver();
+    virtual PN_CPP_EXTERN class link& link();
+    virtual PN_CPP_EXTERN class delivery& delivery();
     virtual PN_CPP_EXTERN class message& message();
-    virtual PN_CPP_EXTERN class delivery delivery();
+
     PN_CPP_EXTERN event_type type() const;
 
   private:
   friend class messaging_adapter;
     event_type type_;
     proton_event *parent_event_;
-    class message message_;
+    message_value message_;
     messaging_event operator=(const messaging_event&);
     messaging_event(const messaging_event&);
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/messaging_handler.hpp b/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
index 7de6ebd..55d1867 100644
--- a/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
+++ b/proton-c/bindings/cpp/include/proton/messaging_handler.hpp
@@ -23,7 +23,6 @@
  */
 
 #include "proton/proton_handler.hpp"
-#include "proton/acking.hpp"
 #include "proton/event.h"
 
 namespace proton {
@@ -36,7 +35,7 @@ class messaging_adapter;
  * over-ride event handling member functions.
  * @see proton::messaging_event for meaning of events.
  */
-class messaging_handler : public proton_handler , public acking
+class messaging_handler : public proton_handler
 {
   public:
     /** Create a messaging_handler

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/proton_event.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/proton_event.hpp b/proton-c/bindings/cpp/include/proton/proton_event.hpp
index 1243717..00413d4 100644
--- a/proton-c/bindings/cpp/include/proton/proton_event.hpp
+++ b/proton-c/bindings/cpp/include/proton/proton_event.hpp
@@ -271,10 +271,10 @@ class proton_event : public event
     virtual PN_CPP_EXTERN void dispatch(handler &h);
     virtual PN_CPP_EXTERN class container &container();
     virtual PN_CPP_EXTERN class connection &connection();
-    virtual PN_CPP_EXTERN class sender sender();
-    virtual PN_CPP_EXTERN class receiver receiver();
-    virtual PN_CPP_EXTERN class link link();
-    virtual PN_CPP_EXTERN class delivery delivery();
+    virtual PN_CPP_EXTERN class sender& sender();
+    virtual PN_CPP_EXTERN class receiver& receiver();
+    virtual PN_CPP_EXTERN class link& link();
+    virtual PN_CPP_EXTERN class delivery& delivery();
 
     /** Get type of event */
     PN_CPP_EXTERN event_type type();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/receiver.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/receiver.hpp b/proton-c/bindings/cpp/include/proton/receiver.hpp
index 578e641..3c8a6f8 100644
--- a/proton-c/bindings/cpp/include/proton/receiver.hpp
+++ b/proton-c/bindings/cpp/include/proton/receiver.hpp
@@ -32,12 +32,9 @@ struct pn_connection_t;
 namespace proton {
 
 /// A receiving link
-class receiver : public link
+class receiver : public link, public ptr_convetible<receiver>
 {
   public:
-    /// @throw proton::error if (link && !link.is_receiver())
-    PN_CPP_EXTERN receiver(link = link());
-
     /// Add credit to the link
     PN_CPP_EXTERN void flow(int count);
 };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/sender.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/sender.hpp b/proton-c/bindings/cpp/include/proton/sender.hpp
index 7260f72..c08ba5a 100644
--- a/proton-c/bindings/cpp/include/proton/sender.hpp
+++ b/proton-c/bindings/cpp/include/proton/sender.hpp
@@ -34,14 +34,11 @@ struct pn_connection_t;
 namespace proton {
 
 /// A sending link
-class sender : public link
+class sender : public link, public ptr_convetible<sender>
 {
   public:
-    /// @throw proton::error if (link && !link.is_sender())
-    PN_CPP_EXTERN sender(link = link());
-
     /// Send a message on the link.
-    PN_CPP_EXTERN delivery send(message &m);
+    PN_CPP_EXTERN delivery& send(message &m);
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/session.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/session.hpp b/proton-c/bindings/cpp/include/proton/session.hpp
index 3eb3fdd..561b90b 100644
--- a/proton-c/bindings/cpp/include/proton/session.hpp
+++ b/proton-c/bindings/cpp/include/proton/session.hpp
@@ -38,11 +38,9 @@ class handler;
 class transport;
 
 /** A session is a collection of links */
-class session : public endpoint, public wrapper<pn_session_t>
+class session : public counted_facade<pn_session_t, session>, public endpoint
 {
   public:
-    PN_CPP_EXTERN session(pn_session_t * = 0);
-
     /** Initiate local open, not complete till messaging_handler::on_session_opened()
      * or proton_handler::on_session_remote_open()
      */
@@ -54,11 +52,13 @@ class session : public endpoint, public wrapper<pn_session_t>
     PN_CPP_EXTERN void close();
 
     /// Get connection
-    PN_CPP_EXTERN virtual class connection &connection();
+    PN_CPP_EXTERN class connection &connection();
+
+    // FIXME aconway 2015-08-31: default generate unique name.
     /// Create a receiver link
-    PN_CPP_EXTERN receiver create_receiver(const std::string& name);
+    PN_CPP_EXTERN receiver& create_receiver(const std::string& name);
     /// Create a sender link
-    PN_CPP_EXTERN sender create_sender(const std::string& name);
+    PN_CPP_EXTERN sender& create_sender(const std::string& name);
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/sync_request_response.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/sync_request_response.hpp b/proton-c/bindings/cpp/include/proton/sync_request_response.hpp
index 397e181..d91929c 100644
--- a/proton-c/bindings/cpp/include/proton/sync_request_response.hpp
+++ b/proton-c/bindings/cpp/include/proton/sync_request_response.hpp
@@ -26,7 +26,6 @@
 #include "proton/blocking_receiver.hpp"
 #include "proton/blocking_sender.hpp"
 #include <string>
-#include <memory>
 
 struct pn_message_t;
 struct pn_data_t;
@@ -49,7 +48,7 @@ class sync_request_response : public messaging_handler
     std::string address_;
     blocking_sender sender_;
     blocking_receiver receiver_;
-    std::auto_ptr<message> response_;
+    PN_UNIQUE_OR_AUTO_PTR<message> response_;
     amqp_ulong correlation_id_;
 };
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/terminus.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/terminus.hpp b/proton-c/bindings/cpp/include/proton/terminus.hpp
index 7c63582..4bb9651 100644
--- a/proton-c/bindings/cpp/include/proton/terminus.hpp
+++ b/proton-c/bindings/cpp/include/proton/terminus.hpp
@@ -24,6 +24,7 @@
 #include "proton/export.hpp"
 
 #include "proton/link.h"
+#include "proton/facade.hpp"
 #include <string>
 
 namespace proton {
@@ -33,7 +34,7 @@ class link;
 /** A terminus represents one end of a link.
  * The source terminus is where originate, the target terminus is where they go.
  */
-class terminus : public wrapper<pn_terminus_t>
+class terminus : public counted_facade<pn_terminus_t, terminus>
 {
   public:
     /// Type of terminus
@@ -68,11 +69,6 @@ class terminus : public wrapper<pn_terminus_t>
     PN_CPP_EXTERN void address(const std::string &);
     PN_CPP_EXTERN bool is_dynamic();
     PN_CPP_EXTERN void dynamic(bool);
-
-  private:
-    pn_link_t* link_;
-    PN_CPP_EXTERN terminus(pn_terminus_t * = 0, pn_link_t * = 0);
-  friend class link;
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/transport.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/transport.hpp b/proton-c/bindings/cpp/include/proton/transport.hpp
index 6bb6f5b..c909166 100644
--- a/proton-c/bindings/cpp/include/proton/transport.hpp
+++ b/proton-c/bindings/cpp/include/proton/transport.hpp
@@ -21,32 +21,22 @@
  * under the License.
  *
  */
+
+#include "proton/facade.hpp"
+
 #include "proton/export.hpp"
-#include "proton/transport.h"
-#include <string>
 
-struct pn_connection_t;
+struct pn_transport_t;
 
 namespace proton {
 
 class connection;
 
 /** Represents a connection transport */
-class transport
+class transport : public counted_facade<pn_transport_t, transport>
 {
   public:
-    PN_CPP_EXTERN transport();
-    PN_CPP_EXTERN ~transport();
-
-    /** Bind the transport to an AMQP connection */
-    PN_CPP_EXTERN void bind(connection &c);
-
-    class connection* connection() const { return connection_; }
-    pn_transport_t* pn_transport() const { return pn_transport_; }
-
-  private:
-    class connection *connection_;
-    pn_transport_t *pn_transport_;
+    class connection* connection();
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/type_traits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/type_traits.hpp b/proton-c/bindings/cpp/include/proton/type_traits.hpp
index aa1f610..df33053 100644
--- a/proton-c/bindings/cpp/include/proton/type_traits.hpp
+++ b/proton-c/bindings/cpp/include/proton/type_traits.hpp
@@ -26,9 +26,10 @@
  * @cond INTERNAL
  */
 
+#include "proton/config.hpp"
 #include "proton/types.hpp"
 
-#ifdef USE_CPP11
+#if PN_USE_CPP11
 #include <type_traits>
 #else
 namespace std {
@@ -75,7 +76,7 @@ namespace proton {
 
 // Metafunction returning exact AMQP type associated with a C++ type
 template <class T> struct type_id_of;
-template<> struct type_id_of<amqp_null> { static const type_id value=NULl_; };
+template<> struct type_id_of<amqp_null> { static const type_id value=NULL_; };
 template<> struct type_id_of<amqp_bool> { static const type_id value=BOOL; };
 template<> struct type_id_of<amqp_ubyte> { static const type_id value=UBYTE; };
 template<> struct type_id_of<amqp_byte> { static const type_id value=BYTE; };

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/types.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/types.hpp b/proton-c/bindings/cpp/include/proton/types.hpp
index d5cf23c..785e60f 100644
--- a/proton-c/bindings/cpp/include/proton/types.hpp
+++ b/proton-c/bindings/cpp/include/proton/types.hpp
@@ -25,7 +25,8 @@
 
 #include "proton/export.hpp"
 #include "proton/cstdint.hpp"
-#include <proton/codec.h>
+#include "proton/comparable.hpp"
+#include <proton/codec.h>       // TODO aconway 2015-08-25: exposes proton header.
 #include <algorithm>
 #include <bitset>
 #include <string>
@@ -36,7 +37,7 @@ namespace proton {
 
 /** type_id identifies an AMQP type. */
 enum type_id {
-    NULl_=PN_NULL,              ///< The null type, contains no data.
+    NULL_=PN_NULL,              ///< The null type, contains no data.
     BOOL=PN_BOOL,               ///< Boolean true or false.
     UBYTE=PN_UBYTE,             ///< Unsigned 8 bit integer.
     BYTE=PN_BYTE,               ///< Signed 8 bit integer.
@@ -63,18 +64,6 @@ enum type_id {
     MAP=PN_MAP                  ///< A sequence of key:value pairs, may be of mixed types.
 };
 
-/// Internal base class to provide comparison operators.
-template <class T> struct comparable {};
-///@cond INTERNAL
-template<class T> bool operator<(const comparable<T>& a, const comparable<T>& b) {
-    return static_cast<const T&>(a) < static_cast<const T&>(b); // operator < provided by type T
-}
-template<class T> bool operator>(const comparable<T>& a, const comparable<T>& b) { return b < a; }
-template<class T> bool operator<=(const comparable<T>& a, const comparable<T>& b) { return !(a > b); }
-template<class T> bool operator>=(const comparable<T>& a, const comparable<T>& b) { return !(a < b); }
-template<class T> bool operator==(const comparable<T>& a, const comparable<T>& b) { return a <= b && b <= a; }
-template<class T> bool operator!=(const comparable<T>& a, const comparable<T>& b) { return !(a == b); }
-
 PN_CPP_EXTERN pn_bytes_t pn_bytes(const std::string&);
 PN_CPP_EXTERN std::string str(const pn_bytes_t& b);
 ///@endcond
@@ -233,7 +222,7 @@ PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, type_id);
  * for examples of use.
  */
 struct start {
-    PN_CPP_EXTERN start(type_id type=NULl_, type_id element=NULl_, bool described=false, size_t size=0);
+    PN_CPP_EXTERN start(type_id type=NULL_, type_id element=NULL_, bool described=false, size_t size=0);
     type_id type;            ///< The container type: ARRAY, LIST, MAP or DESCRIBED.
     type_id element;         ///< the element type for array only.
     bool is_described;       ///< true if first value is a descriptor.

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/url.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/url.hpp b/proton-c/bindings/cpp/include/proton/url.hpp
index f9c5576..cffc0a4 100644
--- a/proton-c/bindings/cpp/include/proton/url.hpp
+++ b/proton-c/bindings/cpp/include/proton/url.hpp
@@ -19,7 +19,7 @@
  * under the License.
  */
 
-#include "proton/wrapper.hpp"
+#include "proton/facade.hpp"
 #include "proton/error.hpp"
 #include <iosfwd>
 
@@ -48,14 +48,14 @@ class url {
     /** Parse url_str as an AMQP URL. If defaults is true, fill in defaults for missing values
      *  otherwise return an empty string for missing values.
      *  Note: converts automatically from string.
-     *@throws bad_url if URL is invalid.
+     *@throw bad_url if URL is invalid.
      */
     PN_CPP_EXTERN url(const std::string& url_str, bool defaults=true);
 
     /** Parse url_str as an AMQP URL. If defaults is true, fill in defaults for missing values
      *  otherwise return an empty string for missing values.
      *  Note: converts automatically from string.
-     *@throws bad_url if URL is invalid.
+     *@throw bad_url if URL is invalid.
      */
     PN_CPP_EXTERN url(const char* url_str, bool defaults=true);
 
@@ -64,12 +64,12 @@ class url {
     PN_CPP_EXTERN url& operator=(const url&);
 
     /** Parse a string as a URL 
-     *@throws bad_url if URL is invalid.
+     *@throw bad_url if URL is invalid.
      */
     PN_CPP_EXTERN void parse(const std::string&);
 
     /** Parse a string as a URL 
-     *@throws bad_url if URL is invalid.
+     *@throw bad_url if URL is invalid.
      */
     PN_CPP_EXTERN void parse(const char*);
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/value.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/value.hpp b/proton-c/bindings/cpp/include/proton/value.hpp
deleted file mode 100644
index 046a98b..0000000
--- a/proton-c/bindings/cpp/include/proton/value.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef VALUE_H
-#define VALUE_H
-/*
- * 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/values.hpp"
-
-namespace proton {
-
-/** Holds a single AMQP value. */
-class value {
-  public:
-    PN_CPP_EXTERN value();
-    PN_CPP_EXTERN value(const value&);
-    /** Converting constructor from any settable value */
-    template <class T> explicit value(const T& v);
-
-    PN_CPP_EXTERN ~value();
-
-    PN_CPP_EXTERN value& operator=(const value&);
-
-    PN_CPP_EXTERN type_id type() const;
-
-    /** Set the value. */
-    template<class T> void set(const T& value);
-    /** Get the value. */
-    template<class T> void get(T& value) const;
-    /** Get the value */
-    template<class T> T get() const;
-
-    /** Assignment sets the value */
-    template<class T> value& operator=(const T& value);
-
-    /** Conversion operator gets  the value */
-    template<class T> operator T() const;
-
-    /** insert a value into an encoder. */
-    PN_CPP_EXTERN friend encoder& operator<<(encoder&, const value&);
-
-    /** Extract a value from a decoder. */
-    PN_CPP_EXTERN friend decoder& operator>>(decoder&, value&);
-
-    /** Human readable format */
-    PN_CPP_EXTERN friend std::ostream& operator<<(std::ostream&, const value&);
-
-    PN_CPP_EXTERN bool operator==(const value&) const;
-    PN_CPP_EXTERN bool operator !=(const value& v) const{ return !(*this == v); }
-
-    /** operator < makes value valid for use as a std::map key. */
-    PN_CPP_EXTERN bool operator<(const value&) const;
-    bool operator>(const value& v) const { return v < *this; }
-    bool operator<=(const value& v) const { return !(*this > v); }
-    bool operator>=(const value& v) const { return !(*this < v); }
-
-  private:
-    mutable values values_;
-};
-
-template<class T> void value::set(const T& value) {
-    values_.clear();
-    values_ << value;
-}
-
-template<class T> void value::get(T& v) const {
-    values& vv = const_cast<values&>(values_);
-    vv >> proton::rewind() >> v;
-}
-
-template<class T> T value::get() const { T value; get(value); return value; }
-
-template<class T> value& value::operator=(const T& value) { set(value); return *this; }
-
-template<class T> value::operator T() const { return get<T>(); }
-
-template<class T> value::value(const T& value) { set(value); }
-}
-
-#endif // VALUE_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/values.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/values.hpp b/proton-c/bindings/cpp/include/proton/values.hpp
deleted file mode 100644
index 1f7c650..0000000
--- a/proton-c/bindings/cpp/include/proton/values.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef VALUES_H
-#define VALUES_H
-/*
- * 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/encoder.hpp>
-#include <proton/decoder.hpp>
-
-namespace proton {
-
-
-/** Holds a sequence of AMQP values, allows inserting and extracting.
- *
- * After inserting values, call rewind() to extract them.
- */
-class values : public encoder, public decoder {
-  public:
-    PN_CPP_EXTERN values();
-    PN_CPP_EXTERN values(const values&);
-
-    /** Does not take ownership, just operates on the pn_data_t object. */
-    PN_CPP_EXTERN values(pn_data_t*);
-
-    PN_CPP_EXTERN ~values();
-
-    /** Copy data from another values */
-    PN_CPP_EXTERN values& operator=(const values&);
-
-  friend class value;
-  friend class message;
-};
-
-PN_CPP_EXTERN std::ostream& operator<<(std::ostream&, const values&);
-
-}
-
-#endif // VALUES_H

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/include/proton/wrapper.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/wrapper.hpp b/proton-c/bindings/cpp/include/proton/wrapper.hpp
deleted file mode 100644
index c9ad151..0000000
--- a/proton-c/bindings/cpp/include/proton/wrapper.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef PROTON_CPP_WRAPPER_H
-#define PROTON_CPP_WRAPPER_H
-
-/*
- *
- * 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/export.hpp"
-#include <utility>
-
-namespace proton {
-
-/**
- * wrapper is a base template for proton pointer wrappers.
- *
- * A pointer wrapper holds a pointer to a proton C struct type but provides C++
- * member functions to make it easier to call the C functions for that type.
- *
- * wrappers can be copied and assigned like pointers, copying a wrapper does not
- * copy the object pointed to. Wrappers can be null, given `wrapper w;` use `if
- * (w)` or `if (!w)` to test for null.
- *
- */
-template <class T> class wrapper {
-  public:
-    wrapper(T *p) : ptr_(p) {}
-    operator T*() const { return ptr_; }
-
-    // Use default copy and assign.
-
-    // @internal NOTE: derived classes can add members but they should have
-    // normal value semantics and be immutable or be pointers to shared mutable
-    // objects.
-
-    T* get() const { return ptr_; }
-
-    operator bool() const { return ptr_; }
-    bool operator !() const { return !ptr_; }
-
-    bool operator==(T* p) const { return ptr_ == p; }
-    bool operator!=(T* p) const { return ptr_ != p; }
-
-  protected:
-    T* ptr_;
-};
-
-}
-
-
-#endif  /*!PROTON_CPP_WRAPPER_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/acceptor.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/acceptor.cpp b/proton-c/bindings/cpp/src/acceptor.cpp
index f1892f7..4fc538c 100644
--- a/proton-c/bindings/cpp/src/acceptor.cpp
+++ b/proton-c/bindings/cpp/src/acceptor.cpp
@@ -25,8 +25,6 @@
 
 namespace proton {
 
-acceptor::acceptor(pn_acceptor_t *a) : wrapper<pn_acceptor_t>(a) {}
-
-void acceptor::close() { pn_acceptor_close(get()); }
+void acceptor::close() { pn_acceptor_close(pn_cast(this)); }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/acking.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/acking.cpp b/proton-c/bindings/cpp/src/acking.cpp
deleted file mode 100644
index b3453c7..0000000
--- a/proton-c/bindings/cpp/src/acking.cpp
+++ /dev/null
@@ -1,48 +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/acking.hpp"
-#include "proton/delivery.h"
-
-namespace proton {
-
-void acking::accept(delivery &d) {
-    settle(d, delivery::ACCEPTED);
-}
-
-void acking::reject(delivery &d) {
-    settle(d, delivery::REJECTED);
-}
-
-void acking::release(delivery &d, bool delivered) {
-    if (delivered)
-        settle(d, delivery::MODIFIED);
-    else
-        settle(d, delivery::RELEASED);
-}
-
-void acking::settle(delivery &d, delivery::state state) {
-    if (state)
-        pn_delivery_update(d.get(), state);
-    d.settle();
-}
-
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/blocking_connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking_connection.cpp b/proton-c/bindings/cpp/src/blocking_connection.cpp
index 762029e..3ac8dbc 100644
--- a/proton-c/bindings/cpp/src/blocking_connection.cpp
+++ b/proton-c/bindings/cpp/src/blocking_connection.cpp
@@ -56,8 +56,8 @@ void blocking_connection::wait(condition &cond, const std::string &msg, duration
 }
 
 blocking_sender blocking_connection::create_sender(const std::string &address, handler *h) {
-    sender sender = impl_->container_.create_sender(impl_->connection_, address, h);
-    return blocking_sender(*this, sender);
+    counted_ptr<sender> snd = impl_->container_.create_sender(impl_->connection_, address, h);
+    return blocking_sender(*this, snd);
 }
 
 namespace {
@@ -76,8 +76,8 @@ blocking_receiver blocking_connection::create_receiver(const std::string &addres
         handler = f;
     }
     fetcher_guard fg(f);
-    receiver receiver = impl_->container_.create_receiver(impl_->connection_, address, dynamic, handler);
-    blocking_receiver brcv(*this, receiver, f, credit);
+    counted_ptr<receiver> rcv = impl_->container_.create_receiver(impl_->connection_, address, dynamic, handler);
+    blocking_receiver brcv(*this, rcv, f, credit);
     return brcv;
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/blocking_connection_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking_connection_impl.hpp b/proton-c/bindings/cpp/src/blocking_connection_impl.hpp
index 17f8f57..e53dd81 100644
--- a/proton-c/bindings/cpp/src/blocking_connection_impl.hpp
+++ b/proton-c/bindings/cpp/src/blocking_connection_impl.hpp
@@ -57,7 +57,7 @@ class ssl_domain;
                             duration=duration(-1));
 
     container container_;
-    connection connection_;
+    counted_ptr<connection> connection_;
     url url_;
     duration timeout_;
     int refcount_;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/blocking_link.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking_link.cpp b/proton-c/bindings/cpp/src/blocking_link.cpp
index 648a8a6..d8110c6 100644
--- a/proton-c/bindings/cpp/src/blocking_link.cpp
+++ b/proton-c/bindings/cpp/src/blocking_link.cpp
@@ -52,7 +52,7 @@ struct link_not_open {
 
 blocking_link::blocking_link(blocking_connection *c, pn_link_t *pnl) : connection_(*c), link_(pnl) {
     std::string msg = "Opening link " + link_.name();
-    link_opened link_opened(link_.get());
+    link_opened link_opened(pn_cast(link_));
     connection_.wait(link_opened, msg);
     check_closed();
 }
@@ -61,13 +61,13 @@ blocking_link::~blocking_link() {}
 
 void blocking_link::wait_for_closed(duration timeout) {
     std::string msg = "Closing link " + link_.name();
-    link_closed link_closed(link_.get());
+    link_closed link_closed(pn_cast(link_));
     connection_.wait(link_closed, msg);
     check_closed();
 }
 
 void blocking_link::check_closed() {
-    pn_link_t * pn_link = link_.get();
+    pn_link_t * pn_link = pn_cast(link_);
     if (pn_link_state(pn_link) & PN_REMOTE_CLOSED) {
         link_.close();
         throw error(MSG("Link detached: " << link_.name()));
@@ -77,7 +77,7 @@ void blocking_link::check_closed() {
 void blocking_link::close() {
     link_.close();
     std::string msg = "Closing link " + link_.name();
-    link_not_open link_not_open(link_.get());
+    link_not_open link_not_open(pn_cast(link_));
     connection_.wait(link_not_open, msg);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/blocking_receiver.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking_receiver.cpp b/proton-c/bindings/cpp/src/blocking_receiver.cpp
index fe94d80..2f7b277 100644
--- a/proton-c/bindings/cpp/src/blocking_receiver.cpp
+++ b/proton-c/bindings/cpp/src/blocking_receiver.cpp
@@ -40,7 +40,7 @@ struct fetcher_has_message {
 
 
 blocking_receiver::blocking_receiver(blocking_connection &c, receiver &l, fetcher *f, int credit)
-    : blocking_link(&c, l.get()), fetcher_(f) {
+    : blocking_link(&c, &l), fetcher_(f) {
     std::string sa = link_.source().address();
     std::string rsa = link_.remote_source().address();
     if (!sa.empty() && sa.compare(rsa) != 0) {
@@ -50,7 +50,7 @@ blocking_receiver::blocking_receiver(blocking_connection &c, receiver &l, fetche
         throw error(MSG(txt));
     }
     if (credit)
-        pn_link_flow(link_.get(), credit);
+        pn_link_flow(pn_cast(link_), credit);
     if (fetcher_)
         fetcher_->incref();
 }
@@ -76,7 +76,7 @@ blocking_receiver::~blocking_receiver() {
 message blocking_receiver::receive(duration timeout) {
     if (!fetcher_)
         throw error(MSG("Can't call receive on this receiver as a handler was provided"));
-    receiver rcv(link_.get());
+    receiver rcv(pn_cast(link_));
     if (!rcv.credit())
         rcv.flow(1);
     std::string txt = "Receiving on receiver " + link_.name();
@@ -112,7 +112,7 @@ void blocking_receiver::settle(delivery::state state = delivery::NONE) {
 }
 
 void blocking_receiver::flow(int count) {
-    receiver rcv(link_.get());
+    receiver rcv(pn_cast(link_));
     rcv.flow(count);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/blocking_sender.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/blocking_sender.cpp b/proton-c/bindings/cpp/src/blocking_sender.cpp
index 4ddbb3c..5f0ff45 100644
--- a/proton-c/bindings/cpp/src/blocking_sender.cpp
+++ b/proton-c/bindings/cpp/src/blocking_sender.cpp
@@ -38,7 +38,7 @@ struct delivery_settled {
 } // namespace
 
 
-blocking_sender::blocking_sender(blocking_connection &c, sender l) : blocking_link(&c, l.get()) {
+blocking_sender::blocking_sender(blocking_connection &c, sender &l) : blocking_link(&c, pn_cast(l)) {
     std::string ta = link_.target().address();
     std::string rta = link_.remote_target().address();
     if (ta.empty() || ta.compare(rta) != 0) {
@@ -49,11 +49,11 @@ blocking_sender::blocking_sender(blocking_connection &c, sender l) : blocking_li
     }
 }
 
-delivery blocking_sender::send(message &msg, duration timeout) {
-    sender snd(link_.get());
-    delivery dlv = snd.send(msg);
+counted_ptr<delivery> blocking_sender::send(message &msg, duration timeout) {
+    sender snd(pn_cast(link_));
+    counted_ptr<delivery> dlv = snd.send(msg);
     std::string txt = "Sending on sender " + link_.name();
-    delivery_settled cond(dlv.get());
+    delivery_settled cond(pn_cast(dlv.get()));
     connection_.wait(cond, txt, timeout);
     return dlv;
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/connection.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection.cpp b/proton-c/bindings/cpp/src/connection.cpp
index 2b335a4..f3781a8 100644
--- a/proton-c/bindings/cpp/src/connection.cpp
+++ b/proton-c/bindings/cpp/src/connection.cpp
@@ -20,49 +20,61 @@
  */
 #include "proton/container.hpp"
 #include "proton/connection.hpp"
+#include "proton/transport.hpp"
 #include "proton/handler.hpp"
+#include "proton/session.hpp"
 #include "proton/error.hpp"
+
 #include "msg.hpp"
 #include "contexts.hpp"
-#include "connection_impl.hpp"
-#include "private_impl_ref.hpp"
+#include "container_impl.hpp"
 
 #include "proton/connection.h"
+#include "proton/session.h"
+#include "proton/transport.h"
+#include "proton/reactor.h"
+#include "proton/object.h"
 
 namespace proton {
 
-template class handle<connection_impl>;
-typedef private_impl_ref<connection> PI;
-
-connection::connection() {PI::ctor(*this, 0); }
-connection::connection(connection_impl* p) { PI::ctor(*this, p); }
-connection::connection(const connection& c) : handle<connection_impl>() { PI::copy(*this, c); }
-
-connection& connection::operator=(const connection& c) { return PI::assign(*this, c); }
-connection::~connection() { PI::dtor(*this); }
-
-connection::connection(class container &c, handler *h) {
-    connection_impl *cimpl = new connection_impl(c, h);
-    PI::ctor(*this, cimpl);
+namespace {
+struct override_holder : counted {
+    override_holder(class handler* h) : handler(h) {}
+    ~override_holder() { delete handler; }
+    class handler* handler;
+};
 }
 
-transport &connection::transport() { return impl_->transport(); }
+transport &connection::transport() {
+    return *transport::cast(pn_connection_transport(pn_cast(this)));
+}
 
-handler* connection::override() { return impl_->override(); }
-void connection::override(handler *h) { impl_->override(h); }
+void connection::open() { pn_connection_open(pn_cast(this)); }
 
-void connection::open() { impl_->open(); }
+void connection::close() { pn_connection_close(pn_cast(this)); }
 
-void connection::close() { impl_->close(); }
+std::string connection::hostname() {
+    return std::string(pn_connection_get_hostname(pn_cast(this)));
+}
 
-pn_connection_t *connection::pn_connection() { return impl_->pn_connection(); }
+container& connection::container() {
+    container_impl* impl = container_context(pn_object_reactor(pn_cast(this)));
+    return impl->container_;
+}
 
-std::string connection::hostname() { return impl_->hostname(); }
+link* connection::link_head(endpoint::state mask) {
+    return link::cast(pn_link_head(pn_cast(this), mask));
+}
 
-class container &connection::container() { return impl_->container(); }
+session& connection::create_session() { return *session::cast(pn_session(pn_cast(this))); }
 
-link connection::link_head(endpoint::state mask) {
-    return impl_->link_head(mask);
+session& connection::default_session() {
+    struct connection_context& ctx = connection_context::get(pn_cast(this));
+    if (!ctx.default_session) {
+        ctx.default_session = &create_session(); 
+        ctx.default_session->open();
+    }
+    return *ctx.default_session;
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/connection_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_impl.cpp b/proton-c/bindings/cpp/src/connection_impl.cpp
deleted file mode 100644
index e2f4608..0000000
--- a/proton-c/bindings/cpp/src/connection_impl.cpp
+++ /dev/null
@@ -1,140 +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/container.hpp"
-#include "proton/handler.hpp"
-#include "proton/error.hpp"
-#include "connection_impl.hpp"
-#include "proton/transport.hpp"
-#include "msg.hpp"
-#include "contexts.hpp"
-#include "private_impl_ref.hpp"
-#include "container_impl.hpp"
-
-#include "proton/connection.h"
-
-namespace proton {
-
-void connection_impl::incref(connection_impl *impl_) {
-    impl_->refcount_++;
-}
-
-void connection_impl::decref(connection_impl *impl_) {
-    impl_->refcount_--;
-    if (impl_->refcount_ == 0)
-        delete impl_;
-}
-
-connection_impl::connection_impl(class container &c, pn_connection_t &pn_conn)
-    : container_(c), refcount_(0), override_(0), transport_(0), default_session_(0),
-      pn_connection_(&pn_conn), reactor_reference_(this)
-{
-    connection_context(pn_connection_, this);
-}
-
-connection_impl::connection_impl(class container &c, handler *handler)
-    : container_(c), refcount_(0), override_(0), transport_(0), default_session_(0),
-      reactor_reference_(this)
-{
-    pn_handler_t *chandler = 0;
-    if (handler) {
-        container_impl *container_impl = private_impl_ref<class container>::get(c);
-        chandler = container_impl->wrap_handler(handler);
-    }
-    pn_connection_ = pn_reactor_connection(container_.reactor(), chandler);
-    if (chandler)
-        pn_decref(chandler);
-    connection_context(pn_connection_, this);
-}
-
-connection_impl::~connection_impl() {
-    delete transport_;
-    delete override_;
-}
-
-transport &connection_impl::transport() {
-    if (transport_)
-        return *transport_;
-    throw error(MSG("connection has no transport"));
-}
-
-handler* connection_impl::override() { return override_; }
-void connection_impl::override(handler *h) {
-    if (override_)
-        delete override_;
-    override_ = h;
-}
-
-void connection_impl::open() {
-    pn_connection_open(pn_connection_);
-}
-
-void connection_impl::close() {
-    pn_connection_close(pn_connection_);
-}
-
-pn_connection_t *connection_impl::pn_connection() { return pn_connection_; }
-
-std::string connection_impl::hostname() {
-    return std::string(pn_connection_get_hostname(pn_connection_));
-}
-
-connection &connection_impl::connection() {
-    // endpoint interface.  Should be implemented in the connection object.
-    throw error(MSG("Internal error"));
-}
-
-container &connection_impl::container() { return (container_); }
-
-
-// TODO: Rework this.  Rename and document excellently for user handlers on connections.
-// Better: provide general solution for handlers that delete before the C reactor object
-// has finished sending events.
-void connection_impl::reactor_detach() {
-    // "save" goes out of scope last, preventing possible recursive destructor
-    // confusion with reactor_reference.
-    class connection save(reactor_reference_);
-    if (reactor_reference_)
-        reactor_reference_ = proton::connection();
-    pn_connection_ = 0;
-}
-
-connection &connection_impl::reactor_reference(pn_connection_t *conn) {
-    if (!conn)
-        throw error(MSG("amqp_null Proton connection"));
-    connection_impl *impl_ = connection_context(conn);
-    if (!impl_) {
-        // First time we have seen this connection
-        pn_reactor_t *reactor = pn_object_reactor(conn);
-        if (!reactor)
-            throw error(MSG("Invalid Proton connection specifier"));
-        class container container(container_context(reactor));
-        if (!container)  // can't be one created by our container
-            throw error(MSG("Unknown Proton connection specifier"));
-        impl_ = new connection_impl(container, *conn);
-    }
-    return impl_->reactor_reference_;
-}
-
-link connection_impl::link_head(endpoint::state mask) {
-    return link(pn_link_head(pn_connection_, mask));
-}
-
-}

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/connection_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connection_impl.hpp b/proton-c/bindings/cpp/src/connection_impl.hpp
deleted file mode 100644
index 6450ef5..0000000
--- a/proton-c/bindings/cpp/src/connection_impl.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef PROTON_CPP_CONNECTIONIMPL_H
-#define PROTON_CPP_CONNECTIONIMPL_H
-
-/*
- *
- * 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/export.hpp"
-#include "proton/endpoint.hpp"
-#include "proton/container.hpp"
-#include "proton/types.h"
-#include <string>
-
-struct pn_connection_t;
-
-namespace proton {
-
-class handler;
-class transport;
-class container;
-
-class connection_impl : public endpoint
-{
-  public:
-    PN_CPP_EXTERN connection_impl(class container &c, pn_connection_t &pn_conn);
-    PN_CPP_EXTERN connection_impl(class container &c, handler *h = 0);
-    PN_CPP_EXTERN virtual ~connection_impl();
-    PN_CPP_EXTERN class transport &transport();
-    PN_CPP_EXTERN handler *override();
-    PN_CPP_EXTERN void override(handler *h);
-    PN_CPP_EXTERN void open();
-    PN_CPP_EXTERN void close();
-    PN_CPP_EXTERN pn_connection_t *pn_connection();
-    PN_CPP_EXTERN class container &container();
-    PN_CPP_EXTERN std::string hostname();
-    PN_CPP_EXTERN link link_head(endpoint::state mask);
-    virtual PN_CPP_EXTERN class connection &connection();
-    static class connection &reactor_reference(pn_connection_t *);
-    static connection_impl *impl(const class connection &c) { return c.impl_; }
-    void reactor_detach();
-    static void incref(connection_impl *);
-    static void decref(connection_impl *);
-  private:
-    friend class connector;
-    friend class container_impl;
-    class container container_;
-    int refcount_;
-    handler *override_;
-    class transport *transport_;
-    pn_session_t *default_session_;  // Temporary, for session_per_connection style policy.
-    pn_connection_t *pn_connection_;
-    class connection reactor_reference_;   // Keep-alive reference, until PN_CONNECTION_FINAL.
-};
-
-
-}
-
-#endif  /*!PROTON_CPP_CONNECTIONIMPL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/connector.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connector.cpp b/proton-c/bindings/cpp/src/connector.cpp
index 559a7fd..75760d9 100644
--- a/proton-c/bindings/cpp/src/connector.cpp
+++ b/proton-c/bindings/cpp/src/connector.cpp
@@ -27,11 +27,10 @@
 #include "proton/url.hpp"
 
 #include "connector.hpp"
-#include "connection_impl.hpp"
 
 namespace proton {
 
-connector::connector(connection &c) : connection_(c), transport_(0) {}
+connector::connector(connection &c) : connection_(c) {}
 
 connector::~connector() {}
 
@@ -40,15 +39,11 @@ void connector::address(const url &a) {
 }
 
 void connector::connect() {
-    pn_connection_t *conn = connection_.pn_connection();
-    pn_connection_set_container(conn, connection_.container().container_id().c_str());
+    pn_connection_t *conn = pn_cast(connection_.get());
+    pn_connection_set_container(conn, connection_->container().container_id().c_str());
     pn_connection_set_hostname(conn, address_.host_port().c_str());
-    transport_ = new transport();
-    transport_->bind(connection_);
-    connection_.impl_->transport_ = transport_;
 }
 
-
 void connector::on_connection_local_open(event &e) {
     connect();
 }
@@ -60,10 +55,8 @@ void connector::on_connection_init(event &e) {
 
 void connector::on_transport_closed(event &e) {
     // TODO: prepend with reconnect logic
-    pn_connection_release(connection_.impl_->pn_connection_);
-    // No more interaction, so drop our counted reference.
-    connection_ = connection();
+    pn_connection_release(pn_cast(connection_.get()));
+    connection_.reset();
 }
 
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/connector.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/connector.hpp b/proton-c/bindings/cpp/src/connector.hpp
index ad373a9..b97be53 100644
--- a/proton-c/bindings/cpp/src/connector.hpp
+++ b/proton-c/bindings/cpp/src/connector.hpp
@@ -48,9 +48,8 @@ class connector : public proton_handler
     virtual void on_transport_closed(event &e);
 
   private:
-    connection connection_;
+    counted_ptr<connection> connection_;
     url address_;
-    transport *transport_;
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/container.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container.cpp b/proton-c/bindings/cpp/src/container.cpp
index 8545143..d5ad890 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -38,26 +38,17 @@
 
 namespace proton {
 
-template class handle<container_impl>;
-typedef private_impl_ref<container> PI;
+container::container() : impl_(new container_impl(*this, 0)) {}
 
-container::container(container_impl* p) { PI::ctor(*this, p); }
-container::container(const container& c) : handle<container_impl>() { PI::copy(*this, c); }
-container& container::operator=(const container& c) { return PI::assign(*this, c); }
-container::~container() { PI::dtor(*this); }
+container::container(messaging_handler &mhandler) :
+    impl_(new container_impl(*this, &mhandler)) {}
 
-container::container(messaging_handler &mhandler) {
-    container_impl *cimpl = new container_impl(mhandler);
-    PI::ctor(*this, cimpl);
-}
+container::~container() {}
 
-container::container() {
-    container_impl *cimpl = new container_impl();
-    PI::ctor(*this, cimpl);
+connection& container::connect(const url &host, handler *h) {
+    return impl_->connect(host, h);
 }
 
-connection container::connect(const url &host, handler *h) { return impl_->connect(host, h); }
-
 pn_reactor_t *container::reactor() { return impl_->reactor(); }
 
 std::string container::container_id() { return impl_->container_id(); }
@@ -66,23 +57,23 @@ duration container::timeout() { return impl_->timeout(); }
 void container::timeout(duration timeout) { impl_->timeout(timeout); }
 
 
-sender container::create_sender(connection &connection, const std::string &addr, handler *h) {
+sender& container::create_sender(connection &connection, const std::string &addr, handler *h) {
     return impl_->create_sender(connection, addr, h);
 }
 
-sender container::create_sender(const proton::url &url) {
+sender& container::create_sender(const proton::url &url) {
     return impl_->create_sender(url);
 }
 
-receiver container::create_receiver(connection &connection, const std::string &addr, bool dynamic, handler *h) {
+receiver& container::create_receiver(connection &connection, const std::string &addr, bool dynamic, handler *h) {
     return impl_->create_receiver(connection, addr, dynamic, h);
 }
 
-receiver container::create_receiver(const proton::url &url) {
+receiver& container::create_receiver(const proton::url &url) {
     return impl_->create_receiver(url);
 }
 
-acceptor container::listen(const proton::url &url) {
+acceptor& container::listen(const proton::url &url) {
     return impl_->listen(url);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/container_impl.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.cpp b/proton-c/bindings/cpp/src/container_impl.cpp
index b769e63..9750b18 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -31,7 +31,6 @@
 
 #include "msg.hpp"
 #include "container_impl.hpp"
-#include "connection_impl.hpp"
 #include "connector.hpp"
 #include "contexts.hpp"
 #include "private_impl_ref.hpp"
@@ -42,15 +41,6 @@
 
 namespace proton {
 
-namespace {
-
-connection_impl *impl(const connection &c) {
-    return private_impl_ref<connection>::get(c);
-}
-
-} // namespace
-
-
 class CHandler : public handler
 {
   public:
@@ -99,43 +89,17 @@ class override_handler : public handler
         pn_event_t *cevent = pne->pn_event();
         pn_connection_t *conn = pn_event_connection(cevent);
         if (conn && type != PN_CONNECTION_INIT) {
-            // send to override handler first
-            connection_impl *connection = connection_context(conn);
-            if (connection) {
-                handler *override = connection->override();
-                if (override) {
-                    e.dispatch(*override);
-                }
-            }
+            handler *override = connection_context::get(conn).handler;
+            if (override) e.dispatch(*override);
         }
 
         pn_handler_dispatch(base_handler, cevent, (pn_event_type_t) type);
-
-        if (conn && type == PN_CONNECTION_FINAL) {
-            //  TODO:  this must be the last action of the last handler looking at
-            //  connection events. Better: generate a custom FINAL event (or task).  Or move to
-            //  separate event streams per connection as part of multi threading support.
-            connection_impl *cimpl = connection_context(conn);
-            if (cimpl)
-                cimpl->reactor_detach();
-            // TODO: remember all connections and do reactor_detach of zombie connections
-            // not yet pn_connection_release'd at PN_REACTOR_FINAL.
-        }
     }
 };
 
 
 namespace {
 
-// TODO: configurable policy.  session_per_connection for now.
-session default_session(pn_connection_t *conn, pn_session_t **ses) {
-    if (!*ses) {
-        *ses = pn_session(conn);
-        pn_session_open(*ses);
-    }
-    return session(*ses);
-}
-
 struct inbound_context {
     static inbound_context* get(pn_handler_t* h) {
         return reinterpret_cast<inbound_context*>(pn_handler_mem(h));
@@ -146,12 +110,9 @@ struct inbound_context {
 
 void cpp_handler_dispatch(pn_handler_t *c_handler, pn_event_t *cevent, pn_event_type_t type)
 {
-    // Ref counted per event, but when is the last event if stop() never called?
-    container c(inbound_context::get(c_handler)->container_impl_);
+    container& c(inbound_context::get(c_handler)->container_impl_->container_);
     messaging_event mevent(cevent, type, c);
     mevent.dispatch(*inbound_context::get(c_handler)->cpp_handler_);
-    // Possible decref and deletion via a handler action on this event.
-    // return without further processing.
     return;
 }
 
@@ -182,14 +143,9 @@ void container_impl::decref(container_impl *impl_) {
         delete impl_;
 }
 
-container_impl::container_impl(handler &h) :
-    reactor_(0), handler_(&h), messaging_adapter_(0),
-    override_handler_(0), flow_controller_(0), container_id_(),
-    refcount_(0)
-{}
-
-container_impl::container_impl() :
-    reactor_(0), handler_(0), messaging_adapter_(0),
+container_impl::container_impl(container& c, handler *h) :
+    container_(c),
+    reactor_(0), handler_(h), messaging_adapter_(0),
     override_handler_(0), flow_controller_(0), container_id_(),
     refcount_(0)
 {}
@@ -201,16 +157,17 @@ container_impl::~container_impl() {
     pn_reactor_free(reactor_);
 }
 
-connection container_impl::connect(const proton::url &url, handler *h) {
+connection& container_impl::connect(const proton::url &url, handler *h) {
     if (!reactor_) throw error(MSG("container not started"));
-    container ctnr(this);
-    connection conn(ctnr, h);
-    connector *ctor = new connector(conn);
-    // connector self-deletes depending on reconnect logic
+
+    pn_handler_t *chandler = h ? wrap_handler(h) : 0;
+    connection* conn = connection::cast(pn_reactor_connection(reactor_, chandler));
+    if (chandler) pn_decref(chandler);
+    connector *ctor = new connector(*conn); // Will be deleted by connection_context
     ctor->address(url);  // TODO: url vector
-    conn.override(ctor);
-    conn.open();
-    return conn;
+    connection_context::get(pn_cast(conn)).handler = ctor;
+    conn->open();
+    return *conn;
 }
 
 pn_reactor_t *container_impl::reactor() { return reactor_; }
@@ -235,11 +192,10 @@ void container_impl::timeout(duration timeout) {
 }
 
 
-sender container_impl::create_sender(connection &connection, const std::string &addr, handler *h) {
+sender& container_impl::create_sender(connection &connection, const std::string &addr, handler *h) {
     if (!reactor_) throw error(MSG("container not started"));
-    session session = default_session(connection.pn_connection(), &impl(connection)->default_session_);
-    sender snd = session.create_sender(container_id_  + '-' + addr);
-    pn_link_t *lnk = snd.get();
+    sender& snd = connection.default_session().create_sender(container_id_  + '-' + addr);
+    pn_link_t *lnk = pn_cast(&snd);
     pn_terminus_set_address(pn_link_target(lnk), addr.c_str());
     if (h) {
         pn_record_t *record = pn_link_attachments(lnk);
@@ -251,23 +207,20 @@ sender container_impl::create_sender(connection &connection, const std::string &
     return snd;
 }
 
-sender container_impl::create_sender(const proton::url &url) {
+sender& container_impl::create_sender(const proton::url &url) {
     if (!reactor_) throw error(MSG("container not started"));
-    connection conn = connect(url, 0);
-    session session = default_session(conn.pn_connection(), &impl(conn)->default_session_);
+    connection& conn = connect(url, 0);
     std::string path = url.path();
-    sender snd = session.create_sender(container_id_ + '-' + path);
-    pn_terminus_set_address(pn_link_target(snd.get()), path.c_str());
+    sender& snd = conn.default_session().create_sender(container_id_ + '-' + path);
+    pn_terminus_set_address(pn_link_target(pn_cast(&snd)), path.c_str());
     snd.open();
     return snd;
 }
 
-receiver container_impl::create_receiver(connection &connection, const std::string &addr, bool dynamic, handler *h) {
+receiver& container_impl::create_receiver(connection &conn, const std::string &addr, bool dynamic, handler *h) {
     if (!reactor_) throw error(MSG("container not started"));
-    connection_impl *conn_impl = impl(connection);
-    session session = default_session(conn_impl->pn_connection_, &conn_impl->default_session_);
-    receiver rcv = session.create_receiver(container_id_ + '-' + addr);
-    pn_link_t *lnk = rcv.get();
+    receiver& rcv = conn.default_session().create_receiver(container_id_ + '-' + addr);
+    pn_link_t *lnk = pn_cast(&rcv);
     pn_terminus_t *src = pn_link_source(lnk);
     pn_terminus_set_address(src, addr.c_str());
     if (dynamic)
@@ -282,26 +235,25 @@ receiver container_impl::create_receiver(connection &connection, const std::stri
     return rcv;
 }
 
-receiver container_impl::create_receiver(const proton::url &url) {
+receiver& container_impl::create_receiver(const proton::url &url) {
     if (!reactor_) throw error(MSG("container not started"));
-    connection conn = connect(url, 0);
-    session session = default_session(conn.pn_connection(), &impl(conn)->default_session_);
+    connection& conn = connect(url, 0);
     std::string path = url.path();
-    receiver rcv = session.create_receiver(container_id_ + '-' + path);
-    pn_terminus_set_address(pn_link_source(rcv.get()), path.c_str());
+    receiver& rcv = conn.default_session().create_receiver(container_id_ + '-' + path);
+    pn_terminus_set_address(pn_link_source(pn_cast(&rcv)), path.c_str());
     rcv.open();
     return rcv;
 }
 
-class acceptor container_impl::acceptor(const proton::url& url) {
+acceptor& container_impl::acceptor(const proton::url& url) {
     pn_acceptor_t *acptr = pn_reactor_acceptor(reactor_, url.host().c_str(), url.port().c_str(), NULL);
     if (acptr)
-        return proton::acceptor(acptr);
+        return *acceptor::cast(acptr);
     else
         throw error(MSG("accept fail: " << pn_error_text(pn_io_error(pn_reactor_io(reactor_))) << "(" << url << ")"));
 }
 
-acceptor container_impl::listen(const proton::url &url) {
+acceptor& container_impl::listen(const proton::url &url) {
     if (!reactor_) throw error(MSG("container not started"));
     return acceptor(url);
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/9bb9c442/proton-c/bindings/cpp/src/container_impl.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/container_impl.hpp b/proton-c/bindings/cpp/src/container_impl.hpp
index 1ce27ee..6780bb5 100644
--- a/proton-c/bindings/cpp/src/container_impl.hpp
+++ b/proton-c/bindings/cpp/src/container_impl.hpp
@@ -40,17 +40,16 @@ class acceptor;
 class container_impl
 {
   public:
-    PN_CPP_EXTERN container_impl(handler &h);
-    PN_CPP_EXTERN container_impl();
+    PN_CPP_EXTERN container_impl(container&, handler *);
     PN_CPP_EXTERN ~container_impl();
-    PN_CPP_EXTERN connection connect(const url&, handler *h);
+    PN_CPP_EXTERN connection& connect(const url&, handler *h);
     PN_CPP_EXTERN void run();
     PN_CPP_EXTERN pn_reactor_t *reactor();
-    PN_CPP_EXTERN sender create_sender(connection &connection, const std::string &addr, handler *h);
-    PN_CPP_EXTERN sender create_sender(const url&);
-    PN_CPP_EXTERN receiver create_receiver(connection &connection, const std::string &addr, bool dynamic, handler *h);
-    PN_CPP_EXTERN receiver create_receiver(const url&);
-    PN_CPP_EXTERN class acceptor listen(const url&);
+    PN_CPP_EXTERN sender& create_sender(connection &connection, const std::string &addr, handler *h);
+    PN_CPP_EXTERN sender& create_sender(const url&);
+    PN_CPP_EXTERN receiver& create_receiver(connection &connection, const std::string &addr, bool dynamic, handler *h);
+    PN_CPP_EXTERN receiver& create_receiver(const url&);
+    PN_CPP_EXTERN class acceptor& listen(const url&);
     PN_CPP_EXTERN std::string container_id();
     PN_CPP_EXTERN duration timeout();
     PN_CPP_EXTERN void timeout(duration timeout);
@@ -63,10 +62,14 @@ class container_impl
     pn_handler_t *wrap_handler(handler *h);
     static void incref(container_impl *);
     static void decref(container_impl *);
+
+    container& container_;
+
   private:
     void dispatch(pn_event_t *event, pn_event_type_t type);
-    class acceptor acceptor(const url&);
+    class acceptor& acceptor(const url&);
     void initialize_reactor();
+
     pn_reactor_t *reactor_;
     handler *handler_;
     messaging_adapter *messaging_adapter_;


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