Rcpp Version 1.0.9
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 
27 namespace Rcpp {
28 
29 template <typename T>
30 void standard_delete_finalizer(T* obj) { // #nocov start
31  delete obj;
32 }
33 
34 template <typename T, void Finalizer(T*) >
35 void finalizer_wrapper(SEXP p) {
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
46  R_ClearExternalPtr(p);
47 
48  Finalizer(ptr);
49 } // #nocov end
50 
51 template <
52  typename T,
53  template <class> class StoragePolicy = PreserveStorage,
54  void Finalizer(T*) = standard_delete_finalizer<T>,
55  #ifdef RCPP_USE_FINALIZE_ON_EXIT
56  bool finalizeOnExit = true
57  #else
58  bool finalizeOnExit = false
59  #endif
60 >
61 class 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 {
69 public:
70 
71  typedef StoragePolicy<XPtr> Storage;
72 
78  explicit XPtr(SEXP x) { checked_set(x); };
79 
87  explicit XPtr(SEXP x, SEXP tag, SEXP prot) {
88  checked_set(x);
89  R_SetExternalPtrTag(x, tag);
90  R_SetExternalPtrProtected(x, prot);
91  };
92 
104  explicit XPtr(T* p, bool set_delete_finalizer = true,
105  SEXP tag = R_NilValue, SEXP prot = R_NilValue) {
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));
108  if (set_delete_finalizer) {
109  setDeleteFinalizer(); // #nocov
110  }
111  }
112 
113  XPtr(const XPtr& other) {
114  Storage::copy__(other);
115  }
116 
117  XPtr& operator=(const XPtr& other) {
118  Storage::copy__(other);
119  return *this;
120  }
121 
126  inline T* get() const {
127  return (T*)(R_ExternalPtrAddr(Storage::get__()));
128  }
129 
134  typedef void (*unspecified_bool_type)();
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
170  R_RegisterCFinalizerEx(Storage::get__(), finalizer_wrapper<T,Finalizer>,
171  (Rboolean) finalizeOnExit);
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 
201 private:
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
T * operator->() const
Definition: XPtr.h:165
void setDeleteFinalizer()
Definition: XPtr.h:169
static void unspecified_bool_true()
Definition: XPtr.h:135
T * checked_get() const
Definition: XPtr.h:146
void checked_set(SEXP x)
Definition: XPtr.h:202
T * get() const
Definition: XPtr.h:126
XPtr(T *p, bool set_delete_finalizer=true, SEXP tag=R_NilValue, SEXP prot=R_NilValue)
Definition: XPtr.h:104
XPtr(SEXP x, SEXP tag, SEXP prot)
Definition: XPtr.h:87
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 & operator*() const
Definition: XPtr.h:157
void(* unspecified_bool_type)()
Definition: XPtr.h:134
bool operator!() const
Definition: XPtr.h:139
XPtr & operator=(const XPtr &other)
Definition: XPtr.h:117
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