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

______________________________________________
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel

Reply via email to