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:58 UTC

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

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