/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _STLPORT_CPP11_EXTENSION_MEMORY_ #define _STLPORT_CPP11_EXTENSION_MEMORY_ // This file extends stlport's <memory> implementation to provide support for: // - std::shared_ptr (C++11) // - std::unique_ptr (C++11) // Cloned from master branch vendor/google/native/cmds/sysproxy/shared_ptr.h // Upstream commit ff64c352c35c46a14f15503778781889a816eea4 // Upstream Change-Id: I481ec53b08beecde2bf6dc38e5933342235da3d9 #include <stlport/memory> namespace std { template <typename T> class shared_ptr { public: shared_ptr(); explicit shared_ptr(T *value); shared_ptr(const shared_ptr &rhs); shared_ptr &operator=(const shared_ptr &rhs); template <typename U> shared_ptr(const shared_ptr<U> &rhs); template <typename U> shared_ptr &operator=(const shared_ptr<U> &rhs); ~shared_ptr(); T *get() const; T *operator->() const; T &operator*() const; template <typename U> bool operator==(const shared_ptr<U> &rhs) const; template <typename U> bool operator!=(const shared_ptr<U> &rhs) const; template <typename U> bool operator<(const shared_ptr<U> &rhs) const; template <typename U> bool operator<=(const shared_ptr<U> &rhs) const; template <typename U> bool operator>(const shared_ptr<U> &rhs) const; template <typename U> bool operator>=(const shared_ptr<U> &rhs) const; void reset(T *value = NULL); // TODO(haining) Work with Deleter private: template <typename U> friend class shared_ptr; struct Node { T *value; int *count; }; // Thread safe decrement, deletes node_ if holding last remaining reference. // Any use of node_ after calling this function is unsafe unless node_ is // reassigned. void DecNode(); // Thread safe increment. void IncNode(); // Creates a Node referring to NULL. static Node NewNullNode(); // Creates a Node referring to value. static Node NewNodeFor(T *value); Node node_; }; template <typename T> typename shared_ptr<T>::Node shared_ptr<T>::NewNodeFor(T *value) { Node n = {value, new int(1)}; return n; } template <typename T> typename shared_ptr<T>::Node shared_ptr<T>::NewNullNode() { return NewNodeFor(NULL); } template <typename T> void shared_ptr<T>::reset(T *value) { DecNode(); node_ = NewNodeFor(value); } template <typename T> shared_ptr<T>::shared_ptr() : node_(NewNullNode()) {} template <typename T> void shared_ptr<T>::DecNode() { bool should_delete = __atomic_fetch_sub(node_.count, 1, __ATOMIC_SEQ_CST) == 0; // The only accesses to node_ that should be made after this line is the // deletion conditional on should_delete. Anything else is unsafe since // because another thread could have deleted node_ if (should_delete) { delete node_.value; delete node_.count; node_.value = NULL; node_.count = NULL; } } template <typename T> void shared_ptr<T>::IncNode() { __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST); } template <typename T> shared_ptr<T>::shared_ptr(T *value) { node_ = NewNodeFor(value); } template <typename T> shared_ptr<T>::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) { IncNode(); } template <typename T> template <typename U> shared_ptr<T>::shared_ptr(const shared_ptr<U> &rhs) { node_.value = rhs.node_.value; node_.count = rhs.node_.count; node_.m = rhs.node_.m; IncNode(); } template <typename T> shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr &rhs) { if (node_.value == rhs.node_.value) { return *this; } DecNode(); node_ = rhs.node_; IncNode(); return *this; } template <typename T> template <typename U> shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr<U> &rhs) { if (node_.value == rhs.node_.value) { return *this; } DecNode(); node_.value = rhs.node_.value; node_.count = rhs.node_.count; node_.m = rhs.node_.m; IncNode(); return *this; } template <typename T> shared_ptr<T>::~shared_ptr() { DecNode(); } template <typename T> T *shared_ptr<T>::get() const { return node_.value; } template <typename T> T *shared_ptr<T>::operator->() const { return get(); } template <typename T> T &shared_ptr<T>::operator*() const { return *node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator==(const shared_ptr<U> &rhs) const { return node_.value == rhs.node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator!=(const shared_ptr<U> &rhs) const { return node_.value != rhs.node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator<(const shared_ptr<U> &rhs) const { return node_.value < rhs.node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator<=(const shared_ptr<U> &rhs) const { return node_.value <= rhs.node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator>(const shared_ptr<U> &rhs) const { return node_.value > rhs.node_.value; } template <typename T> template <typename U> bool shared_ptr<T>::operator>=(const shared_ptr<U> &rhs) const { return node_.value >= rhs.node_.value; } #if !defined(DISALLOW_COPY_AND_ASSIGN) #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ void operator=(const TypeName&); #endif #include <cstddef> // Default deleter for pointer types. template <typename T> struct DefaultDelete { void operator()(T* p) const { delete p; } }; // Default deleter for array types. template <typename T> struct DefaultDelete<T[]> { void operator()(T* p) const { delete[] p; } }; // A smart pointer that deletes the given pointer on destruction. // Equivalent to C++11's std::unique_ptr // Named to be in keeping with Android style but also to avoid // collision with any other implementation, until we can switch over // to unique_ptr. // Use thus: // unique_ptr<C> c(new C); namespace workaround_internal { template <typename T, typename Deleter> class UniquePtrBase { public: // Construct a new UniquePtrBase, taking ownership of the given raw pointer. explicit UniquePtrBase(T* ptr = 0) : mPtr(ptr), mDeleter() {} explicit UniquePtrBase(T* ptr, Deleter d) : mPtr(ptr), mDeleter(d) {} ~UniquePtrBase() { reset(); } // Accessors. T* get() const { return mPtr; } // Returns the raw pointer and hands over ownership to the caller. // The pointer will not be deleted by UniquePtrBase. T* release() { T* result = mPtr; mPtr = 0; return result; } // Takes ownership of the given raw pointer. // If this smart pointer previously owned a different raw pointer, that // raw pointer will be freed. void reset(T* ptr = 0) { T* old_ptr = mPtr; mPtr = ptr; if (old_ptr != NULL && mPtr != old_ptr) { get_deleter()(old_ptr); } } Deleter& get_deleter() { return mDeleter; } const Deleter& get_deleter() const { return mDeleter; } private: // This is so users can compare against null. Callers should be able // to invoke operator== and operator!= above with NULL pointers but not // with any other pointer. struct RawDummy {}; public: bool operator==(const RawDummy*) const { return get() == NULL; } friend bool operator==(const RawDummy*, const UniquePtrBase& self) { return self == NULL; } bool operator!=(const RawDummy*) const { return !(*this == NULL); } friend bool operator!=(const RawDummy*, const UniquePtrBase& self) { return self != NULL; } private: // The raw pointer. T* mPtr; Deleter mDeleter; DISALLOW_COPY_AND_ASSIGN(UniquePtrBase); }; } // namespace workaround_internal template <typename T, typename Deleter = DefaultDelete<T> > class unique_ptr : public workaround_internal::UniquePtrBase<T, Deleter> { typedef workaround_internal::UniquePtrBase<T, Deleter> Base; public: // Construct a new unique_ptr, taking ownership of the given raw pointer. explicit unique_ptr(T* ptr = 0) : Base(ptr) { } explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } T& operator*() const { return *this->get(); } T* operator->() const { return this->get(); } }; // Partial specialization for array types. Like std::unique_ptr, this removes // operator* and operator-> but adds operator[]. template <typename T, typename Deleter> class unique_ptr<T[], Deleter> : public workaround_internal::UniquePtrBase<T, Deleter> { typedef workaround_internal::UniquePtrBase<T, Deleter> Base; public: explicit unique_ptr(T* ptr = 0) : Base(ptr) { } explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } T& operator[](std::ptrdiff_t i) const { return this->get()[i]; } }; template <typename T> shared_ptr<T> make_shared() { return shared_ptr<T>(new T); } } // namespace std #endif // _STLPORT_CPP11_EXTENSION_MEMORY_