[Rd] R_PreserveObject, R_ReleaseObject : reference counting needed ?

Romain Francois romain.francois at dbmail.com
Sat Jan 2 18:24:39 CET 2010


On 01/02/2010 06:01 PM, Simon Urbanek wrote:
>
>
> On Jan 2, 2010, at 5:07 AM, Romain Francois wrote:
>
>> Hello,
>>
>> We are currently making lots of changes to Rcpp (see the open Rcpp mailing list if interested [1] in the details).
>>
>> We are now using [2] R_PreserveObject and R_ReleaseObject to manage garbage collection instead of the PROTECT/UNPROTECT dance. This seems to work well, but I was wondering if there was documentation about it.
>>
>
> I don't think so - the only documentation is the comment in the source.


Fair enough. FWIW, some mention of it in the R-ints or R-exts could be 
valuable.


>> In particular, if we preserve the same SEXP twice (or more), should we implement some sort of reference counting ?
>>
>
> Preserve/Release are for managing objects that are supposed to survive past the call and are not tied to any other R object. PROTECT/UNPROTECT are for temporary preservation within a call.
>
> Although you're right that Preserve/Release is effectively implemented as a stack at the moment it is not stated explicitly anywhere (this goes all the way back to R 0.64 so chances are that only Ross can comment..). However, for practical purposes it would be potentially dangerous to have it work like a flag because you can simply never know whether the same object was not already registered by some other code.
>
>
>> Reading the source (below, from memory.c) I think not, but some confirmation would help.
>>
>> void R_PreserveObject(SEXP object)
>> {
>>     R_PreciousList = CONS(object, R_PreciousList);
>> }
>>
>> static SEXP RecursiveRelease(SEXP object, SEXP list)
>> {
>>     if (!isNull(list)) {
>> 	if (object == CAR(list))
>> 	    return CDR(list);
>> 	else
>> 	    CDR(list) = RecursiveRelease(object, CDR(list));
>>     }
>>     return list;
>> }
>>
>> void R_ReleaseObject(SEXP object)
>> {
>>     R_PreciousList =  RecursiveRelease(object, R_PreciousList);
>> }
>>
>>
>> I'd also be interested if there is some ideas on the relative efficiency of the preserve/release mechanism compared to PROTECT/UNPROTECT.
>>
>
> PROTECT/UNPROTECT is more efficient because all it does is a pointer assignment -- Preserve has to allocate new node and fill it with all parts. On release the extra node is still floating in the GC pool etc.
>
> Normally there is not really a question of choice - within a call you want to use PROTET/UNPROTECT and for anything else you simply cannot use it so you have to use Preserve/Release. As a side note Preserve/Release is merely a convenience call, it is often more efficient to simply assign the object to another object you have control of (which is all Preserve really does).
>
> Cheers,
> Simon

Thanks for this advice. This will make it easier to do the bookkeeping 
of how many objects we preserve, etc ...

Romain

-- 
Romain Francois
Professional R Enthusiast
+33(0) 6 28 91 30 30
http://romainfrancois.blog.free.fr
|- http://tr.im/IW9B : C++ exceptions at the R level
|- http://tr.im/IlMh : CPP package: exposing C++ objects
`- http://tr.im/HlX9 : new package : bibtex



More information about the R-devel mailing list