michael@0: // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. michael@0: // Copyright (c) 2001, 2002 Peter Dimov michael@0: // michael@0: // Permission to copy, use, modify, sell and distribute this software michael@0: // is granted provided this copyright notice appears in all copies. michael@0: // This software is provided "as is" without express or implied michael@0: // warranty, and with no claim as to its suitability for any purpose. michael@0: // michael@0: // See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation. michael@0: // michael@0: michael@0: // scoped_ptr mimics a built-in pointer except that it guarantees deletion michael@0: // of the object pointed to, either on destruction of the scoped_ptr or via michael@0: // an explicit reset(). scoped_ptr is a simple solution for simple needs; michael@0: // use shared_ptr or std::auto_ptr if your needs are more complex. michael@0: michael@0: // *** NOTE *** michael@0: // If your scoped_ptr is a class member of class FOO pointing to a michael@0: // forward declared type BAR (as shown below), then you MUST use a non-inlined michael@0: // version of the destructor. The destructor of a scoped_ptr (called from michael@0: // FOO's destructor) must have a complete definition of BAR in order to michael@0: // destroy it. Example: michael@0: // michael@0: // -- foo.h -- michael@0: // class BAR; michael@0: // michael@0: // class FOO { michael@0: // public: michael@0: // FOO(); michael@0: // ~FOO(); // Required for sources that instantiate class FOO to compile! michael@0: // michael@0: // private: michael@0: // scoped_ptr bar_; michael@0: // }; michael@0: // michael@0: // -- foo.cc -- michael@0: // #include "foo.h" michael@0: // FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition. michael@0: michael@0: // scoped_ptr_malloc added by Google michael@0: // When one of these goes out of scope, instead of doing a delete or michael@0: // delete[], it calls free(). scoped_ptr_malloc is likely to see michael@0: // much more use than any other specializations. michael@0: michael@0: // release() added by Google michael@0: // Use this to conditionally transfer ownership of a heap-allocated object michael@0: // to the caller, usually on method success. michael@0: michael@0: #ifndef COMMON_SCOPED_PTR_H_ michael@0: #define COMMON_SCOPED_PTR_H_ michael@0: michael@0: #include // for std::ptrdiff_t michael@0: #include // for assert michael@0: #include // for free() decl michael@0: michael@0: namespace google_breakpad { michael@0: michael@0: template michael@0: class scoped_ptr { michael@0: private: michael@0: michael@0: T* ptr; michael@0: michael@0: scoped_ptr(scoped_ptr const &); michael@0: scoped_ptr & operator=(scoped_ptr const &); michael@0: michael@0: public: michael@0: michael@0: typedef T element_type; michael@0: michael@0: explicit scoped_ptr(T* p = 0): ptr(p) {} michael@0: michael@0: ~scoped_ptr() { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: delete ptr; michael@0: } michael@0: michael@0: void reset(T* p = 0) { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: michael@0: if (ptr != p) { michael@0: delete ptr; michael@0: ptr = p; michael@0: } michael@0: } michael@0: michael@0: T& operator*() const { michael@0: assert(ptr != 0); michael@0: return *ptr; michael@0: } michael@0: michael@0: T* operator->() const { michael@0: assert(ptr != 0); michael@0: return ptr; michael@0: } michael@0: michael@0: bool operator==(T* p) const { michael@0: return ptr == p; michael@0: } michael@0: michael@0: bool operator!=(T* p) const { michael@0: return ptr != p; michael@0: } michael@0: michael@0: T* get() const { michael@0: return ptr; michael@0: } michael@0: michael@0: void swap(scoped_ptr & b) { michael@0: T* tmp = b.ptr; michael@0: b.ptr = ptr; michael@0: ptr = tmp; michael@0: } michael@0: michael@0: T* release() { michael@0: T* tmp = ptr; michael@0: ptr = 0; michael@0: return tmp; michael@0: } michael@0: michael@0: private: michael@0: michael@0: // no reason to use these: each scoped_ptr should have its own object michael@0: template bool operator==(scoped_ptr const& p) const; michael@0: template bool operator!=(scoped_ptr const& p) const; michael@0: }; michael@0: michael@0: template inline michael@0: void swap(scoped_ptr& a, scoped_ptr& b) { michael@0: a.swap(b); michael@0: } michael@0: michael@0: template inline michael@0: bool operator==(T* p, const scoped_ptr& b) { michael@0: return p == b.get(); michael@0: } michael@0: michael@0: template inline michael@0: bool operator!=(T* p, const scoped_ptr& b) { michael@0: return p != b.get(); michael@0: } michael@0: michael@0: // scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to michael@0: // is guaranteed, either on destruction of the scoped_array or via an explicit michael@0: // reset(). Use shared_array or std::vector if your needs are more complex. michael@0: michael@0: template michael@0: class scoped_array { michael@0: private: michael@0: michael@0: T* ptr; michael@0: michael@0: scoped_array(scoped_array const &); michael@0: scoped_array & operator=(scoped_array const &); michael@0: michael@0: public: michael@0: michael@0: typedef T element_type; michael@0: michael@0: explicit scoped_array(T* p = 0) : ptr(p) {} michael@0: michael@0: ~scoped_array() { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: delete[] ptr; michael@0: } michael@0: michael@0: void reset(T* p = 0) { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: michael@0: if (ptr != p) { michael@0: delete [] ptr; michael@0: ptr = p; michael@0: } michael@0: } michael@0: michael@0: T& operator[](std::ptrdiff_t i) const { michael@0: assert(ptr != 0); michael@0: assert(i >= 0); michael@0: return ptr[i]; michael@0: } michael@0: michael@0: bool operator==(T* p) const { michael@0: return ptr == p; michael@0: } michael@0: michael@0: bool operator!=(T* p) const { michael@0: return ptr != p; michael@0: } michael@0: michael@0: T* get() const { michael@0: return ptr; michael@0: } michael@0: michael@0: void swap(scoped_array & b) { michael@0: T* tmp = b.ptr; michael@0: b.ptr = ptr; michael@0: ptr = tmp; michael@0: } michael@0: michael@0: T* release() { michael@0: T* tmp = ptr; michael@0: ptr = 0; michael@0: return tmp; michael@0: } michael@0: michael@0: private: michael@0: michael@0: // no reason to use these: each scoped_array should have its own object michael@0: template bool operator==(scoped_array const& p) const; michael@0: template bool operator!=(scoped_array const& p) const; michael@0: }; michael@0: michael@0: template inline michael@0: void swap(scoped_array& a, scoped_array& b) { michael@0: a.swap(b); michael@0: } michael@0: michael@0: template inline michael@0: bool operator==(T* p, const scoped_array& b) { michael@0: return p == b.get(); michael@0: } michael@0: michael@0: template inline michael@0: bool operator!=(T* p, const scoped_array& b) { michael@0: return p != b.get(); michael@0: } michael@0: michael@0: michael@0: // This class wraps the c library function free() in a class that can be michael@0: // passed as a template argument to scoped_ptr_malloc below. michael@0: class ScopedPtrMallocFree { michael@0: public: michael@0: inline void operator()(void* x) const { michael@0: free(x); michael@0: } michael@0: }; michael@0: michael@0: // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a michael@0: // second template argument, the functor used to free the object. michael@0: michael@0: template michael@0: class scoped_ptr_malloc { michael@0: private: michael@0: michael@0: T* ptr; michael@0: michael@0: scoped_ptr_malloc(scoped_ptr_malloc const &); michael@0: scoped_ptr_malloc & operator=(scoped_ptr_malloc const &); michael@0: michael@0: public: michael@0: michael@0: typedef T element_type; michael@0: michael@0: explicit scoped_ptr_malloc(T* p = 0): ptr(p) {} michael@0: michael@0: ~scoped_ptr_malloc() { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: free_((void*) ptr); michael@0: } michael@0: michael@0: void reset(T* p = 0) { michael@0: typedef char type_must_be_complete[sizeof(T)]; michael@0: michael@0: if (ptr != p) { michael@0: free_((void*) ptr); michael@0: ptr = p; michael@0: } michael@0: } michael@0: michael@0: T& operator*() const { michael@0: assert(ptr != 0); michael@0: return *ptr; michael@0: } michael@0: michael@0: T* operator->() const { michael@0: assert(ptr != 0); michael@0: return ptr; michael@0: } michael@0: michael@0: bool operator==(T* p) const { michael@0: return ptr == p; michael@0: } michael@0: michael@0: bool operator!=(T* p) const { michael@0: return ptr != p; michael@0: } michael@0: michael@0: T* get() const { michael@0: return ptr; michael@0: } michael@0: michael@0: void swap(scoped_ptr_malloc & b) { michael@0: T* tmp = b.ptr; michael@0: b.ptr = ptr; michael@0: ptr = tmp; michael@0: } michael@0: michael@0: T* release() { michael@0: T* tmp = ptr; michael@0: ptr = 0; michael@0: return tmp; michael@0: } michael@0: michael@0: private: michael@0: michael@0: // no reason to use these: each scoped_ptr_malloc should have its own object michael@0: template michael@0: bool operator==(scoped_ptr_malloc const& p) const; michael@0: template michael@0: bool operator!=(scoped_ptr_malloc const& p) const; michael@0: michael@0: static FreeProc const free_; michael@0: }; michael@0: michael@0: template michael@0: FP const scoped_ptr_malloc::free_ = FP(); michael@0: michael@0: template inline michael@0: void swap(scoped_ptr_malloc& a, scoped_ptr_malloc& b) { michael@0: a.swap(b); michael@0: } michael@0: michael@0: template inline michael@0: bool operator==(T* p, const scoped_ptr_malloc& b) { michael@0: return p == b.get(); michael@0: } michael@0: michael@0: template inline michael@0: bool operator!=(T* p, const scoped_ptr_malloc& b) { michael@0: return p != b.get(); michael@0: } michael@0: michael@0: } // namespace google_breakpad michael@0: michael@0: #endif // COMMON_SCOPED_PTR_H_