[Disclaimer: what is below reflects my understanding from reading the R source, others will correct where deemed necessary]
On 1/2/10 12:00 PM, r-devel-request at r-project.org 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.
The most precise technical documentation is in memory.c PROTECT is an alias for Rf_protect, itself an alias for SEXP protect(SEXP s); and uses a stack (R_PPStack) to store protected objects.
In particular, if we preserve the same SEXP twice (or more), should we implement some sort of reference counting ?
This depends on the requirements for your system. For example, in rpy2 I added a reference counting layer(*) because I wanted to allow several Python objects to share the same underlying R object, but that's not currently(*) counting how many times an object should be freed. (*: imperfect, but currently doing a very decent job - details upon request). That kind of feature could be provided by R's C-level API, since this could be seen of general use as well as give an opportunity to improve the performances of the R_PreservedObject/R_ReleaseObject duo whenever a lot of objects are protected and/or external code is protecting/releasing objects through a FIFO proxy.
Reading the source (below, from memory.c) I think not, but some confirmation would help.
I understand the code in memory.c like an object preserved twice needs to be freed twice: R_PreciousList is just a (linked) list, and "R_PreserveObject(object)" adds the object to the beginning of the list while "R_ReleaseObject(object)" removes the first "object" found from the list.
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 trading granularity for speed. It is a stack with only tow operations possible: - push 1 object into the stack - pull (unprotect) N last objects from the stack HTH, L.
Thanks, Romain [1]http://lists.r-forge.r-project.org/pipermail/rcpp-devel/ [2] http://r-forge.r-project.org/plugins/scmsvn/viewcvs.php/pkg/src/RObject.cpp?rev=255&root=rcpp&view=markup -- 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