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]