On 07/16/2015 02:40 PM, aconway wrote:
Can someone who understand the proton use of refcounts please add some
doc comments to explain the semantics? Apologies if this is already
there and I missed it, tell me to RTFM.

I'm not entirely sure I understand it. However having spent a couple of days reading and puzzling over the code, I'll try and offer some answers where I think I can, and add some questions of my own.

For comparison here is what "refcount" traditionally means ("tradition"
includes CORBA, boost::intrusive_ptr, std::shared_ptr etc.) I'm not
saying we have to make proton conform, but we should document how it
differs to save confusion.

1. A refcount is a count of the number of references (owning pointers)
to an object.

Yes, that broadly speaking is the purpose in proton. However this was a recent addition and it is not used uniformly inside the library itself. Not only that but the old api, where the application (generally) owned the pointers it created until it called pn_xxx_free, is still supported alongside the newer mode of use, as e.g. employed in the python binding, where the application uses only incref and decref.

2. Objects are created with refcuont=1, the creator owns the first
reference.

This is not always the case and was one of the points I found surprising. Though a newly created 'object' does indeed have its ref count set to 1, for pn_session() and pn_link(), which are the functions actually used by the application to created new sessions or links, the implementation of those functions includes an explicit decref, meaning the objects are returned with a ref count of 0.

I suspect this was done to simplify things for the newer mode of use, where a wrapper object can always be instantiated and it simply increments the ref count. Would be good to have that confirmed though, as to me this is the source of confusion and complexity.

However this means that in the old mode of use, e.g. pn_session()/pn_session_free(), the object may have a refcount of 0 even though it has not been freed by the application.

3. If another owning reference is created, the refcount MUST BE
incremented.

This is not currently the case for all internal use which necessitates some extra logic and checks.

4. The owner of a reference MUST decrease the refcount on dropping the
reference and MUST NOT use the pointer after refcount is decremented.
It no longer "owns" a reference.

5. The object MAY be deleted when refcount goes to 0 or MAY be pooled
for re-use but it MUST NOT be used by any code (other than the pooling
system if there is one)

As above, that is currently not completely true at least for sessions and links, where they may be in use while still having a 0 ref count.

6. You never examine the refcount (except for debugging) Either you own
a reference, which means refcount > 0, or you don't, which means you
MUST NOT touch the object, even to examine its refcount.

My questions:

* what are the respective roles of the ref count in pn_endpoint_t, and in the pni_head_t record associated with pn_session_t and pn_link_t? i.e. why are there two separate ref counts for the same object?

* pn_link_new() and pn_session() both decrement the count (in the pni_head_t record) for the newly created objects. Why?

* what exactly does the 'referenced' flag indicate?

* when a finalize function is exited early due to the return value of pni_preserve_child, the reference count is incremented to prevent that object being freed by the code in pn_class_decref. Where/how is that then decremented again to retrigger the finalizer?

* when should pn_class_free be used v pn_class_decref? (The former does not check whether the finalizer increases the reference, the latter does)

* pn_class_free() has the precondition that the object passed in should have a refcount of 1 (which I understand) or -1. When and why would the refcount be -1?

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to