From romain.francois at dbmail.com  Sat Jan  2 17:50:59 2010
From: romain.francois at dbmail.com (Romain Francois)
Date: Sat, 02 Jan 2010 17:50:59 +0100
Subject: [Rd] R_PreserveObject,
 R_ReleaseObject : reference counting needed ?
In-Reply-To: <4B3F7625.1080806@gmail.com>
References: <mailman.11.1262430004.8711.r-devel@r-project.org>
	<4B3F7625.1080806@gmail.com>
Message-ID: <4B3F7973.70203@dbmail.com>

Thanks.

On 01/02/2010 05:36 PM, Laurent Gautier wrote:
>
> [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.

We wrap up SEXP into a C++ class that in particular manages itself 
preserving and releasing the object to garbage collection.

> 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.

That's what I understand of it too. It fits nicely into C++ assignment 
operator and copy constructor.

>> 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



[Rd] R_PreserveObject, R_ReleaseObject : reference counting needed ?
Romain Francois