]> git.proxmox.com Git - ceph.git/blob - ceph/src/arrow/r/inst/include/cpp11/external_pointer.hpp
import quincy 17.2.0
[ceph.git] / ceph / src / arrow / r / inst / include / cpp11 / external_pointer.hpp
1 // cpp11 version: 0.3.1.1
2 // vendored on: 2021-08-11
3 #pragma once
4
5 #include <cstddef> // for nullptr_t, NULL
6 #include <memory> // for bad_weak_ptr
7 #include <type_traits> // for add_lvalue_reference
8
9 #include "cpp11/R.hpp" // for SEXP, SEXPREC, TYPEOF, R_NilValue, R_C...
10 #include "cpp11/protect.hpp" // for protect, safe, protect::function
11 #include "cpp11/r_bool.hpp" // for r_bool
12 #include "cpp11/r_vector.hpp" // for type_error
13 #include "cpp11/sexp.hpp" // for sexp
14
15 namespace cpp11 {
16
17 template <typename T>
18 void default_deleter(T* obj) {
19 delete obj;
20 }
21
22 template <typename T, void Deleter(T*) = default_deleter<T>>
23 class external_pointer {
24 private:
25 sexp data_ = R_NilValue;
26
27 static SEXP valid_type(SEXP data) {
28 if (TYPEOF(data) != EXTPTRSXP) {
29 throw type_error(EXTPTRSXP, TYPEOF(data));
30 }
31
32 return data;
33 }
34
35 static void r_deleter(SEXP p) {
36 if (TYPEOF(p) != EXTPTRSXP) return;
37
38 T* ptr = static_cast<T*>(R_ExternalPtrAddr(p));
39
40 if (ptr == NULL) {
41 return;
42 }
43
44 R_ClearExternalPtr(p);
45
46 Deleter(ptr);
47 }
48
49 public:
50 using pointer = T*;
51
52 external_pointer() noexcept {}
53 external_pointer(std::nullptr_t) noexcept {}
54
55 external_pointer(SEXP data) : data_(valid_type(data)) {}
56
57 external_pointer(pointer p, bool use_deleter = true, bool finalize_on_exit = true)
58 : data_(safe[R_MakeExternalPtr]((void*)p, R_NilValue, R_NilValue)) {
59 if (use_deleter) {
60 R_RegisterCFinalizerEx(data_, r_deleter, static_cast<r_bool>(finalize_on_exit));
61 }
62 }
63
64 external_pointer(const external_pointer& rhs) {
65 data_ = safe[Rf_shallow_duplicate](rhs.data_);
66 }
67
68 external_pointer(external_pointer&& rhs) { reset(rhs.release()); }
69
70 external_pointer& operator=(external_pointer&& rhs) noexcept { reset(rhs.release()); }
71
72 external_pointer& operator=(std::nullptr_t) noexcept { reset(); };
73
74 operator SEXP() const noexcept { return data_; }
75
76 pointer get() const noexcept {
77 pointer addr = static_cast<T*>(R_ExternalPtrAddr(data_));
78 if (addr == nullptr) {
79 return nullptr;
80 }
81 return addr;
82 }
83
84 typename std::add_lvalue_reference<T>::type operator*() {
85 pointer addr = get();
86 if (addr == nullptr) {
87 throw std::bad_weak_ptr();
88 }
89 return *get();
90 }
91
92 pointer operator->() const {
93 pointer addr = get();
94 if (addr == nullptr) {
95 throw std::bad_weak_ptr();
96 }
97 return get();
98 }
99
100 pointer release() noexcept {
101 if (get() == nullptr) {
102 return nullptr;
103 }
104 pointer ptr = get();
105 R_ClearExternalPtr(data_);
106
107 return ptr;
108 }
109
110 void reset(pointer ptr = pointer()) {
111 SEXP old_data = data_;
112 data_ = safe[R_MakeExternalPtr]((void*)ptr, R_NilValue, R_NilValue);
113 r_deleter(old_data);
114 }
115
116 void swap(external_pointer& other) noexcept {
117 SEXP tmp = other.data_;
118 other.data_ = data_;
119 data_ = tmp;
120 }
121
122 operator bool() noexcept { return data_ != nullptr; }
123 };
124
125 template <class T, void Deleter(T*)>
126 void swap(external_pointer<T, Deleter>& lhs, external_pointer<T, Deleter>& rhs) noexcept {
127 lhs.swap(rhs);
128 }
129
130 template <class T, void Deleter(T*)>
131 bool operator==(const external_pointer<T, Deleter>& x,
132 const external_pointer<T, Deleter>& y) {
133 return x.data_ == y.data_;
134 }
135
136 template <class T, void Deleter(T*)>
137 bool operator!=(const external_pointer<T, Deleter>& x,
138 const external_pointer<T, Deleter>& y) {
139 return x.data_ != y.data_;
140 }
141
142 template <class T, void Deleter(T*)>
143 bool operator<(const external_pointer<T, Deleter>& x,
144 const external_pointer<T, Deleter>& y) {
145 return x.data_ < y.data_;
146 }
147
148 template <class T, void Deleter(T*)>
149 bool operator<=(const external_pointer<T, Deleter>& x,
150 const external_pointer<T, Deleter>& y) {
151 return x.data_ <= y.data_;
152 }
153
154 template <class T, void Deleter(T*)>
155 bool operator>(const external_pointer<T, Deleter>& x,
156 const external_pointer<T, Deleter>& y) {
157 return x.data_ > y.data_;
158 }
159
160 template <class T, void Deleter(T*)>
161 bool operator>=(const external_pointer<T, Deleter>& x,
162 const external_pointer<T, Deleter>& y) {
163 return x.data_ >= y.data_;
164 }
165
166 } // namespace cpp11