Gertjan <
gho...@gmail.com> wrote:
> I could replicate the actual code but I think the pseudo version will
> do. Its typical I think.
>
> INT32 GetMyData (ClientData clientdata, Tcl_Interp *interp, INT32 argc, const CHAR *argv[])
>
> Loop over N data elements:
> Tcl_Obj *pSubList = Tcl_NewListObj(0,NULL);
>
> Now put Time and a Float into pSubList using two calls to
> TclListObjAppendElement(interp, pSubList,....);
>
> //copy the sublist as a single element to the output list:
> Tcl_ListObjAppendElement(interp, pOutList, pSubList);
> EndLoop
> Tcl_SetObjResult(interp, pOutList);
> return TCL_OK;
>
> Works like a charm, I get { {time1}{data1} {time2}{data2}...
>
> Any C-programmer not terribly familiar with the Tcl API should
> immediately be concerned about the repeated Tcl_NewListObj(). Who
> cleans up ?
Provided the extension writer does not do something funky with the ref
counter, the Tcl runtime cleans up when the last reference to the list
disappears.
> Having gained more understanding, perhaps some one can judge the
> following statements:
>
> 1. An AppendElement API call doesn't extend the size of the pOutList
> - it merely make a reference to the pSubList in pOutList. For that
> reason, the AppendElement call increments the ref counter on
> pSubList - it is now 'shared' and needs to stay alive.
Well, it does extend the size of pOutList - by one more element.
But yes, the sub-list will have it's refcount incremented as part of
the 'append' process.
> 2. The AppendElement API does *not* increment pOutList ref counter
> because that list is not shared anywhere. In fact the call will fail
> it is ever sees pOutList with a non-zero reference counter
It should not do so, because it is not creating a new reference to the
outer list container, so no reason to increment the ref counter of the
outer list.
> 3. The Tcl_SetObjResult(interp, pOutList); increments the Ref
> counter of pOutlist because the interpreter needs these data and it
> should not be cleaned up.
Yes, and at the same time, the Tcl runtime takes over 'ownership' and
tracking to determine when to free() the allocated memory.
> Now for the final statement. Lets say I call my C function in a
> loop:
>
> While { 1 } {
> set MyData [GetMyData ]
> }
>
> 4. The Tcl interpreters will recursively Free the memory for ALL the
> lists objects created in a previous call to GetMyData upon executing
> the next one when $MyData is over-written. Right ? Otherwise we
> have a memory leak.
Yes, each time MyData is overwritten, the old data in MyData will first
be freed.
> Let me know if (1)..(4) are correct. The bottom line is that I dont
> really need to worry about the ref counts of "temporary" lists (they
> aren't temporary) or what happens with my pOutList.
From your psudeo code, it looks like you likely don't need to do
anything with the ref counters for things to work out properly and for
Tcl to take over the lifetime management of the resulting list.