File: XPtr.h

package info (click to toggle)
rcpp 0.11.3-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,948 kB
  • ctags: 16,427
  • sloc: ansic: 42,692; cpp: 34,078; makefile: 32; sh: 21
file content (130 lines) | stat: -rw-r--r-- 4,258 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
//
// XPtr.h: Rcpp R/C++ interface class library -- smart external pointers
//
// Copyright (C) 2009 - 2013	Dirk Eddelbuettel and Romain Francois
//
// This file is part of Rcpp.
//
// Rcpp is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Rcpp is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.

#ifndef Rcpp_XPtr_h
#define Rcpp_XPtr_h

#include <RcppCommon.h>

namespace Rcpp{

template <typename T>
void standard_delete_finalizer(T* obj){
    delete obj ;
}

template <typename T, void Finalizer(T*) >
void finalizer_wrapper(SEXP p){
    if( TYPEOF(p) == EXTPTRSXP ){
        T* ptr = (T*) R_ExternalPtrAddr(p) ;
        RCPP_DEBUG_3( "finalizer_wrapper<%s>(SEXP p = <%p>). ptr = %p", DEMANGLE(T), p, ptr  )
        Finalizer(ptr) ;
    }
}

template <
    typename T,
    template <class> class StoragePolicy = PreserveStorage,
    void Finalizer(T*) = standard_delete_finalizer<T>
>
class XPtr :
    public StoragePolicy< XPtr<T,StoragePolicy, Finalizer> >,
    public SlotProxyPolicy< XPtr<T,StoragePolicy, Finalizer> >,
    public AttributeProxyPolicy< XPtr<T,StoragePolicy, Finalizer> >,
    public TagProxyPolicy< XPtr<T,StoragePolicy, Finalizer> >,
    public ProtectedProxyPolicy< XPtr<T,StoragePolicy, Finalizer> >,
    public RObjectMethods< XPtr<T,StoragePolicy, Finalizer> >
{
public:

    typedef StoragePolicy<XPtr> Storage ;

    /**
     * constructs a XPtr wrapping the external pointer (EXTPTRSXP SEXP)
     *
     * @param xp external pointer to wrap
     */
    explicit XPtr(SEXP x, SEXP tag = R_NilValue, SEXP prot = R_NilValue) {
        if( TYPEOF(x) != EXTPTRSXP )
            throw ::Rcpp::not_compatible( "expecting an external pointer" ) ;
        Storage::set__(x) ;
        R_SetExternalPtrTag( x, tag ) ;
        R_SetExternalPtrProtected( x, prot ) ;
    } ;

    /**
     * creates a new external pointer wrapping the dumb pointer p.
     *
     * @param p dumb pointer to some object
     * @param set_delete_finalizer if set to true, a finalizer will
     *        be registered for the external pointer. The finalizer
     *        is called when the xp is garbage collected. The finalizer
     *        is merely a call to the delete operator or the pointer
     *        so you need to make sure the pointer can be "delete" d
     *        this way (has to be a C++ object)
     */
    explicit XPtr(T* p, bool set_delete_finalizer = true, SEXP tag = R_NilValue, SEXP prot = R_NilValue){
        RCPP_DEBUG_2( "XPtr(T* p = <%p>, bool set_delete_finalizer = %s, SEXP tag = R_NilValue, SEXP prot = R_NilValue)", p, ( set_delete_finalizer ? "true" : "false" ) )
        Storage::set__( R_MakeExternalPtr( (void*)p , tag, prot) ) ;
        if( set_delete_finalizer ){
            setDeleteFinalizer() ;
        }
    }

    XPtr( const XPtr& other ) {
        Storage::copy__(other) ;
    }

    XPtr& operator=(const XPtr& other){
    	    Storage::copy__(other) ;
    	    return *this ;
    }

    /**
     * Returns a reference to the object wrapped. This allows this
     * object to look and feel like a dumb pointer to T
     */
    T& operator*() const {
        return *((T*)R_ExternalPtrAddr( Storage::get__() )) ;
    }

    /**
     * Returns the dumb pointer. This allows to call the -> operator
     * on this as if it was the dumb pointer
     */
    T* operator->() const {
         return (T*)(R_ExternalPtrAddr( Storage::get__() ));
    }

    void setDeleteFinalizer() {
        R_RegisterCFinalizerEx( Storage::get__(), finalizer_wrapper<T,Finalizer> , FALSE) ;
    }

    inline operator T*(){
        return (T*)( R_ExternalPtrAddr( Storage::get__() )) ;
    }

    void update(SEXP){}
};

} // namespace Rcpp

#endif