Rcpp Version 1.0.7
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 //
6 // This file is part of Rcpp.
7 //
8 // Rcpp is free software: you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by
10 // the Free Software Foundation, either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // Rcpp is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
20 
21 #ifndef Rcpp_XPtr_h
22 #define Rcpp_XPtr_h
23 
24 #include <RcppCommon.h>
25 
26 namespace Rcpp {
27 
28 template <typename T>
29 void standard_delete_finalizer(T* obj) { // #nocov start
30  delete obj;
31 }
32 
33 template <typename T, void Finalizer(T*) >
34 void finalizer_wrapper(SEXP p) {
35  if (TYPEOF(p) != EXTPTRSXP)
36  return;
37 
38  T* ptr = (T*) R_ExternalPtrAddr(p);
39  RCPP_DEBUG_3("finalizer_wrapper<%s>(SEXP p = <%p>). ptr = %p", DEMANGLE(T), p, ptr)
40 
41  if (ptr == NULL)
42  return;
43 
44  // Clear before finalizing to avoid behavior like access of freed memory
45  R_ClearExternalPtr(p);
46 
47  Finalizer(ptr);
48 } // #nocov end
49 
50 template <
51  typename T,
52  template <class> class StoragePolicy = PreserveStorage,
53  void Finalizer(T*) = standard_delete_finalizer<T>,
54  bool finalizeOnExit = false
55 >
56 class XPtr :
57  public StoragePolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
58  public SlotProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
59  public AttributeProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
60  public TagProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
61  public ProtectedProxyPolicy< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >,
62  public RObjectMethods< XPtr<T,StoragePolicy, Finalizer, finalizeOnExit> >
63 {
64 public:
65 
66  typedef StoragePolicy<XPtr> Storage;
67 
73  explicit XPtr(SEXP x) { checked_set(x); };
74 
82  explicit XPtr(SEXP x, SEXP tag, SEXP prot) {
83  checked_set(x);
84  R_SetExternalPtrTag(x, tag);
85  R_SetExternalPtrProtected(x, prot);
86  };
87 
99  explicit XPtr(T* p, bool set_delete_finalizer = true,
100  SEXP tag = R_NilValue, SEXP prot = R_NilValue) {
101  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"))
102  Storage::set__(R_MakeExternalPtr((void*)p , tag, prot));
103  if (set_delete_finalizer) {
104  setDeleteFinalizer(); // #nocov
105  }
106  }
107 
108  XPtr(const XPtr& other) {
109  Storage::copy__(other);
110  }
111 
112  XPtr& operator=(const XPtr& other) {
113  Storage::copy__(other);
114  return *this;
115  }
116 
121  inline T* get() const {
122  return (T*)(R_ExternalPtrAddr(Storage::get__()));
123  }
124 
129  typedef void (*unspecified_bool_type)();
130  static void unspecified_bool_true() {}
131  operator unspecified_bool_type() const {
132  return get() == NULL ? 0 : unspecified_bool_true;
133  }
134  bool operator!() const {
135  return get() == NULL;
136  }
137 
141  inline T* checked_get() const {
142  T* ptr = get();
143  if (ptr == NULL)
144  throw ::Rcpp::exception("external pointer is not valid"); // #nocov
145  return ptr;
146  }
147 
152  T& operator*() const {
153  return *(checked_get());
154  }
155 
160  T* operator->() const {
161  return checked_get();
162  }
163 
164  void setDeleteFinalizer() { // #nocov start
165  R_RegisterCFinalizerEx(Storage::get__(), finalizer_wrapper<T,Finalizer>,
166  (Rboolean) finalizeOnExit);
167  } // #nocov end
168 
178  void release() {
179 
180  if (get() != NULL) {
181  // Call the finalizer -- note that this implies that finalizers
182  // need to be ready for a NULL external pointer value (our
183  // default C++ finalizer is since delete NULL is a no-op).
184  // This clears the external pointer just before calling the finalizer,
185  // to avoid interesting behavior with co-dependent finalizers.
186  finalizer_wrapper<T,Finalizer>(Storage::get__());
187  }
188  }
189 
190  inline operator T*() {
191  return checked_get();
192  }
193 
194  void update(SEXP) {}
195 
196 private:
197  inline void checked_set(SEXP x) {
198  if (TYPEOF(x) != EXTPTRSXP) {
199  const char* fmt = "Expecting an external pointer: [type=%s]."; // #nocov
200  throw ::Rcpp::not_compatible(fmt, Rf_type2char(TYPEOF(x))); // #nocov
201  }
202  Storage::set__(x);
203  }
204 
205 };
206 
207 } // namespace Rcpp
208 
209 #endif
Rcpp::XPtr::checked_get
T * checked_get() const
Definition: XPtr.h:141
Rcpp::XPtr::release
void release()
Definition: XPtr.h:178
Rcpp::XPtr::setDeleteFinalizer
void setDeleteFinalizer()
Definition: XPtr.h:164
Rcpp::XPtr::operator->
T * operator->() const
Definition: XPtr.h:160
Rcpp::XPtr::operator=
XPtr & operator=(const XPtr &other)
Definition: XPtr.h:112
Rcpp::XPtr::update
void update(SEXP)
Definition: XPtr.h:194
Rcpp::XPtr::get
T * get() const
Definition: XPtr.h:121
Rcpp::standard_delete_finalizer
void standard_delete_finalizer(T *obj)
Definition: XPtr.h:29
Rcpp::XPtr::operator*
T & operator*() const
Definition: XPtr.h:152
Rcpp::TagProxyPolicy
Definition: TagProxy.h:24
Rcpp::XPtr::XPtr
XPtr(SEXP x, SEXP tag, SEXP prot)
Definition: XPtr.h:82
Rcpp::XPtr::operator!
bool operator!() const
Definition: XPtr.h:134
Rcpp::finalizer_wrapper
void finalizer_wrapper(SEXP p)
Definition: XPtr.h:34
Rcpp::XPtr::XPtr
XPtr(const XPtr &other)
Definition: XPtr.h:108
DEMANGLE
#define DEMANGLE(__TYPE__)
Definition: exceptions.h:382
Rcpp::XPtr::Storage
StoragePolicy< XPtr > Storage
Definition: XPtr.h:66
RCPP_DEBUG_3
#define RCPP_DEBUG_3(fmt, M1, M2, M3)
Definition: debug.h:46
Rcpp
Rcpp API.
Definition: algo.h:28
Rcpp::RObjectMethods
Definition: RObjectMethods.h:24
Rcpp::XPtr::checked_set
void checked_set(SEXP x)
Definition: XPtr.h:197
Rcpp::ProtectedProxyPolicy< XPtr< T, PreserveStorage, standard_delete_finalizer< T >, false > >::prot
ProtectedProxy prot()
Definition: ProtectedProxy.h:83
RcppCommon.h
Rcpp::XPtr
Definition: XPtr.h:63
Rcpp::TagProxyPolicy< XPtr< T, PreserveStorage, standard_delete_finalizer< T >, false > >::tag
TagProxy tag()
Definition: TagProxy.h:73
Rcpp::SlotProxyPolicy
Definition: SlotProxy.h:24
Rcpp::ProtectedProxyPolicy
Definition: ProtectedProxy.h:26
RCPP_DEBUG_2
#define RCPP_DEBUG_2(fmt, M1, M2)
Definition: debug.h:45
Rcpp::AttributeProxyPolicy
Definition: AttributeProxy.h:24
Rcpp::XPtr::XPtr
XPtr(T *p, bool set_delete_finalizer=true, SEXP tag=R_NilValue, SEXP prot=R_NilValue)
Definition: XPtr.h:99
Rcpp::XPtr::unspecified_bool_type
void(* unspecified_bool_type)()
Definition: XPtr.h:129
Rcpp::XPtr::unspecified_bool_true
static void unspecified_bool_true()
Definition: XPtr.h:130
Rcpp::XPtr::XPtr
XPtr(SEXP x)
Definition: XPtr.h:73