blob: 2ff5435dd8192e2504a470f15e806b2bdd4ed8a3 [file] [log] [blame]
Nicolas Capense3490ed2018-04-09 15:12:15 -04001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _STLPORT_CPP11_EXTENSION_MEMORY_
18#define _STLPORT_CPP11_EXTENSION_MEMORY_
19
20// This file extends stlport's <memory> implementation to provide support for:
21// - std::shared_ptr (C++11)
22// - std::unique_ptr (C++11)
23
24// Cloned from master branch vendor/google/native/cmds/sysproxy/shared_ptr.h
25// Upstream commit ff64c352c35c46a14f15503778781889a816eea4
26// Upstream Change-Id: I481ec53b08beecde2bf6dc38e5933342235da3d9
27
28#include <stlport/memory>
29
30namespace std {
31
32template <typename T>
33class shared_ptr {
34 public:
35 shared_ptr();
36 explicit shared_ptr(T *value);
37 shared_ptr(const shared_ptr &rhs);
38 shared_ptr &operator=(const shared_ptr &rhs);
39 template <typename U>
40 shared_ptr(const shared_ptr<U> &rhs);
41 template <typename U>
42 shared_ptr &operator=(const shared_ptr<U> &rhs);
43 ~shared_ptr();
44
45 T *get() const;
46 T *operator->() const;
47 T &operator*() const;
48
49 template <typename U>
50 bool operator==(const shared_ptr<U> &rhs) const;
51 template <typename U>
52 bool operator!=(const shared_ptr<U> &rhs) const;
53 template <typename U>
54 bool operator<(const shared_ptr<U> &rhs) const;
55 template <typename U>
56 bool operator<=(const shared_ptr<U> &rhs) const;
57 template <typename U>
58 bool operator>(const shared_ptr<U> &rhs) const;
59 template <typename U>
60 bool operator>=(const shared_ptr<U> &rhs) const;
61
62 void reset(T *value = NULL);
63
64 // TODO(haining) Work with Deleter
65
66 private:
67 template <typename U>
68 friend class shared_ptr;
69
70 struct Node {
71 T *value;
72 int *count;
73 };
74 // Thread safe decrement, deletes node_ if holding last remaining reference.
75 // Any use of node_ after calling this function is unsafe unless node_ is
76 // reassigned.
77 void DecNode();
78
79 // Thread safe increment.
80 void IncNode();
81
82 // Creates a Node referring to NULL.
83 static Node NewNullNode();
84
85 // Creates a Node referring to value.
86 static Node NewNodeFor(T *value);
87
88 Node node_;
89};
90
91template <typename T>
92typename shared_ptr<T>::Node shared_ptr<T>::NewNodeFor(T *value) {
93 Node n = {value, new int(1)};
94 return n;
95}
96
97template <typename T>
98typename shared_ptr<T>::Node shared_ptr<T>::NewNullNode() {
99 return NewNodeFor(NULL);
100}
101
102template <typename T>
103void shared_ptr<T>::reset(T *value) {
104 DecNode();
105 node_ = NewNodeFor(value);
106}
107
108template <typename T>
109shared_ptr<T>::shared_ptr() : node_(NewNullNode()) {}
110
111template <typename T>
112void shared_ptr<T>::DecNode() {
113 bool should_delete = __atomic_fetch_sub(node_.count, 1, __ATOMIC_SEQ_CST) == 0;
114 // The only accesses to node_ that should be made after this line is the
115 // deletion conditional on should_delete. Anything else is unsafe since
116 // because another thread could have deleted node_
117 if (should_delete) {
118 delete node_.value;
119 delete node_.count;
120 node_.value = NULL;
121 node_.count = NULL;
122 }
123}
124
125template <typename T>
126void shared_ptr<T>::IncNode() {
127 __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST);
128}
129
130template <typename T>
131shared_ptr<T>::shared_ptr(T *value) {
132 node_ = NewNodeFor(value);
133}
134
135template <typename T>
136shared_ptr<T>::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) {
137 IncNode();
138}
139
140template <typename T>
141template <typename U>
142shared_ptr<T>::shared_ptr(const shared_ptr<U> &rhs) {
143 node_.value = rhs.node_.value;
144 node_.count = rhs.node_.count;
145 node_.m = rhs.node_.m;
146 IncNode();
147}
148
149template <typename T>
150shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr &rhs) {
151 if (node_.value == rhs.node_.value) {
152 return *this;
153 }
154
155 DecNode();
156 node_ = rhs.node_;
157 IncNode();
158 return *this;
159}
160
161template <typename T>
162template <typename U>
163shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr<U> &rhs) {
164 if (node_.value == rhs.node_.value) {
165 return *this;
166 }
167
168 DecNode();
169 node_.value = rhs.node_.value;
170 node_.count = rhs.node_.count;
171 node_.m = rhs.node_.m;
172 IncNode();
173 return *this;
174}
175
176template <typename T>
177shared_ptr<T>::~shared_ptr() {
178 DecNode();
179}
180
181template <typename T>
182T *shared_ptr<T>::get() const {
183 return node_.value;
184}
185
186template <typename T>
187T *shared_ptr<T>::operator->() const {
188 return get();
189}
190
191template <typename T>
192T &shared_ptr<T>::operator*() const {
193 return *node_.value;
194}
195
196template <typename T>
197template <typename U>
198bool shared_ptr<T>::operator==(const shared_ptr<U> &rhs) const {
199 return node_.value == rhs.node_.value;
200}
201
202template <typename T>
203template <typename U>
204bool shared_ptr<T>::operator!=(const shared_ptr<U> &rhs) const {
205 return node_.value != rhs.node_.value;
206}
207
208template <typename T>
209template <typename U>
210bool shared_ptr<T>::operator<(const shared_ptr<U> &rhs) const {
211 return node_.value < rhs.node_.value;
212}
213
214template <typename T>
215template <typename U>
216bool shared_ptr<T>::operator<=(const shared_ptr<U> &rhs) const {
217 return node_.value <= rhs.node_.value;
218}
219
220template <typename T>
221template <typename U>
222bool shared_ptr<T>::operator>(const shared_ptr<U> &rhs) const {
223 return node_.value > rhs.node_.value;
224}
225
226template <typename T>
227template <typename U>
228bool shared_ptr<T>::operator>=(const shared_ptr<U> &rhs) const {
229 return node_.value >= rhs.node_.value;
230}
231
232#if !defined(DISALLOW_COPY_AND_ASSIGN)
233#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
234 TypeName(const TypeName&); \
235 void operator=(const TypeName&);
236#endif
237
238#include <cstddef>
239
240// Default deleter for pointer types.
241template <typename T>
242struct DefaultDelete {
243 void operator()(T* p) const { delete p; }
244};
245
246// Default deleter for array types.
247template <typename T>
248struct DefaultDelete<T[]> {
249 void operator()(T* p) const { delete[] p; }
250};
251
252// A smart pointer that deletes the given pointer on destruction.
253// Equivalent to C++11's std::unique_ptr
254// Named to be in keeping with Android style but also to avoid
255// collision with any other implementation, until we can switch over
256// to unique_ptr.
257// Use thus:
258// unique_ptr<C> c(new C);
259
260namespace workaround_internal {
261template <typename T, typename Deleter>
262class UniquePtrBase {
263 public:
264 // Construct a new UniquePtrBase, taking ownership of the given raw pointer.
265 explicit UniquePtrBase(T* ptr = 0) : mPtr(ptr), mDeleter() {}
266 explicit UniquePtrBase(T* ptr, Deleter d) : mPtr(ptr), mDeleter(d) {}
267
268 ~UniquePtrBase() { reset(); }
269
270 // Accessors.
271 T* get() const { return mPtr; }
272
273 // Returns the raw pointer and hands over ownership to the caller.
274 // The pointer will not be deleted by UniquePtrBase.
275 T* release() {
276 T* result = mPtr;
277 mPtr = 0;
278 return result;
279 }
280
281 // Takes ownership of the given raw pointer.
282 // If this smart pointer previously owned a different raw pointer, that
283 // raw pointer will be freed.
284 void reset(T* ptr = 0) {
285 T* old_ptr = mPtr;
286 mPtr = ptr;
287 if (old_ptr != NULL && mPtr != old_ptr) {
288 get_deleter()(old_ptr);
289 }
290 }
291
292 Deleter& get_deleter() { return mDeleter; }
293 const Deleter& get_deleter() const { return mDeleter; }
294
295 private:
296 // This is so users can compare against null. Callers should be able
297 // to invoke operator== and operator!= above with NULL pointers but not
298 // with any other pointer.
299 struct RawDummy {};
300
301 public:
302 bool operator==(const RawDummy*) const { return get() == NULL; }
303 friend bool operator==(const RawDummy*, const UniquePtrBase& self) {
304 return self == NULL;
305 }
306
307 bool operator!=(const RawDummy*) const { return !(*this == NULL); }
308 friend bool operator!=(const RawDummy*, const UniquePtrBase& self) {
309 return self != NULL;
310 }
311
312 private:
313 // The raw pointer.
314 T* mPtr;
315 Deleter mDeleter;
316
317 DISALLOW_COPY_AND_ASSIGN(UniquePtrBase);
318};
319} // namespace workaround_internal
320
321template <typename T, typename Deleter = DefaultDelete<T> >
322class unique_ptr : public workaround_internal::UniquePtrBase<T, Deleter> {
323 typedef workaround_internal::UniquePtrBase<T, Deleter> Base;
324 public:
325 // Construct a new unique_ptr, taking ownership of the given raw pointer.
326 explicit unique_ptr(T* ptr = 0) : Base(ptr) { }
327 explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { }
328
329 T& operator*() const { return *this->get(); }
330 T* operator->() const { return this->get(); }
331};
332
333// Partial specialization for array types. Like std::unique_ptr, this removes
334// operator* and operator-> but adds operator[].
335template <typename T, typename Deleter>
336class unique_ptr<T[], Deleter> : public workaround_internal::UniquePtrBase<T, Deleter> {
337 typedef workaround_internal::UniquePtrBase<T, Deleter> Base;
338 public:
339 explicit unique_ptr(T* ptr = 0) : Base(ptr) { }
340 explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { }
341
342 T& operator[](std::ptrdiff_t i) const { return this->get()[i]; }
343};
344
345template <typename T>
346shared_ptr<T> make_shared() {
347 return shared_ptr<T>(new T);
348}
349
350} // namespace std
351
352#endif // _STLPORT_CPP11_EXTENSION_MEMORY_