Rcpp Version 1.0.14
Loading...
Searching...
No Matches
XPtr.h
Go to the documentation of this file.
1//
2// XPtr.h: Rcpp R/C++ interface class library -- smart external pointers
3//
4// Copyright (C) 2009 - 2020 Dirk Eddelbuettel and Romain Francois
5// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and IƱaki Ucar
6//
7// This file is part of Rcpp.
8//
9// Rcpp is free software: you can redistribute it and/or modify it
10// under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 2 of the License, or
12// (at your option) any later version.
13//
14// Rcpp is distributed in the hope that it will be useful, but
15// WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21
22#ifndef Rcpp_XPtr_h
23#define Rcpp_XPtr_h
24
25#include <RcppCommon.h>
26
27namespace Rcpp {
28
29template <typename T>
30void standard_delete_finalizer(T* obj) { // #nocov start
31 delete obj;
32}
33
34template <typename T, void Finalizer(T*) >
36 if (TYPEOF(p) != EXTPTRSXP)
37 return;
38
39 T* ptr = (T*) R_ExternalPtrAddr(p);
40 RCPP_DEBUG_3("finalizer_wrapper<%s>(SEXP p = <%p>). ptr = %p", DEMANGLE(T), p, ptr)
41
42 if (ptr == NULL)
43 return;
44
45 // Clear before finalizing to avoid behavior like access of freed memory
47
48 Finalizer(ptr);
49} // #nocov end
50
51template <
52 typename T,
53 template <class> class StoragePolicy = PreserveStorage,
55 #ifdef RCPP_USE_FINALIZE_ON_EXIT
56 bool finalizeOnExit = true
57 #else
58 bool finalizeOnExit = false
59 #endif
60>
61class XPtr :
62 public StoragePolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
63 public SlotProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
64 public AttributeProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
65 public TagProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
66 public ProtectedProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
67 public RObjectMethods< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >
68{
69public:
70
72
78 explicit XPtr(SEXP x) { checked_set(x); };
79
92
104 explicit XPtr(T* p, bool set_delete_finalizer = true,
106 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"))
107 Storage::set__(R_MakeExternalPtr((void*)p , tag, prot));
109 setDeleteFinalizer(); // #nocov
110 }
111 }
112
113 XPtr(const XPtr& other) {
114 Storage::copy__(other);
115 }
116
118 Storage::copy__(other);
119 return *this;
120 }
121
126 inline T* get() const {
127 return (T*)(R_ExternalPtrAddr(Storage::get__()));
128 }
129
135 static void unspecified_bool_true() {}
136 operator unspecified_bool_type() const {
137 return get() == NULL ? 0 : unspecified_bool_true;
138 }
139 bool operator!() const {
140 return get() == NULL;
141 }
142
146 inline T* checked_get() const {
147 T* ptr = get();
148 if (ptr == NULL)
149 throw ::Rcpp::exception("external pointer is not valid"); // #nocov
150 return ptr;
151 }
152
157 T& operator*() const {
158 return *(checked_get());
159 }
160
165 T* operator->() const {
166 return checked_get();
167 }
168
169 void setDeleteFinalizer() { // #nocov start
172 } // #nocov end
173
183 void release() {
184
185 if (get() != NULL) {
186 // Call the finalizer -- note that this implies that finalizers
187 // need to be ready for a NULL external pointer value (our
188 // default C++ finalizer is since delete NULL is a no-op).
189 // This clears the external pointer just before calling the finalizer,
190 // to avoid interesting behavior with co-dependent finalizers.
191 finalizer_wrapper<T,Finalizer>(Storage::get__());
192 }
193 }
194
195 inline operator T*() {
196 return checked_get();
197 }
198
199 void update(SEXP) {}
200
201private:
202 inline void checked_set(SEXP x) {
203 if (TYPEOF(x) != EXTPTRSXP) {
204 const char* fmt = "Expecting an external pointer: [type=%s]."; // #nocov
205 throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x))); // #nocov
206 }
207 Storage::set__(x);
208 }
209
210};
211
212} // namespace Rcpp
213
214#endif
void setDeleteFinalizer()
Definition XPtr.h:169
static void unspecified_bool_true()
Definition XPtr.h:135
void checked_set(SEXP x)
Definition XPtr.h:202
XPtr(T *p, bool set_delete_finalizer=true, SEXP tag=R_NilValue, SEXP prot=R_NilValue)
Definition XPtr.h:104
T * operator->() const
Definition XPtr.h:165
XPtr(SEXP x, SEXP tag, SEXP prot)
Definition XPtr.h:87
XPtr & operator=(const XPtr &other)
Definition XPtr.h:117
T * checked_get() const
Definition XPtr.h:146
XPtr(const XPtr &other)
Definition XPtr.h:113
void release()
Definition XPtr.h:183
StoragePolicy< XPtr > Storage
Definition XPtr.h:71
XPtr(SEXP x)
Definition XPtr.h:78
T * get() const
Definition XPtr.h:126
T & operator*() const
Definition XPtr.h:157
void(* unspecified_bool_type)()
Definition XPtr.h:134
bool operator!() const
Definition XPtr.h:139
void update(SEXP)
Definition XPtr.h:199
#define RCPP_DEBUG_2(fmt, M1, M2)
Definition debug.h:45
#define RCPP_DEBUG_3(fmt, M1, M2, M3)
Definition debug.h:46
#define DEMANGLE(__TYPE__)
Definition exceptions.h:382
Rcpp API.
Definition algo.h:28
void standard_delete_finalizer(T *obj)
Definition XPtr.h:30
void finalizer_wrapper(SEXP p)
Definition XPtr.h:35
T as(SEXP x)
Definition as.h:151