blob: 2ff5435dd8192e2504a470f15e806b2bdd4ed8a3 [file] [log] [blame]
/*
* 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_