// 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 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 ptr(new Foo()); // takes ownership. // SmartPtr 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 ptr(foo); // |ptr| takes ownership of |foo|. // SmartPtr 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 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(other)) {} // Assignment operator, same semantics as copy-constructor. SmartPtr& operator=(const SmartPtr& other) { void* old_ptr = copyFrom(static_cast(other)); if (old_ptr) delete reinterpret_cast(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(ptr); } // Return owned object instance, or NULL. T* Ptr() const { return reinterpret_cast(mPtr); } // Return owned object instance, or NULL const T* constPtr() const { return reinterpret_cast(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