Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Clarification on reference counting

2 views
Skip to first unread message

Andre

unread,
Dec 11, 2001, 8:38:36 AM12/11/01
to
Hello,

This is a followup to an earlier question. I'd like to clarify the
proper maintenance of reference counts to Tcl objects from within a C
extension. I am writing a small extension whose purpose is to provide
access to process information (i.e., on UNIX machines, access to the
information that is maintained in the /proc filesystem). The
extension is to accept process IDs and return the various members of
the process info structure as a Tcl array.

I can see how to set/create Tcl array elements, but as I am doing that
I guess I will need to create intermediate Tcl_Objs to follow the Tcl
C API for SetVar2, etc. These objects (typically a small group of
string values that correspond to the structure members in the procfs.h
headers) only need to exist within the extension and will only be used
to reference the array indices as strings that I am creating. I can
create them with Tcl_NewStringObj, etc.

Do I still need to specifically increment/decrement reference counts
to these temporary objects that are created, or will their storage be
returned to the free pool once execution returns from the extension
procedure? Or are these objects that I've created needed by Tcl
internally as it refers to the defined array indices that I am
creating later on (i.e., outside of my extension)?

Hope this question isn't too naive and thanks again in advance for
advice...

Petasis George

unread,
Dec 14, 2001, 1:37:29 AM12/14/01
to

An easy rule that applies most of the time is that you should
increment the reference count of an object only if *you*
want to keep it somewhere.

Lets say for example that you created a new object.
This has a reference count of zero.
If you pass it to tcl (either set it as the interpreter result or
define a variable and place it as a value) tcl wants to keep it
around, so it increments its reference count to 1.
You don't need to make anything else with this object.

However, this assumes that you know when tcl will keep a reference
to this object, else you are leaking objects. Unfortunately, you will
have to read the man page of each function in order to see if reference
counts of passed objects are incremented.

Alternatively, there is a way that always works:
When you create a new object, always increment its refcount.
Do what ever you want with this object, pass it to tcl or store it
somewhere in your extension. Each time that *you* store it somewhere
increase its refcount. Finally before the function that created the object
returns, decrease the refcount (to match the increment right after
object creation). This is very easy to implement and works always,
independently whether tcl keeps references to this object. Consider
for example the following example:

Obj = Tcl_NewStringObj("varname", -1);
Tcl_IncrRefCount(Obj); // Obj->refCount == 1;
Val = Tcl_NewStringObj("varname", -1);
Tcl_IncrRefCount(Val); // Val->refCount == 1;

/* Define a variable: */
Tcl_ObjSetVar2(interp, Obj, NULL, Val, TCL_GLOBAL_ONLY);
/* Now we have no idea what has happened to our objects. If
tcl kept references to any of them, its refcount will have been
increased. Note that it is possible that tcl has not kept
any reference to any of these, especially if the variable
already existed and had traces... */

/* Set the value as the interp result */
Tcl_SetObjResult(interp, Obj);
/* Here Obj->refCount was for sure increased */

Tcl_DecrRefCount(Obj);
Tcl_DecrRefCount(Val);
/* Finally we don't want these objects any more. Note
that we have said we want them just after they were created.
If tcl has kept references, these objects will be now
managed by tcl. Else, they are freed...*/

I hope its clearer now...

George

Andre

unread,
Dec 15, 2001, 9:34:05 AM12/15/01
to
Thanks very much, George. I think your explanation clarifies things
for me very much! I was unclear on a few points - don't know if my
original post stated my intention well, but this is just a small
extension that would allow access to the /proc filesystem database of
information about running processes on Unix. You can fill up a C
structure with various info and I only want to create a Tcl array
indexed by the names of the structure members to pass that back to the
calling script. So, for example the resulting array would have values
like:

psinfo(rss) = 51928 ; # Resident set size of this process.

I realized I'd have to create a TclObj that was a string "rss" in
order to set the value of the array element. I didn't know what would
"happen" to that object and its memory once the extension returned. I
also expect the extension to handle repeated invocations intelligently
(i.e. not keep creating the same object, since the returned indices
always remain the same). So it seems to me that the best thing to do
is to:

1. Create a series of string TclObjs on first call to the extension.
Set their reference counts all to 1 and keep a pointer to them around
in some static location.

2. Use these objects to set the values for the returned array.

3. On subsequent calls, reuse the objects created in (1) to set/create
array elements for new processes.

I guess Tcl can do what it wants with the objects I create in (1),
either make copies of them or increment the reference count. As long
as it doesn't modify the value in any way, I should be OK. I'll give
that a try - if you see anything wrong with that, comments
appreciated.

Thanks once again for the helpful reply !


Petasis George <pet...@iit.demokritos.gr> wrote in message news:<3C199E29...@iit.demokritos.gr>...

Petasis George

unread,
Dec 19, 2001, 2:02:38 AM12/19/01
to
Andre,

Since your responce didn't show up in my news server, I am answering
to your post I saw on google:

There is absolutely no problem with what you want to do.
Just a simple note though. Allocating objects and free them
is a fast procedure. Why to bother storing them?
I don't expect to gain any measuable difference in speed.

Finally a second tip :-) If you want to be absolutely sure that
the value of an object will never be changed by tcl (or accidently
by you) set its refcount to a value >= 2 (i.e. call Tcl_IncrRefCount
twice). In this case the object becomes a shared object (Tcl_IsShared
returns true for this object). Tcl will never modify a shared object.
If you try to modify it, most of the functions in the tcl api will
cause an abort:-)

Of course this is not applicable in your case, as tcl won't
modify your object when defining the array variables...

George

0 new messages