From 2bd280d84e5d660aaf16465fac51c569d15f593a Mon Sep 17 00:00:00 2001 From: "mjudge%netscape.com" Date: Wed, 18 Nov 1998 22:09:52 +0000 Subject: [PATCH] smart pointer updates --- xpcom/public/COM_auto_ptr.h | 144 ++++++++++++++++++++++-------- xpcom/tests/test_COM_auto_ptr.cpp | 36 ++------ 2 files changed, 116 insertions(+), 64 deletions(-) diff --git a/xpcom/public/COM_auto_ptr.h b/xpcom/public/COM_auto_ptr.h index 03846adbef53..3a89c11e7227 100644 --- a/xpcom/public/COM_auto_ptr.h +++ b/xpcom/public/COM_auto_ptr.h @@ -190,6 +190,10 @@ #define REINTERPRET_CAST(T,x) ((T)(x)) #endif +#ifdef NO_BOOL + typedef unsigned char bool; +#endif + #ifdef NO_MEMBER_USING_DECLARATIONS #include "prtypes.h" #endif @@ -289,7 +293,8 @@ class COM_auto_ptr explicit COM_auto_ptr( T* ptr = 0 ) - : ptr_(ptr) + : ptr_(ptr), + awaiting_AddRef_(false) { if ( ptr_ ) ptr_->AddRef(); @@ -297,13 +302,15 @@ class COM_auto_ptr explicit COM_auto_ptr( const dont_AddRef_t& P ) - : ptr_(P.ptr_) + : ptr_(P.ptr_), + awaiting_AddRef_(false) { // nothing else to do here } COM_auto_ptr( const COM_auto_ptr& P ) - : ptr_(P.ptr_) + : ptr_(P.ptr_), + awaiting_AddRef_(false) { if ( ptr_ ) ptr_->AddRef(); @@ -311,7 +318,7 @@ class COM_auto_ptr ~COM_auto_ptr() { - if ( ptr_ ) + if ( ptr_ && !awaiting_AddRef_ ) ptr_->Release(); } @@ -325,8 +332,9 @@ class COM_auto_ptr COM_auto_ptr& operator=( const dont_AddRef_t& rhs ) { - if ( ptr_ ) + if ( ptr_ && !awaiting_AddRef_ ) ptr_->Release(); + awaiting_AddRef_ = false; ptr_ = rhs.ptr_; return *this; } @@ -342,6 +350,7 @@ class COM_auto_ptr operator->() const // returns a |derived_safe*| to deny clients the use of |AddRef| and |Release| { + assert( ptr_ != 0 ); // you're not allowed to dereference a NULL pointer return get(); } @@ -369,21 +378,75 @@ class COM_auto_ptr void reset( T* ptr = 0 ) { - if ( ptr != ptr_ ) + if ( ptr ) + ptr->AddRef(); + if ( ptr_ && !awaiting_AddRef_ ) + ptr_->Release(); + awaiting_AddRef_ = false; + ptr_ = ptr; + } + + +// private: +// template friend class func_AddRefs_t; +// template friend class func_doesnt_AddRef_t; + + T** + start_assignment( bool awaiting_AddRef ) + { + if ( ptr_ && !awaiting_AddRef_ ) + ptr_->Release(); + awaiting_AddRef_ = awaiting_AddRef; + ptr_ = 0; + return &ptr_; + } + + void + finish_assignment() + { + if ( awaiting_AddRef_ ) { - if ( ptr ) - ptr->AddRef(); if ( ptr_ ) - ptr_->Release(); - ptr_ = ptr; + ptr_->AddRef(); + awaiting_AddRef_ = false; } } private: T* ptr_; + bool awaiting_AddRef_; }; +template +bool +operator==( const COM_auto_ptr& lhs, const T*const rhs ) + { + return lhs.get() == rhs; + } + +template +bool +operator!=( const COM_auto_ptr& lhs, const T*const rhs ) + { + return lhs.get() != rhs; + } + +template +bool +operator==( const T*const lhs, const COM_auto_ptr& rhs ) + { + return lhs == rhs.get(); + } + +template +bool +operator!=( const T*const lhs, const COM_auto_ptr& rhs ) + { + return lhs != rhs.get(); + } + + template @@ -410,36 +473,33 @@ class func_AddRefs_t public: explicit func_AddRefs_t( COM_auto_ptr& P ) - : ptr_(0), - new_owner_(P) + : owner_(&P) { // nothing else to do } - ~func_AddRefs_t() +#if 1 + operator void**() { - new_owner_ = dont_AddRef(ptr_); + return REINTERPRET_CAST(void**, owner_->start_assignment(false)); } +#endif T*& operator*() { - return ptr_; + assert(owner_); + return *(owner_->start_assignment(false)); } operator T**() { - return &ptr_; + assert(owner_); + return owner_->start_assignment(false); } - operator void**() - { - return REINTERPRET_CAST(void **,&ptr_); - } - - private: - T* ptr_; - COM_auto_ptr& new_owner_; + private: + COM_auto_ptr* owner_; }; template @@ -463,36 +523,48 @@ class func_doesnt_AddRef_t public: explicit func_doesnt_AddRef_t( COM_auto_ptr& P ) - : ptr_(0), - new_owner_(P) + : owner_(&P) { // nothing else to do } + func_doesnt_AddRef_t( func_doesnt_AddRef_t& F ) + : owner_(F.owner_) + { + F.owner_ = 0; + } + ~func_doesnt_AddRef_t() { - new_owner_ = ptr_; + if ( owner_ ) + owner_->finish_assignment(); } +#if 1 + operator void**() + { + return REINTERPRET_CAST(void**, owner_->start_assignment(true)); + } +#endif + T*& operator*() { - return ptr_; + assert(owner_); + return *(owner_->start_assignment(true)); } operator T**() { - return &ptr_; + assert(owner_); + return owner_->start_assignment(true); } - operator void**() - { - return REINTERPRET_CAST(void **,&ptr_); - } + private: + func_doesnt_AddRef_t operator=( const func_doesnt_AddRef_t& ); // not to be implemented - private: - T* ptr_; - COM_auto_ptr& new_owner_; + private: + COM_auto_ptr* owner_; }; template diff --git a/xpcom/tests/test_COM_auto_ptr.cpp b/xpcom/tests/test_COM_auto_ptr.cpp index c0b2f7f7d802..9edc2a359ce1 100644 --- a/xpcom/tests/test_COM_auto_ptr.cpp +++ b/xpcom/tests/test_COM_auto_ptr.cpp @@ -148,21 +148,6 @@ CreateIFoo( void** result ) return 0; } -NS_RESULT -CreateIFooVoidPtrRef( void*& result ) - // a typical factory function (that calls AddRef) - { - cout << ">>CreateIFooVoidPtrRef() --> "; - IFoo* foop = new IFoo; - cout << "IFoo@" << STATIC_CAST(void*, foop) << endl; - - foop->AddRef(); - result = foop; - - cout << "<* result ) { @@ -288,10 +273,10 @@ main() IFoo* raw_foo2p = foo2p.get(); cout << endl << "### Test 8: can you compare a |COM_auto_ptr| with a raw interface pointer [!=]?" << endl; - if ( foo1p.get() != raw_foo2p ) - cout << "foo1p.get() != raw_foo2p" << endl; + if ( foo1p != raw_foo2p ) + cout << "foo1p != raw_foo2p" << endl; else - cout << "foo1p.get() == raw_foo2p" << endl; + cout << "foo1p == raw_foo2p" << endl; cout << endl << "### Test 9: can you assign one |COM_auto_ptr| into another?" << endl; @@ -304,10 +289,10 @@ main() cout << "foo1p != foo2p" << endl; cout << endl << "### Test 11: can you compare a |COM_auto_ptr| with a raw interface pointer [==]?" << endl; - if ( raw_foo2p == foo2p.get() ) - cout << "raw_foo2p == foo2p.get()" << endl; + if ( raw_foo2p == foo2p ) + cout << "raw_foo2p == foo2p" << endl; else - cout << "raw_foo2p != foo2p.get()" << endl; + cout << "raw_foo2p != foo2p" << endl; cout << endl << "### Test 12: bare pointer test?" << endl; if ( foo1p ) @@ -350,21 +335,16 @@ main() { cout << endl << "### Test 17: basic parameter behavior?" << endl; COM_auto_ptr foop; - CreateIFoo( (void **)(IFoo **)func_AddRefs_t(foop) ); + CreateIFoo( func_AddRefs_t(foop) ); } { cout << endl << "### Test 18: basic parameter behavior, using the short form?" << endl; COM_auto_ptr foop; - CreateIFoo( (void **)(IFoo **)func_AddRefs(foop) ); + CreateIFoo( func_AddRefs(foop) ); } - { - cout << endl << "### Test 18: basic parameter behavior, using the short form?" << endl; - COM_auto_ptr foop; - CreateIFooVoidPtrRef( *(void **)func_AddRefs(foop) ); - } { cout << endl << "### Test 19: reference parameter behavior?" << endl;