Home | History | Annotate | Download | only in stlport-cpp11-extension
      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 
     30 namespace std {
     31 
     32 template <typename T>
     33 class 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 
     91 template <typename T>
     92 typename shared_ptr<T>::Node shared_ptr<T>::NewNodeFor(T *value) {
     93   Node n = {value, new int(1)};
     94   return n;
     95 }
     96 
     97 template <typename T>
     98 typename shared_ptr<T>::Node shared_ptr<T>::NewNullNode() {
     99   return NewNodeFor(NULL);
    100 }
    101 
    102 template <typename T>
    103 void shared_ptr<T>::reset(T *value) {
    104   DecNode();
    105   node_ = NewNodeFor(value);
    106 }
    107 
    108 template <typename T>
    109 shared_ptr<T>::shared_ptr() : node_(NewNullNode()) {}
    110 
    111 template <typename T>
    112 void 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 
    125 template <typename T>
    126 void shared_ptr<T>::IncNode() {
    127   __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST);
    128 }
    129 
    130 template <typename T>
    131 shared_ptr<T>::shared_ptr(T *value) {
    132   node_ = NewNodeFor(value);
    133 }
    134 
    135 template <typename T>
    136 shared_ptr<T>::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) {
    137   IncNode();
    138 }
    139 
    140 template <typename T>
    141 template <typename U>
    142 shared_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 
    149 template <typename T>
    150 shared_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 
    161 template <typename T>
    162 template <typename U>
    163 shared_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 
    176 template <typename T>
    177 shared_ptr<T>::~shared_ptr() {
    178   DecNode();
    179 }
    180 
    181 template <typename T>
    182 T *shared_ptr<T>::get() const {
    183   return node_.value;
    184 }
    185 
    186 template <typename T>
    187 T *shared_ptr<T>::operator->() const {
    188   return get();
    189 }
    190 
    191 template <typename T>
    192 T &shared_ptr<T>::operator*() const {
    193   return *node_.value;
    194 }
    195 
    196 template <typename T>
    197 template <typename U>
    198 bool shared_ptr<T>::operator==(const shared_ptr<U> &rhs) const {
    199   return node_.value == rhs.node_.value;
    200 }
    201 
    202 template <typename T>
    203 template <typename U>
    204 bool shared_ptr<T>::operator!=(const shared_ptr<U> &rhs) const {
    205   return node_.value != rhs.node_.value;
    206 }
    207 
    208 template <typename T>
    209 template <typename U>
    210 bool shared_ptr<T>::operator<(const shared_ptr<U> &rhs) const {
    211   return node_.value < rhs.node_.value;
    212 }
    213 
    214 template <typename T>
    215 template <typename U>
    216 bool shared_ptr<T>::operator<=(const shared_ptr<U> &rhs) const {
    217   return node_.value <= rhs.node_.value;
    218 }
    219 
    220 template <typename T>
    221 template <typename U>
    222 bool shared_ptr<T>::operator>(const shared_ptr<U> &rhs) const {
    223   return node_.value > rhs.node_.value;
    224 }
    225 
    226 template <typename T>
    227 template <typename U>
    228 bool 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.
    241 template <typename T>
    242 struct DefaultDelete {
    243   void operator()(T* p) const { delete p; }
    244 };
    245 
    246 // Default deleter for array types.
    247 template <typename T>
    248 struct 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 
    260 namespace workaround_internal {
    261 template <typename T, typename Deleter>
    262 class 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 
    321 template <typename T, typename Deleter = DefaultDelete<T> >
    322 class 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[].
    335 template <typename T, typename Deleter>
    336 class 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 
    345 template <typename T>
    346 shared_ptr<T> make_shared() {
    347   return shared_ptr<T>(new T);
    348 }
    349 
    350 }  // namespace std
    351 
    352 #endif  // _STLPORT_CPP11_EXTENSION_MEMORY_
    353