• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
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_
353