| // Copyright (C) 2014 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 EMUGL_SMART_PTR_H |
| #define EMUGL_SMART_PTR_H |
| |
| #include <stddef.h> |
| |
| namespace emugl { |
| |
| // Hidden atomic ref-counting implementation. |
| class RefCount; |
| |
| // Base class for all templated SmartPtr<> instances. Reduces |
| // template expansion and code. Consider this to be an implementation |
| // detail of SmartPtr<>, so don't rely on anything here. |
| class SmartPtrBase { |
| public: |
| // Defrault constructor. |
| SmartPtrBase() : mPtr(NULL), mRefCount(NULL) {} |
| |
| // Normal constructor. This takes ownership of |ptr|, though only |
| // template instances are capable of destroying the object. |
| explicit SmartPtrBase(void* ptr); |
| |
| // Copy-constructor, this increments the reference count. |
| SmartPtrBase(const SmartPtrBase& other); |
| |
| // Assignment operator, also increments the reference count. |
| SmartPtrBase& operator=(const SmartPtrBase& other); |
| |
| // Nothing happens in this destructor, the real work must be performed |
| // in subclasses. |
| ~SmartPtrBase() {} |
| |
| |
| // Used to enable 'if (smart_ptr) { ... }' properly. |
| operator void*() const { |
| return mPtr; |
| } |
| |
| // Return internal reference count value, only use for unit testing. |
| int getRefCount() const; |
| |
| protected: |
| // Used internally to increment the reference count. |
| void addRef(); |
| |
| // Copy the |other| into this instance, returns the old pointer value |
| // if it needs to be destroyed by the caller, or NULL otherwise. |
| void* copyFrom(const SmartPtrBase& other); |
| |
| // Used internally to decrement the reference count, if it reaches 0, |
| // returns the pointer to be destroyed, NULL otherwise. |
| void* release(); |
| |
| void* mPtr; |
| RefCount* mRefCount; |
| }; |
| |
| |
| // The real template class to be used for smart pointers. |
| // Typical uses: |
| // |
| // SmartPtr<Foo> ptr(new Foo()); // takes ownership. |
| // SmartPtr<Foo> ptr2; // empty pointer. |
| // ptr2 = ptr; // copies pointer + increment reference count. |
| // Foo* obj = ptr.Ptr(); // access pointed object. |
| // ptr->DoStuff(); // operate directly on pointed object. |
| // (*ptr)->DoStuff(); // same here. |
| // |
| // On scope exit, the internal reference count is decremented and the |
| // object is deleted automatically when it reaches 0, indicating that |
| // there are no more owners. |
| // |
| // IMPORTANT: You need to be sure that only one 'chain' of smart pointers |
| // own a given object. I.e. the following is incorrect: |
| // |
| // Foo* foo = new Foo(); // create new instance. |
| // SmartPtr<Foo> ptr(foo); // |ptr| takes ownership of |foo|. |
| // SmartPtr<Foo> ptr2(foo); // |ptr2| takes also ownership of |foo|. |
| // |
| // The problem is that |ptr| and |ptr2| don't know anything about each |
| // other, and will not share the same reference count. Once a smart pointer |
| // owns an object, only use other smart pointers that are copy-constructed |
| // or assigned with the initial one to keep everything consistent. |
| template <class T> |
| class SmartPtr : public emugl::SmartPtrBase { |
| public: |
| // Default constructor. The instance holds a NULL pointer. |
| SmartPtr() : SmartPtrBase() {} |
| |
| // Regular constructor, takes ownership of |ptr|. |
| explicit SmartPtr(T* ptr) : SmartPtrBase(ptr) {} |
| |
| // Copy-constructor, |this| and |other| will share the same internal |
| // reference count, which is incremented by 1. |
| SmartPtr(const SmartPtr& other) |
| : SmartPtrBase(reinterpret_cast<const SmartPtrBase&>(other)) {} |
| |
| // Assignment operator, same semantics as copy-constructor. |
| SmartPtr& operator=(const SmartPtr& other) { |
| void* old_ptr = copyFrom(static_cast<const SmartPtrBase&>(other)); |
| if (old_ptr) |
| delete reinterpret_cast<T*>(old_ptr); |
| return *this; |
| } |
| |
| // Destructor, decrements reference count and destroys the object |
| // if it reaches 0 (indicating this was the last owning smart pointer). |
| ~SmartPtr() { |
| void* ptr = release(); |
| if (ptr) |
| delete reinterpret_cast<T*>(ptr); |
| } |
| |
| // Return owned object instance, or NULL. |
| T* Ptr() const { |
| return reinterpret_cast<T*>(mPtr); |
| } |
| |
| // Return owned object instance, or NULL |
| const T* constPtr() const { |
| return reinterpret_cast<const T*>(mPtr); |
| } |
| |
| // Operate directly on owned object. |
| T* operator->() const { |
| return Ptr(); |
| } |
| |
| // Return reference to owned object. |
| T& operator*() const { |
| return *Ptr(); |
| } |
| }; |
| |
| } // namespace emugl |
| |
| #endif // EMUGL_SMART_PTR_H |