Skip to content

Commit 32f6b65

Browse files
Added destruct and is_destructed to
- explicitely destruct a C++ object (without waiting for the GC) - check if an object has been destructed
1 parent 4721e44 commit 32f6b65

File tree

11 files changed

+101
-5
lines changed

11 files changed

+101
-5
lines changed

NAMESPACE

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export(Module,
3232
cpp_object_initializer,
3333
cpp_object_dummy,
3434
Rcpp.plugin.maker,
35-
copy
35+
copy,
36+
destruct,
37+
is_destructed
3638
)
3739
S3method( print, bytes )
3840
exportClass(RcppClass)

R/Module.R

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,14 @@ cpp_fields <- function( CLASS, where){
439439
paste0("Rcpp_",name)
440440

441441
copy <- function( obj ){
442-
xp <- .Call(copy_constructor, obj$.cppclass, obj$.pointer )
442+
.Call(copy_constructor, obj$.cppclass, obj$.pointer )
443+
}
444+
445+
destruct <- function(obj){
446+
.Call(destructor, obj$.cppclass, obj$.pointer)
447+
invisible(NULL)
448+
}
443449

450+
is_destructed <- function(obj){
451+
.Call(is_destructed_impl, obj$.pointer)
444452
}

inst/NEWS.Rd

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
\item Changes in Rcpp Modules:
1818
\itemize{
1919
\item New function \code{copy} to invoke the copy constructor of a
20-
C++ class that has been exposed by modules.
20+
C++ class that has been exposed by modules.
21+
\item New function \code{destruct} to explicitely call the
22+
destructor of the underlying C++ object without waiting for the
23+
garbage collector.
24+
\item New function \code{is\_destructed} to check if an object has been
25+
destructed (presumably by \code{destruct} )
2126
}
2227
}
2328
}

inst/include/Rcpp/module/class.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@
170170
END_RCPP
171171
}
172172

173+
SEXP invoke_destructor(SEXP object) {
174+
BEGIN_RCPP
175+
run_finalizer(object);
176+
XP(object).release() ;
177+
return R_NilValue ;
178+
END_RCPP
179+
}
180+
173181
bool has_default_constructor(){
174182
int n = constructors.size() ;
175183
signed_constructor_class* p ;
@@ -498,7 +506,7 @@
498506
vec_signed_factory factories ;
499507
self* class_pointer ;
500508
std::string typeinfo_name ;
501-
509+
502510
class_( ) : class_Base(), vec_methods(), properties(), specials(0), constructors(), factories() {};
503511

504512

inst/include/Rcpp/module/class_Base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class class_Base {
3838
virtual void run_finalizer(SEXP){ }
3939

4040
virtual SEXP invoke_copy_constructor(SEXP) = 0 ;
41+
virtual SEXP invoke_destructor(SEXP) = 0 ;
4142
virtual bool has_default_constructor(){ return false ; }
4243
virtual bool has_method( const std::string& ){
4344
return false ;

inst/unitTests/runit.Module.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,11 @@ if( .runThisTest && Rcpp:::capabilities()[["Rcpp modules"]] ) {
104104
checkEquals( g$x, 4L)
105105
}
106106

107+
test.Module.destructor <- function(){
108+
f <- new( ModuleCopyConstructor, 4L)
109+
checkEquals( !is_destructed(f) )
110+
destruct(f)
111+
checkEquals( is_destructed(f) )
112+
}
113+
107114
}

man/copy.Rd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,4 @@
5555

5656
}
5757
}
58-
\keyword{ ~kwd1 }
58+
\keyword{manip}

man/destruct.Rd

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
\name{destruct}
2+
\alias{destruct}
3+
\alias{is_destructed}
4+
\title{
5+
Explicitely destructs the C++ object.
6+
}
7+
\description{
8+
Explicitely invokes the C++ object destructor.
9+
}
10+
\usage{
11+
destruct(obj)
12+
is_destructed(obj)
13+
}
14+
\arguments{
15+
\item{obj}{A C++ object}
16+
}
17+
\details{
18+
\code{destruct} explicitely destruct the C++ object
19+
\code{is_destructed} checks if it has been destructed
20+
}
21+
\value{
22+
\code{is_destructed} returns a logical.
23+
}
24+
\author{
25+
Romain Francois <romain@r-enthusiasts.com>
26+
}
27+
\examples{
28+
\dontrun{
29+
30+
sourceCpp( code = '
31+
#include <Rcpp.h>
32+
using namespace Rcpp ;
33+
34+
class Foo{
35+
public:
36+
Foo( int x_ ) : x(x_){}
37+
~Foo(){ Rprintf("~Foo\\n") ; }
38+
int x ;
39+
} ;
40+
41+
RCPP_MODULE(test){
42+
class_<Foo>("Foo")
43+
.constructor<int>()
44+
.field( "x", &Foo::x)
45+
;
46+
}
47+
')
48+
f <- new( Foo, 1 )
49+
destruct(f)
50+
is_destructed(f)
51+
52+
}
53+
}
54+
\keyword{manip}

src/Module.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ RCPP_FUN_2( SEXP, copy_constructor, XP_Class cl, SEXP obj){
117117
return cl->invoke_copy_constructor(obj) ;
118118
}
119119

120+
RCPP_FUN_2( SEXP, destructor, XP_Class cl, SEXP obj){
121+
return cl->invoke_destructor(obj) ;
122+
}
123+
RCPP_FUN_1( SEXP, is_destructed_impl, SEXP obj){
124+
return Rf_ScalarLogical( R_ExternalPtrAddr(obj) == NULL ) ;
125+
}
126+
120127
// .External functions
121128
SEXP InternalFunction_invoke(SEXP args) {
122129
BEGIN_RCPP

src/Rcpp_init.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ static R_CallMethodDef callEntries[] = {
5454
CALLDEF(CppField__get,3),
5555
CALLDEF(CppField__set,4),
5656
CALLDEF(copy_constructor,2),
57+
CALLDEF(destructor, 2),
58+
CALLDEF(is_destructed_impl, 1),
5759

5860
CALLDEF(rcpp_capabilities,0),
5961
CALLDEF(rcpp_can_use_cxx0x,0),

0 commit comments

Comments
 (0)