[Gambas-devel] Store GB_VARIANT in memory

Benoît Minisini gambas at ...1...
Fri Aug 17 18:15:24 CEST 2012


Le 17/08/2012 18:05, Tobias Boege a écrit :
> On Fri, 17 Aug 2012, Beno?t Minisini wrote:
>> Le 17/08/2012 17:36, Tobias Boege a ?crit :
>>> On Tue, 14 Aug 2012, Tobias Boege wrote:
>>>>> BEGIN_METHOD_VOID(Restore)
>>>>>
>>>>>      // The variant is copied in a temporary place.
>>>>>      GB.ReturnVariant(&THIS->tag);
>>>>>
>>>>>      // Free the stored variant.
>>>>>      // But you can't do it now, because the Variant will
>>>>>      // be referenced after the function has returned only.
>>>>>      // GB.StoreVariant(NULL, &THIS->tag);
>>>>>
>>>>> END_METHOD
>>>>>
>>>>> --8<-------------------------------------------------------
>>>>>
>>>>> Regards,
>>>>>
>>>>> --
>>>>> Beno?t Minisini
>>>>>
>>>>
>>>> _This_ is confusing and may be the error in my code. I thought, the Variant
>>>> is copied to a temporary place by GB.Return*() (AFAICS this "TEMP" variable.
>>>> Haven't I once heard that Gambas is not thread-safe? :-))
>>>> Why can't I free up my storage of the Variant?
>>>> Maybe my approach is just too different from what you proposed... What comes
>>>> to my mind now is this: GB.StoreVariant() refs the Object it takes but it
>>>> gets never unref'd by my code. If this is true, no wonder why I had memory
>>>> errors...
>>>>
>>>> I can (and actually wanted to) rewrite the code a bit so I can test your
>>>> suggestion - which is not to try to free the buffer but instead keep it and
>>>> re-use like the Array classes do. We'll see... Thanks.
>>>>
>>>> Regards,
>>>> Tobi
>>>
>>> OK, recalling the Socket class I apparently found a method to do this
>>> properly: I GB.Post() my destruction function. This works perfectly and is -
>>> I hope - correct.
>>>
>>> Commit coming soon.
>>>
>>> Regards,
>>> Tobi
>>>
>>
>> That hack won't work if you don't have an event loop. And it's an
>> horrible hack. :-)
>>
>> What you need is something like what has been used in the implementation
>> of the Array.Pop() method : that method returns something that must be
>> freed.
>>
>> That needs some new stuff in the interpreter API.
>>
>> But at the moment I'm not sure how I will do that, so you must wait a
>> little!
>>
>> Regards,
>>
>> --
>> Beno?t Minisini
>>
>
> There is a question I wanted to ask after I commited but as it certainly
> comes from this "horrible hack": I noticed that with the above method I get
> objects which I put in a Stack or Queue (and never popped or dequeued in
> order to test their self-cleanup functions) destroyed *really* late, not
> to say at program termination. This would be one outcome of the missing
> event loop, most probably.
> It worked so far and I don't fear changing it later in favour of something
> better. Hmm, well, Array.Pop() certainly does its job but I thought _this_
> would be a hack. It is nebulous to me what it does after GB.ReturnPtr() and
> why but I will dig deeper into the right way once the code is up.
>
> Regards,
> Tobi
>

The returned value is referenced when put on the caller stack after the 
function have actually returned.

So if you release it just after the call to GB.ReturnXXX(), you actually 
free it before the interpreter sees it!

So the trick is using two functions: "Borrow", that references a value, 
and "Unborrow", that dereferences it without freeing it (as we know that 
the return value will be reference later).

So it will be a matter of writing something like that:

BEGIN_METHOD_VOID(Restore)

   // The variant is copied in a temporary place.
   GB.ReturnVariant(&THIS->tag);

   // Unreference the variant without freeing it, and put NULL
   // inside the tag. I call the method "Release" and not "Borrow".
   GB.ReleaseVariant(&THIS->tag);

END_METHOD

For coherency, I should add a GB.ReleaseObject() and GB.ReleaseString() 
method.

I will tell you when this is done.

-- 
Benoît Minisini




More information about the Devel mailing list