On Mon, 2015-08-17 at 10:38 -0400, Andrew Stitcher wrote:
> I like the way you're thinking - I expect to have real time to look 
> at
> your code Tomorrow/Wednesday.
> One point that occurred to me over the weekend (that I think is
> probably incorporated in what you've done here). Is that C++ code 
> never
> needs to use a shared_ptr to any Proton struct because Proton ref
> counts by itself. In other words the C++ ref count could only ever by 
> 0
> or 1. All the C++ code ever needs is a unique_ptr. I suspect this 
> point
> doesn't really affect your proposal here though.
> Andrew

Here's a preview of what I'm thinking now, it follows from the code I

   The C++ proton binding can be used in a memory-safe way via
   std::unique_ptr, boost::shared_ptr and boost::intrusive_ptr. If you
are using
   an older C++ compiler and cannot use boost, you can can optionally
   proton::pn_shared_ptr to automate memory management.

   You can also use the binding in an *unsafe* C-like way with plain
pointers if
   you must avoid the (low) overhead of reference counting, or if you
are writing
   mixed C/C++ code. Caveat emptor.

template <class T> class pn_shared_ptr;
template <class T> class pn_borrowed_ptr;

/** Base class for pn_ smart pointers, see pn_shared_ptr and
pn_borrowed_ptr */
template <class T> class pn_base_ptr {
    typedef typename T::pn_type pn_type;

    T* get() const { return ptr_; }
    operator T*() const { return ptr_; }
    T* operator->() const { return ptr_; }

    // get_pn is only needed if you are mixing C and C++ proton code.
    pn_type* get_pn() const { return reinterpret_get_pn<P*>(ptr_); }

#if PN_USE_CPP11
    operator std::shared_ptr<T>() const { return
std::shared_ptr<T>(incref(), pn_object_decref); }
    operator std::unique_ptr<T>() const { return
std::unique_ptr<T>(incref(), pn_object_decref); }
    operator boost::shared_ptr<T>() const { return
boost::shared_ptr<T>(incref(), pn_object_decref); }
    operator boost::intrusive_ptr<T>() const { TODO; }

    // FIXME aconway 2015-08-17: get_pning conversions to compatible

    pn_base_ptr(T* p) : ptr_(p) {}

    T* incref() { pn_object_incref(get_pn()); return ptr_; }
    void decref() { pn_object_decref(get_pn()); }

    T* ptr_;

    template <> friend class pn_shared_ptr<T>;
    template <> friend class pn_borrowed_ptr<T>;

   pn_shared_ptr is a smart pointer template that uses proton's
   reference counting. Proton objects hold their own reference count so
there is
   no separate "counter" object allocated. The memory footprint is the
same as a
   plain pointer.

   It is provided as a convenience for programmers that have pre-c++11
   and cannot use the boost libraries. If you have access to
   std::unique_ptr, boost::shared_ptr or boost::intrusive_ptr you can
use them
   instead. pn_shared_ptr converts automatically with correct reference
template <class T> class pn_shared_ptr : public pn_base_ptr<T> {
    pn_shared_ptr(pn_shared_ptr p) : ptr_(p) { incref(); }
    pn_shared_ptr(pn_borrowed_ptr p) : ptr_(p) { incref(); }
    ~pn_shared_ptr() { decref(); }

    pn_shared_ptr(T* p) : pn_base_ptr<T>(p) {}
    template <> friend class pn_shared_ptr<T>;

   pn_borrowed_ptr<> is used as a return and parameter type in
   to automate correct memory management. You do not normally need to
use it in
   your own code.

   It behaves like (and converts to/from) a plain pointer, the only
   from a plain pointer is that converting it to any "owning" smart
pointer type
   will automatically add a reference. Converting from (i.e.
"borrowing") a plain
   or smart pointer will not change the reference couint.
template <class T> class pn_borrowed_ptr : public pn_base_ptr<T> {
    typedef typename pn_base_ptr<T>::pn_type pn_type;

    /** This constructor is only needed if you are mixing C and C++
proton code */
    explict pn_borrowed_ptr(pn_type* p) :
pn_base_ptr(dynamic_cast<T*>(p)) {}
    pn_borrowed_ptr(T* p) : pn_base_ptr<T>(p) {}
    operator T*() const { return ptr_; }
    operator pn_shared_ptr<T>() const { return
pn_shared_ptr<T>(incref()); }

Reply via email to