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/14 19:24:44 UTC

qpid-proton git commit: PROTON-865: Replace proton_handler with simpler pointer-semantic wrapper template.

Repository: qpid-proton
Updated Branches:
  refs/heads/cjansen-cpp-client bc1491c5f -> 6bef190d4


PROTON-865: Replace proton_handler with simpler pointer-semantic wrapper template.

Template proton::wrapper<pn_foo_t> simply wraps a pn_foo_t*.  Derived classes
such as link, terminus etc. just provide C++ convenience wrapper functions.
Wrappers are passed by value, like pointers, not by reference.

Exception 1: proton::message has value semantics (copy the message) and owns it's
pn_message_t* but still provides access to the underlying pointer. Functions
returning a message return a message&.
TODO: return by ref is ugly, needs move semantics on C++11. Arguably should be
a plain wrapper<> and provide value semantics in separate class?

Exception 2: proton::connection - TODO.


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

Branch: refs/heads/cjansen-cpp-client
Commit: 6bef190d4303f818dddfdc4f366ae152dd8cc6fe
Parents: bc1491c
Author: Alan Conway <ac...@redhat.com>
Authored: Wed Aug 12 12:36:06 2015 -0400
Committer: Alan Conway <ac...@redhat.com>
Committed: Wed Aug 12 14:56:26 2015 -0400

----------------------------------------------------------------------
 examples/cpp/client.cpp                         |  1 +
 .../bindings/cpp/include/proton/acceptor.hpp    | 13 +---
 .../cpp/include/proton/blocking_sender.hpp      |  2 +-
 .../bindings/cpp/include/proton/delivery.hpp    | 14 +---
 proton-c/bindings/cpp/include/proton/handle.hpp | 14 +---
 proton-c/bindings/cpp/include/proton/link.hpp   | 18 +----
 .../bindings/cpp/include/proton/message.hpp     | 17 +++--
 .../cpp/include/proton/messaging_adapter.hpp    |  2 +-
 .../cpp/include/proton/proton_handle.hpp        | 74 --------------------
 .../bindings/cpp/include/proton/receiver.hpp    |  9 ++-
 proton-c/bindings/cpp/include/proton/sender.hpp |  7 +-
 .../bindings/cpp/include/proton/session.hpp     | 13 +---
 .../bindings/cpp/include/proton/terminus.hpp    | 14 +---
 proton-c/bindings/cpp/include/proton/url.hpp    |  2 +-
 .../bindings/cpp/include/proton/wrapper.hpp     | 67 ++++++++++++++++++
 proton-c/bindings/cpp/src/acceptor.cpp          | 27 +------
 proton-c/bindings/cpp/src/acking.cpp            |  2 +-
 .../bindings/cpp/src/blocking_connection.cpp    |  2 +
 proton-c/bindings/cpp/src/blocking_link.cpp     |  8 +--
 proton-c/bindings/cpp/src/blocking_receiver.cpp |  9 +--
 proton-c/bindings/cpp/src/blocking_sender.cpp   |  8 ++-
 proton-c/bindings/cpp/src/container.cpp         |  2 +
 proton-c/bindings/cpp/src/container_impl.cpp    | 10 +--
 proton-c/bindings/cpp/src/contexts.hpp          |  4 +-
 proton-c/bindings/cpp/src/data.cpp              |  2 +-
 proton-c/bindings/cpp/src/delivery.cpp          | 34 ++-------
 proton-c/bindings/cpp/src/event.cpp             |  2 +
 proton-c/bindings/cpp/src/fetcher.cpp           |  4 +-
 proton-c/bindings/cpp/src/link.cpp              | 54 ++++----------
 proton-c/bindings/cpp/src/message.cpp           | 18 ++---
 proton-c/bindings/cpp/src/messaging_event.cpp   |  2 +
 proton-c/bindings/cpp/src/proton_bits.cpp       |  2 +-
 proton-c/bindings/cpp/src/proton_bits.hpp       |  6 +-
 proton-c/bindings/cpp/src/proton_event.cpp      |  2 +
 proton-c/bindings/cpp/src/proton_impl_ref.hpp   | 65 -----------------
 proton-c/bindings/cpp/src/receiver.cpp          | 17 ++---
 proton-c/bindings/cpp/src/sender.cpp            | 24 +++----
 proton-c/bindings/cpp/src/session.cpp           | 30 ++------
 .../bindings/cpp/src/sync_request_response.cpp  |  2 +-
 proton-c/bindings/cpp/src/terminus.cpp          | 53 +++-----------
 proton-c/include/proton/link.h                  | 18 ++---
 41 files changed, 214 insertions(+), 460 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/examples/cpp/client.cpp
----------------------------------------------------------------------
diff --git a/examples/cpp/client.cpp b/examples/cpp/client.cpp
index be5fc40..4c34ce7 100644
--- a/examples/cpp/client.cpp
+++ b/examples/cpp/client.cpp
@@ -58,6 +58,7 @@ class client : public proton::messaging_handler {
     }
 
     void on_message(proton::event &e) {
+        if (requests.empty()) return; // Spurious extra message!
         proton::message response = e.message();
         std::cout << '"' << requests.front() << '"' << " => " << response.body() << std::endl;
         requests.erase(requests.begin());

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 bc9edbc..6339a08 100644
--- a/proton-c/bindings/cpp/include/proton/acceptor.hpp
+++ b/proton-c/bindings/cpp/include/proton/acceptor.hpp
@@ -24,27 +24,20 @@
 
 #include "proton/reactor.h"
 #include "proton/export.hpp"
-#include "proton/proton_handle.hpp"
+#include "proton/wrapper.hpp"
 
 struct pn_connection_t;
 
 namespace proton {
 
 /** acceptor accepts connections. @see container::listen */
-class acceptor : public proton_handle<pn_acceptor_t>
+class acceptor : public wrapper<pn_acceptor_t>
 {
   public:
-    PN_CPP_EXTERN acceptor();
-    PN_CPP_EXTERN acceptor(pn_acceptor_t *);
-    PN_CPP_EXTERN acceptor(const acceptor&);
-    PN_CPP_EXTERN acceptor& operator=(const acceptor&);
-    PN_CPP_EXTERN ~acceptor();
+    PN_CPP_EXTERN acceptor(pn_acceptor_t * = 0);
 
     /** close the acceptor */
     PN_CPP_EXTERN void close();
-
-  private:
-    friend class proton_impl_ref<acceptor>;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 0fa89d9..9b3c1a1 100644
--- a/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
+++ b/proton-c/bindings/cpp/include/proton/blocking_sender.hpp
@@ -44,7 +44,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/6bef190d/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 3fa3069..cc74498 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/proton_handle.hpp"
+#include "proton/wrapper.hpp"
 
 #include "proton/delivery.h"
 #include "proton/disposition.h"
@@ -30,7 +30,7 @@
 namespace proton {
 
 /** delivery status of a message */
-class delivery : public proton_handle<pn_delivery_t>
+class delivery : public wrapper<pn_delivery_t>
 {
   public:
 
@@ -44,11 +44,7 @@ class delivery : public proton_handle<pn_delivery_t>
         MODIFIED = PN_MODIFIED  ///< Settled as modified
     };  // AMQP spec 3.4 delivery State
 
-    PN_CPP_EXTERN delivery(pn_delivery_t *d);
-    PN_CPP_EXTERN delivery();
-    PN_CPP_EXTERN ~delivery();
-    PN_CPP_EXTERN delivery(const delivery&);
-    PN_CPP_EXTERN delivery& operator=(const delivery&);
+    PN_CPP_EXTERN delivery(pn_delivery_t * = 0);
 
     /** Return true if the delivery has been settled. */
     PN_CPP_EXTERN bool settled();
@@ -58,10 +54,6 @@ class delivery : public proton_handle<pn_delivery_t>
 
     /** Set the local state of the delivery. */
     PN_CPP_EXTERN void update(delivery::state state);
-
-    PN_CPP_EXTERN pn_delivery_t *pn_delivery();
-  private:
-    friend class proton_impl_ref<delivery>;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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
index e0542ef..acff27d 100644
--- a/proton-c/bindings/cpp/include/proton/handle.hpp
+++ b/proton-c/bindings/cpp/include/proton/handle.hpp
@@ -28,29 +28,17 @@ namespace proton {
 
 ///@cond INTERNAL
 template <class> class private_impl_ref;
-template <class> class proton_impl_ref;
 ///@endcond INTERNAL
 
 /**
  * A handle is like a pointer: refers to an underlying implementation object.
  * Copying the handle does not copy the object.
  *
- * Handles can be null,  like a 0 pointer. Use is_valid(), is_null() or the
- * conversion to bool to test for a null handle.
+ * A handle can be null, use `if (handle)` or `if (!handle)` to test for a null handle.
  */
 template <class T> class handle {
   public:
-
-    /**@return true if handle is valid,  i.e. not null. */
-    bool is_valid() const { return impl_; }
-
-    /**@return true if handle is null. It is an error to call any function on a null handle. */
-    bool is_null() const { return !impl_; }
-
-    /** Conversion to bool supports idiom if (handle) { handle->... } */
     operator bool() const { return impl_; }
-
-    /** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
     bool operator !() const { return !impl_; }
 
     /** Operator ==  equal if they point to same non-null object*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 46b8894..05ca742 100644
--- a/proton-c/bindings/cpp/include/proton/link.hpp
+++ b/proton-c/bindings/cpp/include/proton/link.hpp
@@ -22,7 +22,7 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/proton_handle.hpp"
+#include "proton/wrapper.hpp"
 #include "proton/endpoint.hpp"
 #include "proton/terminus.hpp"
 #include "proton/types.h"
@@ -33,14 +33,10 @@ struct pn_connection_t;
 namespace proton {
 
 /** Messages are transferred across a link. Base class for sender, receiver. */
-class link : public endpoint, public proton_handle<pn_link_t>
+class link : public endpoint, public wrapper<pn_link_t>
 {
   public:
-    PN_CPP_EXTERN link(pn_link_t *);
-    PN_CPP_EXTERN link();
-    PN_CPP_EXTERN ~link();
-    PN_CPP_EXTERN link(const link&);
-    PN_CPP_EXTERN link& operator=(const link&);
+    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
@@ -74,14 +70,6 @@ class link : public endpoint, public proton_handle<pn_link_t>
 
     /** Connection of the link */
     PN_CPP_EXTERN class connection &connection();
-
-    PN_CPP_EXTERN pn_link_t *pn_link() const;
-
-  protected:
-    PN_CPP_EXTERN virtual void verify_type(pn_link_t *l);
-  private:
-    friend class proton_impl_ref<link>;
-    bool sender_link;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 ddbb306..6f98fe8 100644
--- a/proton-c/bindings/cpp/include/proton/message.hpp
+++ b/proton-c/bindings/cpp/include/proton/message.hpp
@@ -35,9 +35,13 @@ class delivery;
 
 /** An AMQP message.
  *
- * This class has value semantics: the copy constructor and assignment make a
- * copy of the underlying message data. If you want to transfer the message data
- * without a copy use the swap member function or std::swap.
+ * 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
@@ -53,12 +57,11 @@ class message
 
     PN_CPP_EXTERN ~message();
 
-    PN_CPP_EXTERN void swap(message&);
-
     /// Access the underlying pn_message_t, note it will be freed by ~message.
-    PN_CPP_EXTERN pn_message_t *pn_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 *pn_message_forget();
+    PN_CPP_EXTERN pn_message_t *release();
 
     /** Clear the message content */
     PN_CPP_EXTERN void clear();

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 8744c95..06293c0 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/proton_handler.hpp"
+#include "proton/wrapper.hpp"
 #include "proton/messaging_handler.hpp"
 
 #include "proton/messaging_event.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/proton-c/bindings/cpp/include/proton/proton_handle.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/include/proton/proton_handle.hpp b/proton-c/bindings/cpp/include/proton/proton_handle.hpp
deleted file mode 100644
index 19ee90b..0000000
--- a/proton-c/bindings/cpp/include/proton/proton_handle.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef PROTON_CPP_PROTONHANDLE_H
-#define PROTON_CPP_PROTONHANDLE_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 proton_impl_ref;
-///@endcond INTERNAL
-
-/**
- * See handle.h.  Similar but for lightly wrapped Proton pn_object_t targets.
- */
-template <class T> class proton_handle {
-  public:
-    /**@return true if handle is valid,  i.e. not null. */
-    bool is_valid() const { return impl_; }
-
-    /**@return true if handle is null. It is an error to call any function on a null handle. */
-    bool is_null() const { return !impl_; }
-
-    /** Conversion to bool supports idiom if (handle) { handle->... } */
-    operator bool() const { return impl_; }
-
-    /** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */
-    bool operator !() const { return !impl_; }
-
-    void swap(proton_handle<T>& h) { T* t = h.impl_; h.impl_ = impl_; impl_ = t; }
-
-    bool operator==(const proton_handle<T>& x) { return x.impl_ == impl_; }
-    bool operator!=(const proton_handle<T>& x) { return x.impl_ != impl_; }
-
-    T* raw() { return impl_; }
-
-  private:
-    // Not implemented, subclasses must implement.
-    // FIXME aconway 2015-08-07: why?
-    proton_handle(const proton_handle&);
-    proton_handle& operator=(const proton_handle&);
-
-  protected:
-    typedef T Impl;
-    proton_handle() : impl_() {}
-
-    mutable Impl* impl_;
-
-  friend class proton_impl_ref<T>;
-};
-
-}
-
-#endif  /*!PROTON_CPP_PROTONHANDLE_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 1974cd0..578e641 100644
--- a/proton-c/bindings/cpp/include/proton/receiver.hpp
+++ b/proton-c/bindings/cpp/include/proton/receiver.hpp
@@ -35,12 +35,11 @@ namespace proton {
 class receiver : public link
 {
   public:
-    PN_CPP_EXTERN receiver(pn_link_t *lnk);
-    PN_CPP_EXTERN receiver();
-    PN_CPP_EXTERN receiver(const link& c);
+    /// @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);
-  protected:
-    PN_CPP_EXTERN virtual void verify_type(pn_link_t *l);
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 3573a90..7260f72 100644
--- a/proton-c/bindings/cpp/include/proton/sender.hpp
+++ b/proton-c/bindings/cpp/include/proton/sender.hpp
@@ -37,14 +37,11 @@ namespace proton {
 class sender : public link
 {
   public:
-    PN_CPP_EXTERN sender(pn_link_t *lnk=0);
-    PN_CPP_EXTERN sender(const link& c);
+    /// @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);
-
-  protected:
-    PN_CPP_EXTERN virtual void verify_type(pn_link_t *l);
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 7f670b8..3eb3fdd 100644
--- a/proton-c/bindings/cpp/include/proton/session.hpp
+++ b/proton-c/bindings/cpp/include/proton/session.hpp
@@ -38,14 +38,10 @@ class handler;
 class transport;
 
 /** A session is a collection of links */
-class session : public endpoint, public proton_handle<pn_session_t>
+class session : public endpoint, public wrapper<pn_session_t>
 {
   public:
-    PN_CPP_EXTERN session(pn_session_t *s);
-    PN_CPP_EXTERN session();
-    PN_CPP_EXTERN session(const session&);
-    PN_CPP_EXTERN ~session();
-    PN_CPP_EXTERN session& operator=(const session&);
+    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()
@@ -63,11 +59,6 @@ class session : public endpoint, public proton_handle<pn_session_t>
     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 pn_session_t *pn_session();
-
-  private:
-  friend class proton_impl_ref<session>;
 };
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 f53d6c3..7c63582 100644
--- a/proton-c/bindings/cpp/include/proton/terminus.hpp
+++ b/proton-c/bindings/cpp/include/proton/terminus.hpp
@@ -22,7 +22,6 @@
  *
  */
 #include "proton/export.hpp"
-#include "proton/link.hpp"
 
 #include "proton/link.h"
 #include <string>
@@ -34,7 +33,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 proton_handle<pn_terminus_t>
+class terminus : public wrapper<pn_terminus_t>
 {
   public:
     /// Type of terminus
@@ -59,12 +58,6 @@ class terminus : public proton_handle<pn_terminus_t>
         MOVE = PN_DIST_MODE_MOVE
     };
 
-
-    PN_CPP_EXTERN terminus();
-    PN_CPP_EXTERN ~terminus();
-    PN_CPP_EXTERN terminus(const terminus&);
-    PN_CPP_EXTERN terminus& operator=(const terminus&);
-    PN_CPP_EXTERN pn_terminus_t *pn_terminus();
     PN_CPP_EXTERN type_t type();
     PN_CPP_EXTERN void type(type_t);
     PN_CPP_EXTERN expiry_policy_t expiry_policy();
@@ -77,10 +70,9 @@ class terminus : public proton_handle<pn_terminus_t>
     PN_CPP_EXTERN void dynamic(bool);
 
   private:
-    link *link_;
-    PN_CPP_EXTERN terminus(pn_terminus_t *, link *);
+    pn_link_t* link_;
+    PN_CPP_EXTERN terminus(pn_terminus_t * = 0, pn_link_t * = 0);
   friend class link;
-  friend class proton_impl_ref<terminus>;
 };
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 4da3a56..f9c5576 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/proton_handle.hpp"
+#include "proton/wrapper.hpp"
 #include "proton/error.hpp"
 #include <iosfwd>
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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
new file mode 100644
index 0000000..c9ad151
--- /dev/null
+++ b/proton-c/bindings/cpp/include/proton/wrapper.hpp
@@ -0,0 +1,67 @@
+#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/6bef190d/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 990bfc3..f1892f7 100644
--- a/proton-c/bindings/cpp/src/acceptor.cpp
+++ b/proton-c/bindings/cpp/src/acceptor.cpp
@@ -21,35 +21,12 @@
 
 #include "proton/acceptor.hpp"
 #include "proton/error.hpp"
-#include "proton_impl_ref.hpp"
 #include "msg.hpp"
 
 namespace proton {
 
-template class proton_handle<pn_acceptor_t>;
-typedef proton_impl_ref<acceptor> PI;
+acceptor::acceptor(pn_acceptor_t *a) : wrapper<pn_acceptor_t>(a) {}
 
-acceptor::acceptor() {}
-
-acceptor::acceptor(pn_acceptor_t *a)
-{
-    PI::ctor(*this, a);
-}
-
-acceptor::~acceptor() { PI::dtor(*this); }
-
-
-acceptor::acceptor(const acceptor& a) : proton_handle<pn_acceptor_t>() {
-    PI::copy(*this, a);
-}
-
-acceptor& acceptor::operator=(const acceptor& a) {
-    return PI::assign(*this, a);
-}
-
-void acceptor::close() {
-    if (impl_)
-        pn_acceptor_close(impl_);
-}
+void acceptor::close() { pn_acceptor_close(get()); }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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
index 5738257..b3453c7 100644
--- a/proton-c/bindings/cpp/src/acking.cpp
+++ b/proton-c/bindings/cpp/src/acking.cpp
@@ -41,7 +41,7 @@ void acking::release(delivery &d, bool delivered) {
 
 void acking::settle(delivery &d, delivery::state state) {
     if (state)
-        pn_delivery_update(d.pn_delivery(), state);
+        pn_delivery_update(d.get(), state);
     d.settle();
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 c54005e..762029e 100644
--- a/proton-c/bindings/cpp/src/blocking_connection.cpp
+++ b/proton-c/bindings/cpp/src/blocking_connection.cpp
@@ -23,6 +23,8 @@
 #include "proton/blocking_sender.hpp"
 #include "proton/blocking_receiver.hpp"
 #include "proton/messaging_handler.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/url.hpp"
 #include "proton/error.hpp"
 #include "fetcher.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 43d1b83..648a8a6 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_.pn_link());
+    link_opened link_opened(link_.get());
     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_.pn_link());
+    link_closed link_closed(link_.get());
     connection_.wait(link_closed, msg);
     check_closed();
 }
 
 void blocking_link::check_closed() {
-    pn_link_t * pn_link = link_.pn_link();
+    pn_link_t * pn_link = link_.get();
     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_.pn_link());
+    link_not_open link_not_open(link_.get());
     connection_.wait(link_not_open, msg);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 f4736e5..fe94d80 100644
--- a/proton-c/bindings/cpp/src/blocking_receiver.cpp
+++ b/proton-c/bindings/cpp/src/blocking_receiver.cpp
@@ -20,6 +20,7 @@
  */
 #include "proton/blocking_receiver.hpp"
 #include "proton/blocking_connection.hpp"
+#include "proton/receiver.hpp"
 #include "proton/error.hpp"
 #include "fetcher.hpp"
 #include "msg.hpp"
@@ -39,7 +40,7 @@ struct fetcher_has_message {
 
 
 blocking_receiver::blocking_receiver(blocking_connection &c, receiver &l, fetcher *f, int credit)
-    : blocking_link(&c, l.pn_link()), fetcher_(f) {
+    : blocking_link(&c, l.get()), fetcher_(f) {
     std::string sa = link_.source().address();
     std::string rsa = link_.remote_source().address();
     if (!sa.empty() && sa.compare(rsa) != 0) {
@@ -49,7 +50,7 @@ blocking_receiver::blocking_receiver(blocking_connection &c, receiver &l, fetche
         throw error(MSG(txt));
     }
     if (credit)
-        pn_link_flow(link_.pn_link(), credit);
+        pn_link_flow(link_.get(), credit);
     if (fetcher_)
         fetcher_->incref();
 }
@@ -75,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_;
+    receiver rcv(link_.get());
     if (!rcv.credit())
         rcv.flow(1);
     std::string txt = "Receiving on receiver " + link_.name();
@@ -111,7 +112,7 @@ void blocking_receiver::settle(delivery::state state = delivery::NONE) {
 }
 
 void blocking_receiver::flow(int count) {
-    receiver rcv(link_);
+    receiver rcv(link_.get());
     rcv.flow(count);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 a4757eb..4ddbb3c 100644
--- a/proton-c/bindings/cpp/src/blocking_sender.cpp
+++ b/proton-c/bindings/cpp/src/blocking_sender.cpp
@@ -20,6 +20,8 @@
  */
 #include "proton/blocking_sender.hpp"
 #include "proton/blocking_connection.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/error.hpp"
 #include "msg.hpp"
 
@@ -36,7 +38,7 @@ struct delivery_settled {
 } // namespace
 
 
-blocking_sender::blocking_sender(blocking_connection &c, sender &l) : blocking_link(&c, l.pn_link()) {
+blocking_sender::blocking_sender(blocking_connection &c, sender l) : blocking_link(&c, l.get()) {
     std::string ta = link_.target().address();
     std::string rta = link_.remote_target().address();
     if (ta.empty() || ta.compare(rta) != 0) {
@@ -48,10 +50,10 @@ blocking_sender::blocking_sender(blocking_connection &c, sender &l) : blocking_l
 }
 
 delivery blocking_sender::send(message &msg, duration timeout) {
-    sender snd = link_;
+    sender snd(link_.get());
     delivery dlv = snd.send(msg);
     std::string txt = "Sending on sender " + link_.name();
-    delivery_settled cond(dlv.pn_delivery());
+    delivery_settled cond(dlv.get());
     connection_.wait(cond, txt, timeout);
     return dlv;
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 a424c0b..8545143 100644
--- a/proton-c/bindings/cpp/src/container.cpp
+++ b/proton-c/bindings/cpp/src/container.cpp
@@ -26,6 +26,8 @@
 #include "proton/acceptor.hpp"
 #include "proton/error.hpp"
 #include "proton/url.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 
 #include "container_impl.hpp"
 #include "private_impl_ref.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 e328251..b769e63 100644
--- a/proton-c/bindings/cpp/src/container_impl.cpp
+++ b/proton-c/bindings/cpp/src/container_impl.cpp
@@ -26,6 +26,8 @@
 #include "proton/acceptor.hpp"
 #include "proton/error.hpp"
 #include "proton/url.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 
 #include "msg.hpp"
 #include "container_impl.hpp"
@@ -237,7 +239,7 @@ sender container_impl::create_sender(connection &connection, const std::string &
     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.pn_link();
+    pn_link_t *lnk = snd.get();
     pn_terminus_set_address(pn_link_target(lnk), addr.c_str());
     if (h) {
         pn_record_t *record = pn_link_attachments(lnk);
@@ -255,7 +257,7 @@ sender container_impl::create_sender(const proton::url &url) {
     session session = default_session(conn.pn_connection(), &impl(conn)->default_session_);
     std::string path = url.path();
     sender snd = session.create_sender(container_id_ + '-' + path);
-    pn_terminus_set_address(pn_link_target(snd.pn_link()), path.c_str());
+    pn_terminus_set_address(pn_link_target(snd.get()), path.c_str());
     snd.open();
     return snd;
 }
@@ -265,7 +267,7 @@ receiver container_impl::create_receiver(connection &connection, const std::stri
     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.pn_link();
+    pn_link_t *lnk = rcv.get();
     pn_terminus_t *src = pn_link_source(lnk);
     pn_terminus_set_address(src, addr.c_str());
     if (dynamic)
@@ -286,7 +288,7 @@ receiver container_impl::create_receiver(const proton::url &url) {
     session session = default_session(conn.pn_connection(), &impl(conn)->default_session_);
     std::string path = url.path();
     receiver rcv = session.create_receiver(container_id_ + '-' + path);
-    pn_terminus_set_address(pn_link_source(rcv.pn_link()), path.c_str());
+    pn_terminus_set_address(pn_link_source(rcv.get()), path.c_str());
     rcv.open();
     return rcv;
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 4830044..1f0678d 100644
--- a/proton-c/bindings/cpp/src/contexts.hpp
+++ b/proton-c/bindings/cpp/src/contexts.hpp
@@ -36,8 +36,8 @@ 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 *pn_link, link *link);
-link *link_context(pn_link_t *pn_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);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 51a9dde..dd35890 100644
--- a/proton-c/bindings/cpp/src/data.cpp
+++ b/proton-c/bindings/cpp/src/data.cpp
@@ -62,6 +62,6 @@ void data::rewind() { ::pn_data_rewind(data_); }
 
 bool data::empty() const { return ::pn_data_size(data_) == 0; }
 
-std::ostream& operator<<(std::ostream& o, const data& d) { return o << pn_object(d.data_); }
+std::ostream& operator<<(std::ostream& o, const data& d) { return o << inspectable(d.data_); }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 6c87939..93b4349 100644
--- a/proton-c/bindings/cpp/src/delivery.cpp
+++ b/proton-c/bindings/cpp/src/delivery.cpp
@@ -21,41 +21,15 @@
 
 #include "proton/delivery.hpp"
 #include "proton/delivery.h"
-#include "proton_impl_ref.hpp"
 
 namespace proton {
 
-template class proton_handle<pn_delivery_t>;
-typedef proton_impl_ref<delivery> PI;
+delivery::delivery(pn_delivery_t *p) : wrapper<pn_delivery_t>(p) {}
 
-delivery::delivery(pn_delivery_t *p) {
-    PI::ctor(*this, p);
-}
-delivery::delivery() {
-    PI::ctor(*this, 0);
-}
-delivery::delivery(const delivery& c) : proton_handle<pn_delivery_t>() {
-    PI::copy(*this, c);
-}
-delivery& delivery::operator=(const delivery& c) {
-    return PI::assign(*this, c);
-}
-delivery::~delivery() {
-    PI::dtor(*this);
-}
+bool delivery::settled() { return pn_delivery_settled(get()); }
 
-bool delivery::settled() {
-    return pn_delivery_settled(impl_);
-}
-
-void delivery::settle() {
-    pn_delivery_settle(impl_);
-}
-
-void delivery::update(delivery::state state) {
-    pn_delivery_update(impl_, state);
-}
+void delivery::settle() { pn_delivery_settle(get()); }
 
-pn_delivery_t *delivery::pn_delivery() { return impl_; }
+void delivery::update(delivery::state state) { pn_delivery_update(get(), state); }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 b1eaa77..d773878 100644
--- a/proton-c/bindings/cpp/src/event.cpp
+++ b/proton-c/bindings/cpp/src/event.cpp
@@ -25,6 +25,8 @@
 #include "proton/event.hpp"
 #include "proton/handler.hpp"
 #include "proton/error.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 
 #include "msg.hpp"
 #include "contexts.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 46ee18c..165a018 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().pn_link();
+    pn_link_ = e.link().get();
     pn_incref(pn_link_);
 }
 
@@ -56,7 +56,7 @@ void fetcher::on_message(event &e) {
 
 void fetcher::on_link_error(event &e) {
     link lnk = e.link();
-    if (pn_link_state(lnk.pn_link()) & PN_LOCAL_ACTIVE) {
+    if (pn_link_state(lnk.get()) & PN_LOCAL_ACTIVE) {
         lnk.close();
         throw error(MSG("Link detached: " << lnk.name()));
     }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 2cef0a2..95c0ed8 100644
--- a/proton-c/bindings/cpp/src/link.cpp
+++ b/proton-c/bindings/cpp/src/link.cpp
@@ -24,7 +24,6 @@
 #include "connection_impl.hpp"
 #include "msg.hpp"
 #include "contexts.hpp"
-#include "proton_impl_ref.hpp"
 
 #include "proton/connection.h"
 #include "proton/session.h"
@@ -32,82 +31,55 @@
 
 namespace proton {
 
-template class proton_handle<pn_link_t>;
-typedef proton_impl_ref<link> PI;
-
-link::link(pn_link_t* p) {
-    verify_type(p);
-    PI::ctor(*this, p);
-    if (p) sender_link = pn_link_is_sender(p);
-}
-link::link() {
-    PI::ctor(*this, 0);
-}
-link::link(const link& c) : proton_handle<pn_link_t>() {
-    verify_type(impl_);
-    PI::copy(*this, c);
-    sender_link = c.sender_link;
-}
-link& link::operator=(const link& c) {
-    verify_type(impl_);
-    sender_link = c.sender_link;
-    return PI::assign(*this, c);
-}
-link::~link() { PI::dtor(*this); }
-
-void link::verify_type(pn_link_t *l) {} // Generic link can be sender or receiver
-
-pn_link_t *link::pn_link() const { return impl_; }
+link::link(pn_link_t* p) : wrapper<pn_link_t>(p) {}
 
 void link::open() {
-    pn_link_open(impl_);
+    pn_link_open(get());
 }
 
 void link::close() {
-    pn_link_close(impl_);
+    pn_link_close(get());
 }
 
 bool link::is_sender() {
-    return impl_ && sender_link;
+    return pn_link_is_sender(get());
 }
 
-bool link::is_receiver() {
-    return impl_ && !sender_link;
-}
+bool link::is_receiver() { return !is_sender(); }
 
 int link::credit() {
-    return pn_link_credit(impl_);
+    return pn_link_credit(get());
 }
 
 terminus link::source() {
-    return terminus(pn_link_source(impl_), this);
+    return terminus(pn_link_source(get()), get());
 }
 
 terminus link::target() {
-    return terminus(pn_link_target(impl_), this);
+    return terminus(pn_link_target(get()), get());
 }
 
 terminus link::remote_source() {
-    return terminus(pn_link_remote_source(impl_), this);
+    return terminus(pn_link_remote_source(get()), get());
 }
 
 terminus link::remote_target() {
-    return terminus(pn_link_remote_target(impl_), this);
+    return terminus(pn_link_remote_target(get()), get());
 }
 
 std::string link::name() {
-    return std::string(pn_link_name(impl_));
+    return std::string(pn_link_name(get()));
 }
 
 class connection &link::connection() {
-    pn_session_t *s = pn_link_session(impl_);
+    pn_session_t *s = pn_link_session(get());
     pn_connection_t *c = pn_session_connection(s);
     return connection_impl::reactor_reference(c);
 }
 
 link link::next(endpoint::state mask) {
 
-    return link(pn_link_next(impl_, (pn_state_t) mask));
+    return link(pn_link_next(get(), (pn_state_t) mask));
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 8aae044..2e1165d 100644
--- a/proton-c/bindings/cpp/src/message.cpp
+++ b/proton-c/bindings/cpp/src/message.cpp
@@ -24,11 +24,11 @@
 #include "proton/link.hpp"
 #include "proton/delivery.hpp"
 #include "proton/message.h"
-#include "proton/link.h"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/delivery.h"
 #include "msg.hpp"
 #include "proton_bits.hpp"
-#include "proton_impl_ref.hpp"
 
 #include <cstring>
 #include <assert.h>
@@ -51,10 +51,6 @@ message& message::operator=(const message& m) {
 
 message::~message() { if (impl_) pn_message_free(impl_); }
 
-void message::swap(message& m) {
-    if (this != &m) std::swap(impl_, m.impl_);
-}
-
 void message::clear() { pn_message_clear(impl_); }
 
 namespace {
@@ -224,9 +220,9 @@ void message::decode(const std::string &s) {
     check(pn_message_decode(impl_, s.data(), s.size()));
 }
 
-pn_message_t *message::pn_message() { return impl_; }
+pn_message_t *message::get() { return impl_; }
 
-pn_message_t *message::pn_message_forget() {
+pn_message_t *message::release() {
     pn_message_t *result = impl_;
     impl_ = 0;
     return result;
@@ -234,12 +230,12 @@ pn_message_t *message::pn_message_forget() {
 
 void message::decode(proton::link link, proton::delivery delivery) {
     std::string buf;
-    buf.resize(pn_delivery_pending(delivery.pn_delivery()));
-    ssize_t n = pn_link_recv(link.pn_link(), (char *) buf.data(), buf.size());
+    buf.resize(pn_delivery_pending(delivery.get()));
+    ssize_t n = pn_link_recv(link.get(), (char *) buf.data(), buf.size());
     if (n != (ssize_t) buf.size()) throw error(MSG("link read failure"));
     clear();
     decode(buf);
-    pn_link_advance(link.pn_link());
+    pn_link_advance(link.get());
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 a629f47..f302a3b 100644
--- a/proton-c/bindings/cpp/src/messaging_event.cpp
+++ b/proton-c/bindings/cpp/src/messaging_event.cpp
@@ -27,6 +27,8 @@
 #include "proton/message.hpp"
 #include "proton/proton_handler.hpp"
 #include "proton/messaging_handler.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 #include "proton/error.hpp"
 #include "msg.hpp"
 #include "contexts.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/proton-c/bindings/cpp/src/proton_bits.cpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_bits.cpp b/proton-c/bindings/cpp/src/proton_bits.cpp
index aea18a3..3b522bf 100644
--- a/proton-c/bindings/cpp/src/proton_bits.cpp
+++ b/proton-c/bindings/cpp/src/proton_bits.cpp
@@ -47,7 +47,7 @@ std::string error_str(pn_error_t* err, int code) {
     return error_str(code);
 }
 
-std::ostream& operator<<(std::ostream& o, const pn_object& object) {
+std::ostream& operator<<(std::ostream& o, const inspectable& object) {
     pn_string_t* str = pn_string("");
     pn_inspect(object.value, str);
     o << pn_string_get(str);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/proton-c/bindings/cpp/src/proton_bits.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_bits.hpp b/proton-c/bindings/cpp/src/proton_bits.hpp
index 4dd9ad4..d615c0f 100644
--- a/proton-c/bindings/cpp/src/proton_bits.hpp
+++ b/proton-c/bindings/cpp/src/proton_bits.hpp
@@ -33,11 +33,11 @@ std::string error_str(int code);
 /** Print the error string from pn_error_t, or from code if pn_error_t has no error. */
 std::string error_str(pn_error_t*, int code=0);
 
-/** Wrapper for a proton object pointer. */
-struct pn_object { void* value; pn_object(void* o) : value(o) {} };
+/** Make a void* inspectable via operator <<. */
+struct inspectable { void* value; inspectable(void* o) : value(o) {} };
 
 /** Stream a proton object via pn_inspect. */
-std::ostream& operator<<(std::ostream& o, const pn_object& object);
+std::ostream& operator<<(std::ostream& o, const inspectable& object);
 
 
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 46b43ee..1c1788c 100644
--- a/proton-c/bindings/cpp/src/proton_event.cpp
+++ b/proton-c/bindings/cpp/src/proton_event.cpp
@@ -27,6 +27,8 @@
 #include "proton/proton_handler.hpp"
 #include "proton/error.hpp"
 #include "proton/container.hpp"
+#include "proton/sender.hpp"
+#include "proton/receiver.hpp"
 
 #include "connection_impl.hpp"
 #include "msg.hpp"

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/proton-c/bindings/cpp/src/proton_impl_ref.hpp
----------------------------------------------------------------------
diff --git a/proton-c/bindings/cpp/src/proton_impl_ref.hpp b/proton-c/bindings/cpp/src/proton_impl_ref.hpp
deleted file mode 100644
index 795754a..0000000
--- a/proton-c/bindings/cpp/src/proton_impl_ref.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef PROTON_CPP_PROTONIMPL_H
-#define PROTON_CPP_PROTONIMPL_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/object.h"
-
-namespace proton {
-
-// Modified from qpid::messaging version to work without
-// boost::intrusive_ptr but integrate with Proton's pn_class_t
-// reference counting.  Thread safety currently absent but fluid in
-// intention...
-
-
-/**
- * See private_impl_ref.h  This is for lightly wrapped Proton pn_object_t targets.
- * class Foo : proton_handle<pn_foo_t> {...}
- */
-
-template <class T> class proton_impl_ref {
-  public:
-    typedef typename T::Impl Impl;
-
-    /** Get the implementation pointer from a handle */
-    static Impl* get(const T& t) { return t.impl_; }
-
-    /** Set the implementation pointer in a handle */
-    static void set(T& t, const Impl* p) {
-        if (t.impl_ == p) return;
-        if (t.impl_) pn_decref(t.impl_);
-        t.impl_ = const_cast<Impl *>(p);
-        if (t.impl_) pn_incref(t.impl_);
-    }
-
-    // Helper functions to implement the ctor, dtor, copy, assign
-    static void ctor(T& t, Impl* p) { t.impl_ = p; if (p) pn_incref(p); }
-    static void copy(T& t, const T& x) { if (&t == &x) return; t.impl_ = 0; assign(t, x); }
-    static void dtor(T& t) { if(t.impl_) pn_decref(t.impl_); }
-    static T& assign(T& t, const T& x) { set(t, get(x)); return t;}
-};
-
-}
-
-#endif  /*!PROTON_CPP_PROTONIMPL_H*/

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 b9ed680..12f2c31 100644
--- a/proton-c/bindings/cpp/src/receiver.cpp
+++ b/proton-c/bindings/cpp/src/receiver.cpp
@@ -29,19 +29,20 @@
 
 namespace proton {
 
+namespace {
 
-receiver::receiver(pn_link_t *lnk) : link(lnk) {}
-receiver::receiver() : link(0) {}
-
-receiver::receiver(const link& c) : link(c.pn_link()) {}
+pn_link_t* verify(pn_link_t* l) {
+    if (l && !link(l).is_receiver())
+        throw error(MSG("Creating receiver from sender link"));
+    return l;
+}
 
-void receiver::verify_type(pn_link_t *lnk) {
-    if (lnk && pn_link_is_sender(lnk))
-        throw error(MSG("Creating receiver with sender context"));
 }
 
+receiver::receiver(link lnk) : link(verify(lnk.get())) {}
+
 void receiver::flow(int count) {
-    pn_link_flow(pn_link(), count);
+    pn_link_flow(get(), count);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 85d79da..a8945b2 100644
--- a/proton-c/bindings/cpp/src/sender.cpp
+++ b/proton-c/bindings/cpp/src/sender.cpp
@@ -36,31 +36,29 @@
 
 namespace proton {
 
+namespace {
 
-sender::sender(pn_link_t *lnk) : link(lnk) {}
-
-void sender::verify_type(pn_link_t *lnk) {
-    if (lnk && pn_link_is_receiver(lnk))
-        throw error(MSG("Creating sender with receiver context"));
+pn_link_t* verify(pn_link_t* l) {
+    if (l && !link(l).is_sender())
+        throw error(MSG("Creating sender from receiver link"));
+    return l;
 }
-
-sender::sender(const link& c) : link(c.pn_link()) {}
-
-
-namespace{
-// revisit if thread safety required
+// 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;
     std::uint64_t id = ++tag_counter;
     *((std::uint64_t *) ptr) = id;
-    pn_delivery_t *dlv = pn_delivery(pn_link(), pn_dtag(tag, 8));
+    pn_delivery_t *dlv = pn_delivery(get(), pn_dtag(tag, 8));
     std::string buf;
     message.encode(buf);
-    pn_link_t *link = pn_link();
+    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)

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 5742f13..9154975 100644
--- a/proton-c/bindings/cpp/src/session.cpp
+++ b/proton-c/bindings/cpp/src/session.cpp
@@ -26,47 +26,27 @@
 #include "proton/session.hpp"
 #include "proton/connection.hpp"
 #include "connection_impl.hpp"
-#include "proton_impl_ref.hpp"
 
 namespace proton {
 
-template class proton_handle<pn_session_t>;
-typedef proton_impl_ref<session> PI;
-
-session::session(pn_session_t *p) {
-    PI::ctor(*this, p);
-}
-session::session() {
-    PI::ctor(*this, 0);
-}
-session::session(const session& c) : proton_handle<pn_session_t>() {
-    PI::copy(*this, c);
-}
-session& session::operator=(const session& c) {
-    return PI::assign(*this, c);
-}
-session::~session() {
-    PI::dtor(*this);
-}
-
-pn_session_t *session::pn_session() { return impl_; }
+session::session(pn_session_t *p) : wrapper<pn_session_t>(p) {}
 
 void session::open() {
-    pn_session_open(impl_);
+    pn_session_open(get());
 }
 
 connection &session::connection() {
-    pn_connection_t *c = pn_session_connection(impl_);
+    pn_connection_t *c = pn_session_connection(get());
     return connection_impl::reactor_reference(c);
 }
 
 receiver session::create_receiver(const std::string& name) {
-    pn_link_t *link = pn_receiver(impl_, name.c_str());
+    pn_link_t *link = pn_receiver(get(), name.c_str());
     return receiver(link);
 }
 
 sender session::create_sender(const std::string& name) {
-    pn_link_t *link = pn_sender(impl_, name.c_str());
+    pn_link_t *link = pn_sender(get(), name.c_str());
     return sender(link);
 }
 

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 f3c76a2..b20c3a3 100644
--- a/proton-c/bindings/cpp/src/sync_request_response.cpp
+++ b/proton-c/bindings/cpp/src/sync_request_response.cpp
@@ -67,7 +67,7 @@ std::string sync_request_response::reply_to() {
 
 void sync_request_response::on_message(event &e) {
     response_.reset(new message);
-    response_->swap(e.message());
+    std::swap(*response_, e.message());
     // Wake up enclosing blocking_connection.wait() to handle the message
     e.container().yield();
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/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 210d273..cff2fa5 100644
--- a/proton-c/bindings/cpp/src/terminus.cpp
+++ b/proton-c/bindings/cpp/src/terminus.cpp
@@ -24,78 +24,47 @@
 
 namespace proton {
 
-template class proton_handle<pn_terminus_t>;
-typedef proton_impl_ref<terminus> PI;
-
-// Note: the pn_terminus_t is not ref counted.  We count the parent link.
-
-terminus::terminus() : link_(0) {
-    impl_ = 0;
-}
-
-terminus::terminus(pn_terminus_t *p, link *l) : link_(l) {
-    impl_ = p;
-    pn_incref(link_->pn_link());
-}
-terminus::terminus(const terminus& c) : proton_handle<pn_terminus_t>() {
-    impl_ = c.impl_;
-    link_ = c.link_;
-    pn_incref(link_->pn_link());
-}
-terminus& terminus::operator=(const terminus& c) {
-    if (impl_ == c.impl_) return *this;
-    if (impl_) pn_decref(link_->pn_link());
-    impl_ = c.impl_;
-    link_ = c.link_;
-    pn_incref(link_->pn_link());
-    return *this;
-}
-terminus::~terminus() {
-    if (impl_)
-        pn_decref(link_->pn_link());
-}
-
-pn_terminus_t *terminus::pn_terminus() { return impl_; }
+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(impl_);
+    return (type_t) pn_terminus_get_type(get());
 }
 
 void terminus::type(type_t type) {
-    pn_terminus_set_type(impl_, (pn_terminus_type_t) type);
+    pn_terminus_set_type(get(), (pn_terminus_type_t) type);
 }
 
 terminus::expiry_policy_t terminus::expiry_policy() {
-    return (expiry_policy_t) pn_terminus_get_type(impl_);
+    return (expiry_policy_t) pn_terminus_get_type(get());
 }
 
 void terminus::expiry_policy(expiry_policy_t policy) {
-    pn_terminus_set_expiry_policy(impl_, (pn_expiry_policy_t) policy);
+    pn_terminus_set_expiry_policy(get(), (pn_expiry_policy_t) policy);
 }
 
 terminus::distribution_mode_t terminus::distribution_mode() {
-    return (distribution_mode_t) pn_terminus_get_type(impl_);
+    return (distribution_mode_t) pn_terminus_get_type(get());
 }
 
 void terminus::distribution_mode(distribution_mode_t mode) {
-    pn_terminus_set_distribution_mode(impl_, (pn_distribution_mode_t) mode);
+    pn_terminus_set_distribution_mode(get(), (pn_distribution_mode_t) mode);
 }
 
 std::string terminus::address() {
-    const char *addr = pn_terminus_get_address(impl_);
+    const char *addr = pn_terminus_get_address(get());
     return addr ? std::string(addr) : std::string();
 }
 
 void terminus::address(const std::string &addr) {
-    pn_terminus_set_address(impl_, addr.c_str());
+    pn_terminus_set_address(get(), addr.c_str());
 }
 
 bool terminus::is_dynamic() {
-    return (type_t) pn_terminus_is_dynamic(impl_);
+    return (type_t) pn_terminus_is_dynamic(get());
 }
 
 void terminus::dynamic(bool d) {
-    pn_terminus_set_dynamic(impl_, d);
+    pn_terminus_set_dynamic(get(), d);
 }
 
 }

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/6bef190d/proton-c/include/proton/link.h
----------------------------------------------------------------------
diff --git a/proton-c/include/proton/link.h b/proton-c/include/proton/link.h
index d9ddca4..58ad5c3 100644
--- a/proton-c/include/proton/link.h
+++ b/proton-c/include/proton/link.h
@@ -280,15 +280,15 @@ PN_EXTERN void pn_link_detach(pn_link_t *link);
  */
 PN_EXTERN pn_terminus_t *pn_link_source(pn_link_t *link);
 
-/**
- * Access the locally defined target definition for a link.
- *
- * The pointer returned by this operation is valid until the link
- * object is freed.
- *
- * @param[in] link a link object
- * @return a pointer to a target terminus
- */
+    /**
+     * Access the locally defined target definition for a link.
+     *
+     * The pointer returned by this operation is valid until the link
+     * object is freed.
+     *
+     * @param[in] link a link object
+     * @return a pointer to a target terminus
+     */
 PN_EXTERN pn_terminus_t *pn_link_target(pn_link_t *link);
 
 /**


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