Home | History | Annotate | Download | only in common
      1 // Copyright (C) 2014 The Android Open Source Project
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 // http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 #ifndef EMUGL_SMART_PTR_H
     15 #define EMUGL_SMART_PTR_H
     16 
     17 #include <stddef.h>
     18 
     19 namespace emugl {
     20 
     21 // Hidden atomic ref-counting implementation.
     22 class RefCount;
     23 
     24 // Base class for all templated SmartPtr<> instances. Reduces
     25 // template expansion and code. Consider this to be an implementation
     26 // detail of SmartPtr<>, so don't rely on anything here.
     27 class SmartPtrBase {
     28 public:
     29     // Defrault constructor.
     30     SmartPtrBase() : mPtr(NULL), mRefCount(NULL) {}
     31 
     32     // Normal constructor. This takes ownership of |ptr|, though only
     33     // template instances are capable of destroying the object.
     34     explicit SmartPtrBase(void* ptr);
     35 
     36     // Copy-constructor, this increments the reference count.
     37     SmartPtrBase(const SmartPtrBase& other);
     38 
     39     // Assignment operator, also increments the reference count.
     40     SmartPtrBase& operator=(const SmartPtrBase& other);
     41 
     42     // Nothing happens in this destructor, the real work must be performed
     43     // in subclasses.
     44     ~SmartPtrBase() {}
     45 
     46 
     47     // Used to enable 'if (smart_ptr) { ... }' properly.
     48     operator void*() const {
     49         return mPtr;
     50     }
     51 
     52     // Return internal reference count value, only use for unit testing.
     53     int getRefCount() const;
     54 
     55 protected:
     56     // Used internally to increment the reference count.
     57     void addRef();
     58 
     59     // Copy the |other| into this instance, returns the old pointer value
     60     // if it needs to be destroyed by the caller, or NULL otherwise.
     61     void* copyFrom(const SmartPtrBase& other);
     62 
     63     // Used internally to decrement the reference count, if it reaches 0,
     64     // returns the pointer to be destroyed, NULL otherwise.
     65     void* release();
     66 
     67     void* mPtr;
     68     RefCount* mRefCount;
     69 };
     70 
     71 
     72 // The real template class to be used for smart pointers.
     73 // Typical uses:
     74 //
     75 //     SmartPtr<Foo>  ptr(new Foo());   // takes ownership.
     76 //     SmartPtr<Foo>  ptr2;             // empty pointer.
     77 //     ptr2 = ptr;                      // copies pointer + increment reference count.
     78 //     Foo* obj = ptr.Ptr();            // access pointed object.
     79 //     ptr->DoStuff();                  // operate directly on pointed object.
     80 //     (*ptr)->DoStuff();               // same here.
     81 //
     82 // On scope exit, the internal reference count is decremented and the
     83 // object is deleted automatically when it reaches 0, indicating that
     84 // there are no more owners.
     85 //
     86 // IMPORTANT: You need to be sure that only one 'chain' of smart pointers
     87 // own a given object. I.e. the following is incorrect:
     88 //
     89 //     Foo* foo = new Foo();      // create new instance.
     90 //     SmartPtr<Foo>  ptr(foo);   // |ptr| takes ownership of |foo|.
     91 //     SmartPtr<Foo>  ptr2(foo);  // |ptr2| takes also ownership of |foo|.
     92 //
     93 // The problem is that |ptr| and |ptr2| don't know anything about each
     94 // other, and will not share the same reference count. Once a smart pointer
     95 // owns an object, only use other smart pointers that are copy-constructed
     96 // or assigned with the initial one to keep everything consistent.
     97 template <class T>
     98 class SmartPtr : public emugl::SmartPtrBase {
     99 public:
    100     // Default constructor. The instance holds a NULL pointer.
    101     SmartPtr() : SmartPtrBase() {}
    102 
    103     // Regular constructor, takes ownership of |ptr|.
    104     explicit SmartPtr(T* ptr) : SmartPtrBase(ptr) {}
    105 
    106     // Copy-constructor, |this| and |other| will share the same internal
    107     // reference count, which is incremented by 1.
    108     SmartPtr(const SmartPtr& other)
    109             : SmartPtrBase(reinterpret_cast<const SmartPtrBase&>(other)) {}
    110 
    111     // Assignment operator, same semantics as copy-constructor.
    112     SmartPtr& operator=(const SmartPtr& other) {
    113       void* old_ptr = copyFrom(static_cast<const SmartPtrBase&>(other));
    114       if (old_ptr)
    115         delete reinterpret_cast<T*>(old_ptr);
    116       return *this;
    117     }
    118 
    119     // Destructor, decrements reference count and destroys the object
    120     // if it reaches 0 (indicating this was the last owning smart pointer).
    121     ~SmartPtr() {
    122         void* ptr = release();
    123         if (ptr)
    124           delete reinterpret_cast<T*>(ptr);
    125     }
    126 
    127     // Return owned object instance, or NULL.
    128     T* Ptr() const {
    129         return reinterpret_cast<T*>(mPtr);
    130     }
    131 
    132     // Return owned object instance, or NULL
    133     const T* constPtr() const {
    134         return reinterpret_cast<const T*>(mPtr);
    135     }
    136 
    137     // Operate directly on owned object.
    138     T* operator->() const {
    139         return Ptr();
    140     }
    141 
    142     // Return reference to owned object.
    143     T& operator*() const {
    144         return *Ptr();
    145     }
    146 };
    147 
    148 }  // namespace emugl
    149 
    150 #endif // EMUGL_SMART_PTR_H
    151