summaryrefslogtreecommitdiffstats
path: root/src/arrow/r/inst/include/cpp11/external_pointer.hpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/arrow/r/inst/include/cpp11/external_pointer.hpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/arrow/r/inst/include/cpp11/external_pointer.hpp b/src/arrow/r/inst/include/cpp11/external_pointer.hpp
new file mode 100644
index 000000000..059a1aa55
--- /dev/null
+++ b/src/arrow/r/inst/include/cpp11/external_pointer.hpp
@@ -0,0 +1,166 @@
+// cpp11 version: 0.3.1.1
+// vendored on: 2021-08-11
+#pragma once
+
+#include <cstddef> // for nullptr_t, NULL
+#include <memory> // for bad_weak_ptr
+#include <type_traits> // for add_lvalue_reference
+
+#include "cpp11/R.hpp" // for SEXP, SEXPREC, TYPEOF, R_NilValue, R_C...
+#include "cpp11/protect.hpp" // for protect, safe, protect::function
+#include "cpp11/r_bool.hpp" // for r_bool
+#include "cpp11/r_vector.hpp" // for type_error
+#include "cpp11/sexp.hpp" // for sexp
+
+namespace cpp11 {
+
+template <typename T>
+void default_deleter(T* obj) {
+ delete obj;
+}
+
+template <typename T, void Deleter(T*) = default_deleter<T>>
+class external_pointer {
+ private:
+ sexp data_ = R_NilValue;
+
+ static SEXP valid_type(SEXP data) {
+ if (TYPEOF(data) != EXTPTRSXP) {
+ throw type_error(EXTPTRSXP, TYPEOF(data));
+ }
+
+ return data;
+ }
+
+ static void r_deleter(SEXP p) {
+ if (TYPEOF(p) != EXTPTRSXP) return;
+
+ T* ptr = static_cast<T*>(R_ExternalPtrAddr(p));
+
+ if (ptr == NULL) {
+ return;
+ }
+
+ R_ClearExternalPtr(p);
+
+ Deleter(ptr);
+ }
+
+ public:
+ using pointer = T*;
+
+ external_pointer() noexcept {}
+ external_pointer(std::nullptr_t) noexcept {}
+
+ external_pointer(SEXP data) : data_(valid_type(data)) {}
+
+ external_pointer(pointer p, bool use_deleter = true, bool finalize_on_exit = true)
+ : data_(safe[R_MakeExternalPtr]((void*)p, R_NilValue, R_NilValue)) {
+ if (use_deleter) {
+ R_RegisterCFinalizerEx(data_, r_deleter, static_cast<r_bool>(finalize_on_exit));
+ }
+ }
+
+ external_pointer(const external_pointer& rhs) {
+ data_ = safe[Rf_shallow_duplicate](rhs.data_);
+ }
+
+ external_pointer(external_pointer&& rhs) { reset(rhs.release()); }
+
+ external_pointer& operator=(external_pointer&& rhs) noexcept { reset(rhs.release()); }
+
+ external_pointer& operator=(std::nullptr_t) noexcept { reset(); };
+
+ operator SEXP() const noexcept { return data_; }
+
+ pointer get() const noexcept {
+ pointer addr = static_cast<T*>(R_ExternalPtrAddr(data_));
+ if (addr == nullptr) {
+ return nullptr;
+ }
+ return addr;
+ }
+
+ typename std::add_lvalue_reference<T>::type operator*() {
+ pointer addr = get();
+ if (addr == nullptr) {
+ throw std::bad_weak_ptr();
+ }
+ return *get();
+ }
+
+ pointer operator->() const {
+ pointer addr = get();
+ if (addr == nullptr) {
+ throw std::bad_weak_ptr();
+ }
+ return get();
+ }
+
+ pointer release() noexcept {
+ if (get() == nullptr) {
+ return nullptr;
+ }
+ pointer ptr = get();
+ R_ClearExternalPtr(data_);
+
+ return ptr;
+ }
+
+ void reset(pointer ptr = pointer()) {
+ SEXP old_data = data_;
+ data_ = safe[R_MakeExternalPtr]((void*)ptr, R_NilValue, R_NilValue);
+ r_deleter(old_data);
+ }
+
+ void swap(external_pointer& other) noexcept {
+ SEXP tmp = other.data_;
+ other.data_ = data_;
+ data_ = tmp;
+ }
+
+ operator bool() noexcept { return data_ != nullptr; }
+};
+
+template <class T, void Deleter(T*)>
+void swap(external_pointer<T, Deleter>& lhs, external_pointer<T, Deleter>& rhs) noexcept {
+ lhs.swap(rhs);
+}
+
+template <class T, void Deleter(T*)>
+bool operator==(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ == y.data_;
+}
+
+template <class T, void Deleter(T*)>
+bool operator!=(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ != y.data_;
+}
+
+template <class T, void Deleter(T*)>
+bool operator<(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ < y.data_;
+}
+
+template <class T, void Deleter(T*)>
+bool operator<=(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ <= y.data_;
+}
+
+template <class T, void Deleter(T*)>
+bool operator>(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ > y.data_;
+}
+
+template <class T, void Deleter(T*)>
+bool operator>=(const external_pointer<T, Deleter>& x,
+ const external_pointer<T, Deleter>& y) {
+ return x.data_ >= y.data_;
+}
+
+} // namespace cpp11