 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Gianni Mariani Guest
|
Posted: Mon Jul 07, 2003 2:25 am Post subject: Comments on TR1 smart pointers |
|
|
I would like to discuss :
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html
I would like to see 3 more features in the libraries regarding smart
pointers, in particular reference counting smart pointers.
a) Returning or passing smart pointers.
A number of issues occur when passing or returning pointers. The most
critical one is when in a tight loop and passing a reference counted
pointer. The calling of a virtual method to increment and decrement the
reference count can become a significant performance issue. Passing the
raw pointer produces confusing semantics. The best solution is to
create 3 co-operating smart pointer classes. Once class is intended to
be for objects that are semi-persistant, the other 2 are for passing or
returning pointers. Of the 2 pointer passing templates one is intended
to imply a policy that the receiver is being passed the responsibility
to release a reference while the other is intended to imply that no sucj
responsibility exists. Passing of a raw reference counted pointer would
be considered at worst an error or at best a legacy issue.
In practice, this system reduces the errors due to reference counting
leaks/bugs to virtually zero. I have implemented such a scheme where on
of the smart pointer types (the one where the implication is to pass the
obligation to call release) is instrumented and will assert on improper
usage.
b) Interface for reference counting.
There are a number of different methods names/schemes used for managing
reference counts. I suggest that to make the library truly useful, it
would be best to parameterize the reference counting methods through a
template argument. This would enable the use of the smart pointer
templates with systems like MS-COM as well as inc()/dec() methods.
c) Reference to pointer within.
There are older interfaces that expect a pointer to pointer to the
object to be returned. It would be most advantageous for a `safe' way
to access the inner pointer.
I have a working implementation of a smart pointer reference counting
library that implements all of these features. I would be more than
happy to submit it as an alternative smart pointer system for consideration.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Peter Dimov Guest
|
Posted: Wed Jul 09, 2003 2:43 am Post subject: Re: Comments on TR1 smart pointers |
|
|
[email]gi2nospam (AT) mariani (DOT) ws[/email] (Gianni Mariani) wrote in message news:<beaj87$c19 (AT) dispatch (DOT) concentric.net>...
| Quote: | I would like to discuss :
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html
I would like to see 3 more features in the libraries regarding smart
pointers, in particular reference counting smart pointers.
a) Returning or passing smart pointers.
A number of issues occur when passing or returning pointers. The most
critical one is when in a tight loop and passing a reference counted
pointer. The calling of a virtual method to increment and decrement the
reference count can become a significant performance issue.
|
There is no requirement that reference count updates need to be
implemented with virtual member functions.
| Quote: | Passing the raw pointer produces confusing semantics.
|
Not necessarily. A shared_ptr parameter implies that the function
needs to be able to take ownership. If this is not the case, a
reference or a raw pointer (depending on whether NULL is a valid
argument) is more appropriate. Otherwise, passing shared_ptr by const
reference may eliminate the copy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Wed Jul 09, 2003 2:45 am Post subject: Re: Comments on TR1 smart pointers |
|
|
[email]gi2nospam (AT) mariani (DOT) ws[/email] (Gianni Mariani) writes:
| Quote: | Richard Smith wrote:
Gianni Mariani wrote:
I would like to discuss :
http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1450.html
[...]
The calling of a virtual method to increment and decrement the
reference count can become a significant performance issue.
Maybe I'm being unobservant, but can you point me to a bit of N1450
that
requires virtual functions for incrementing and decrementing the reference
count (or equivalent)? Certainly, the Boost 1.30 implementation does not
do a virtual function call in these circumstances. The boost::shared_ptr
copy constructor uses the implictly generated copy constructor, which calls
down to boost::details::shared_count's copy constructor, which in turn calls
boost::details::sp_counted_base::add_ref, which is not virtual and all ought
to be trivially inlineable. A similar call sequence happens in the
destructor, which only calls the virtual dispose function when the reference
count reaches zero.
OK - we might be on different planets here but if we do this to COM
pointers then they are virtual and can't be trivially inlineable.
It makes little sense to make the argument that on one end they are
trivially inlineable and on the other end to say they work with COM
which can't be trivially inlineable.
|
This seems to be a perfect argument for the Boost model. What great
advantage is there in inlining all of a shared_ptr destructor which
calls a non-inlinable COM destructor?
| Quote: | The only use of virtual functions, or calls via function pointers,
etc. in the Boost implementation is in the handling of the deletion
function object, and which is (I believe) unavoidable if the class
is to be useable on an incomplete type. Also, in my experience,
the cost of a virtual function call is relatively small compared to
the cost of deleting an object.
Small but potentially significant.
|
Have you got an application where you've measured it to be
significant?
| Quote: | One of the underlining philosophies in C++ is that you don't pay for
what you don't need. The boost reference counted model seems
(correct me if I am wrong) to require incrementing and decrementing
reference counts when reference counted objects are trivially passed
or retruned.
|
Only when passed. The compiler is free to apply the RVO in most
situations where a shared_ptr is returned.
| Quote: | I suggest that this is directly contradicting the philosophy stated.
|
It's the only safe possibility other than (arguably) auto_ptr, given
the current core language definition. If you need to not pay for
reference counting when objects are passed, you should use an auto_ptr
or a raw pointer (or show us a better alternative).
| Quote: | while the other is intended to imply that no sucj responsibility
exists.
And this is what passing the raw object by const reference is for.
Alternatively, passing shared_ptr by const reference (or even by value)
would work.
But passing a const pointer has nothing to do with policies regarding
obligation for decrementing reference count.
|
If I write:
foo(shared_ptr<T> const&);
Then I can pass any shared_ptr<T> to foo without changing its
reference count. There is no obligation to change its reference
count.
| Quote: | In practice, this system reduces the errors due to reference counting
leaks/bugs to virtually zero.
|
You don't need these reductions with boost::shared_ptr because the
errors you claim to be preventing don't occur with boost::shared_ptr.
| Quote: | Could you please give an example of the sort of leak you hope to
avoid?
Yep, when passing a reference counted pointer and the obligation to
decrement the reference count and no decrement is done by the callee
(or similary when returning a reference counted pointer).
|
Those sorts of problems are the result of your "reference counted
pointer" model which automates too little.
| Quote: | In my experience with boost::shared_ptr, the main source of memory
leaks is when you have cyclic references. After that, I think I
can honestly say, I get more memory leaks due to compiler bugs than
due to misusing boost::shared_ptr.
Yes, and multiple useless calls to reference counting methods.
In tight loops you want to avoid this and if you are limited to using
raw pointers you diminish greatly the value of what the smart pointers
are doing for you.
|
Likewise if you have to keep track of when a shared_ptr's pointee may
have become invalid, which is essentially what your proposal seems to
require. After you pass it to a function which takes one of your
reference-stealing pointers as a parameter, you can't use it anymore.
| Quote: | b) Interface for reference counting.
There are a number of different methods names/schemes used for managing
reference counts. I suggest that to make the library truly useful, it
would be best to parameterize the reference counting methods through a
template argument. This would enable the use of the smart pointer
templates with systems like MS-COM as well as inc()/dec() methods.
One of the design principles given in this documentation is
[III.A.3]:
| No Extra Parameters
|
| Following the "as close as possible" principle, the proposed smart
| pointers have a single template parameter, the type of the pointee.
| Avoiding additional parameters ensures interoperability between
| libraries from different authors, and also makes shared_ptr easier to
| use, teach and recommend.
Although I'm not overly familiar with COM, my understanding is that
by using a suitable deletion function, a shared_ptr can be allowed
to made to hold a COM object. Persumably the game is to get the
deletion function to call
obj->Release().
This avoids any need to specify the functions to increment and
decrement the reference counts.
I don't get it OR this is just plain FUD. You can certainly make it
so the template has default paramater values and hence you get the
benefit described above
|
No you don't. If the parameter is there people will use it and you
will have many different types of smart pointer to the same T, which
don't interoperate. An extra parameter also impairs learnability.
| Quote: | yet it is trivial to use where you're applying these templates to
reference counting interfaces that pre-exist (like COM).
Why limit the ultility of the smart pointer classes ?
|
There's no limitation; you don't need to use COM's slow refcounting
when you can use shared_ptr's fast refcounting.
| Quote: | c) Reference to pointer within.
There are older interfaces that expect a pointer to pointer to the
object to be returned. It would be most advantageous for a `safe' way
to access the inner pointer.
|
Ouch. The only safe pointer to the contained T* of a shared_ptr is a
T*const*. What legacy interface benefits from providing that?
| Quote: | I have a working implementation of a smart pointer reference
counting library that implements all of these features. I would be
more than happy to submit it as an alternative smart pointer system
for consideration.
I think a more constructive course of action would be to explain
precisely which bits of the current proposal you are unhappy with
and why, and how exactly you would modify them. Submitting an
entirely new alternative smart pointer proposal is unlikely to be
productive, especially when the existing proposal is as popular and
heavily used as the Boost one.
|
And already accepted into the TR.
| Quote: | Before I go and invest my time doing such a thing, I would prefer that
this discussion have some interest.
|
You've got several responses now.
| Quote: | Just like std::auto_ptr, I think there is danger that c++ developers
will find significant issues with the boost shared pointers if a
more hearty discussion does not occur.
|
Let's have it, then!
| Quote: | In simple terms, I'm saying "I have some ideas that may make sense,
if you want me to explain it further, then show me you're interested
in dicussing it".
So far, it seems like people (other than yourself) care very little.
|
I think you mistake strong disagreement for disinterest.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Howard Hinnant Guest
|
Posted: Wed Jul 09, 2003 2:46 am Post subject: Re: Comments on TR1 smart pointers |
|
|
In article <bef891$c1h (AT) dispatch (DOT) concentric.net>, Gianni Mariani
<gi2nospam (AT) mariani (DOT) ws> wrote:
| Quote: | So far, it seems like people (other than yourself) care very little.
|
Fwiw, I care a lot.
I'm intimately familiar with the tr1::shared_ptr having independently
implemented it. After reading your post, it seemed like you had not
looked closely at shared_ptr, and there was no reference to enable me
to look more closely at your design.
My day is simply too full to drop everything everytime somebody says:
I've got a better idea, want to know more?
It literally took me 6 months to schedule the two weeks it took to
crawl inside of tr1::shared_ptr enough to feel like I understood it.
I'm probably slow, but that's what it takes me.
If you've got a better idea, and if you feel strongly enough about it,
post it somewhere so we can study it at our convenience. And since
std::tr1::shared_ptr is already there, it would be to your advantage to
compare and contrast with it (with code examples!) in order to shorten
your reader's learning curve.
--
Howard Hinnant
Metrowerks
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
|
 |
Gianni Mariani Guest
|
Posted: Wed Jul 09, 2003 6:41 pm Post subject: Re: Comments on TR1 smart pointers |
|
|
Howard Hinnant wrote:
| Quote: | In article <bef891$c1h (AT) dispatch (DOT) concentric.net>, Gianni Mariani
[email]gi2nospam (AT) mariani (DOT) ws[/email]> wrote:
| So far, it seems like people (other than yourself) care very little.
Fwiw, I care a lot.
I'm intimately familiar with the tr1::shared_ptr having independently
implemented it. After reading your post, it seemed like you had not
looked closely at shared_ptr, and there was no reference to enable me
to look more closely at your design.
|
See attachment.
| Quote: |
My day is simply too full to drop everything everytime somebody says:
I've got a better idea, want to know more?
|
Hint of arrogance I hear ?
| Quote: |
It literally took me 6 months to schedule the two weeks it took to
crawl inside of tr1::shared_ptr enough to feel like I understood it.
I'm probably slow, but that's what it takes me.
|
| Quote: |
If you've got a better idea, and if you feel strongly enough about it,
post it somewhere so we can study it at our convenience. And since
std::tr1::shared_ptr is already there, it would be to your advantage to
compare and contrast with it (with code examples!) in order to shorten
your reader's learning curve.
|
I have attached the header that defines the templates. If you're
interested I'll make an alpha release of the entire library soon as it
stands soon.
/**
* at_lifetime.h
*
*/
#ifndef __at_lifetime_h__
#define __at_lifetime_h__ 1
#include "at_assert.h"
#include "at_types.h"
// ======== Forward references =========================================
//
template < class w_ClassRef > class AT_ReferenceTraits;
#define AT_Friend_LifeTime
template <
class wa_ClassRef,
class wa_RefTraits
| Quote: | friend class AT_LifeTime;
// end macro |
template <
class w_ClassRef,
class w_RefTraits = AT_ReferenceTraits< w_ClassRef >
| Quote: | class AT_LifeTime;
|
#define AT_Friend_LifeView
template <
class wa_ClassRef,
class wa_RefTraits
| Quote: | friend class AT_LifeView;
// end macro |
template <
class w_ClassRef,
class w_RefTraits = AT_ReferenceTraits< w_ClassRef >
| Quote: | class AT_LifeView;
|
// ======== AT_LifeControl ===========================================
/**
* AT_LifeControl is an abstract base class for any class whose lifetime
* is managed by means of reference counting.
*/
class AT_LifeControl
{
public:
virtual ~AT_LifeControl(); // Virtual destructor
/**
* AddRef()
* --------
* This method adds 1 to the reference count to this object.
*
* @return ret The current reference count.
*/
virtual int AddRef() = 0;
/**
* Release()
* ---------
* This decrements by 1 the reference count to this object. Once
* all references have been released (the reference count is zero),
* the AT_LifeControl implementation is expected to delete itself.
* The act of "deleting itself" may be determinted to be different
* for each kind of implementation.
*
* @return ret The current reference count.
*/
virtual int Release() = 0;
};
// ======== AT_ReferenceTraits =========================================
/**
* AT_ReferenceTraits is a helper class that wraps AT_LifeControl's
* AddRef() and Release() methods inside static methods having the
* standard names IncRefCount() and DecRefCount().
*
* If you are using your own reference-counting scheme, i.e. one not
* based on AT_LifeControl, then you will need to define your own
* helper class that implements the same interface as AT_ReferenceTraits.
*
* This is necessary because an AT_ReferenceTraits-like class is expected
* as the second template parameter in the definitions of smart pointers
* concerned with lifetime management.
*/
template <class w_ClassRef>
class AT_ReferenceTraits
{
public:
/**
* IncRefCount()
* -------------
* This method increments the reference count of an object.
*
* @param i_ptr A pointer to the reference-counted object.
*/
static inline void IncRefCount( w_ClassRef i_ptr )
{
i_ptr->AddRef();
}
/**
* DecRefCount()
* -------------
* This method decrements the reference count of an object.
* Once the reference count reaches zero, the object will
* delete itself.
*
* @param i_ptr A pointer to the reference-counted object.
*/
static inline void DecRefCount( w_ClassRef i_ptr )
{
i_ptr->Release();
}
};
// ======== AT_LifeLine ================================================
/**
* The AT_LifeLine smart pointer is designed to solve a very common
* problem: When you pass an object's pointer to a function, how do
* you tell that function that he is supposed to RELEASE the object
* when he's done with it?
*
* With an ordinary pointer, the best you can do is to insert a comment
* to that effect in the code. The problem with this approach is that
* if a programmer doesn't read the comment, he may very well neglect
* to release the object, thereby causing a memory leak.
*
* A better solution is to use a MECHANISM that enforces your desired
* POLICY. The mechanism in this case is the AT_LifeLine smart
* pointer.
*
* By declaring the passed pointer's formal parameter type to be an
* AT_LifeLine, you GUARANTEE that the function either releases the
* object, or copies its pointer to an AT_LifeTime persistent pointer
* so that it can be released later.
*
* How does this happen? Very simple: When the function returns,
* the AT_LifeLine formal parameter goes out of scope, causing its
* destructor to be called. The destructor verifies that the object
* either has been released, or has been copied to a persistent
* pointer.
*
* In effect, the AT_LifeLine forces the function to take OWNERSHIP
* of the pointed-to object, including the responsibility for
* releasing the object when he is done with it.
*
* (Incidentally, the name "AT_LifeLine" is meant to evoke the image
* of someone tossing a rope to someone adrift at sea, saying, in
* effect, "Here, this is yours, you'd better take ownership of it.")
*/
/**
* Instrumenting an AT_LifeLine object to check for memory leaks is a
* useful debugging aid, but is expensive in terms of execution time.
*
* Therefore, the code that checks for memory leaks will be conditionally
* compiled.
*/
#define __AT_MEMORY_LEAK_CHECK
( AT_FORCE_MEMORY_LEAK_CHECK || ! RELEASE_BUILD )
/**
* g_abortOnMemoryLeak
* -------------------
* This global flag specifies the action to take if a memory leak
* is detected: 'true' = Abort, 'false' = Throw exception. (Can
* be useful for unit tests that want to keep on going if a leak
* is detected.)
*/
extern bool g_abortOnMemoryLeak;
/**
* The instrumented and un-instrumented versions of the AT_LifeLine
* class will be given different mangled names, so that if the two
* versions are accidentally co-mingled in an application, the linker
* stands a chance of catching the error.
*/
#if __AT_MEMORY_LEAK_CHECK
#define AT_Friend_LifeLine
template <
class wa_ClassRef,
class wa_RefTraits,
class wa_MemoryLeak
| Quote: | friend class AT_LifeLine;
// end macro |
template <
class w_ClassRef,
class w_RefTraits = AT_ReferenceTraits< w_ClassRef >,
class w_MemoryLeak = int
#else
#define AT_Friend_LifeLine
template <
class wa_ClassRef,
class wa_RefTraits
| Quote: | friend class AT_LifeLine;
// end macro |
template <
class w_ClassRef,
class w_RefTraits = AT_ReferenceTraits< w_ClassRef >
#endif // __AT_MEMORY_LEAK_CHECK
class AT_LifeLine
{
AT_Friend_LifeView
AT_Friend_LifeTime
AT_Friend_LifeLine
/**
* m_ptrVal
* --------
* This data member contains the actual pointer value,
* i.e. the address of the object whose lifetime is
* being managed by reference counting.
*/
w_ClassRef m_ptrVal;
private:
#if __AT_MEMORY_LEAK_CHECK
/**
* m_hasBeenTransferred
* --------------------
* This data member contains a flag indicating whether
* ownership of the pointee has been successfully
* transferred to some persistent pointer.
* (Declared "mutable" so it can be changed even if
* this AT_LifeLine pointer was declared "const".)
*
* Since initialization of data members is not permitted
* in class definitions, we use a helper class to create
* the data member and initialize it to 'false'.
*/
mutable AT_IType< bool, false > m_hasBeenTransferred;
/**
* MadeTransfer()
* --------------
* This method sets a member variable indicating that
* ownership of the pointee has been successfully
* transferred from this AT_LifeLine to some persistent
* pointer.
*/
inline void MadeTransfer() const
{
Assert( ! m_hasBeenTransferred.m_value );
m_hasBeenTransferred.m_value = true;
}
/**
* CheckTransfer()
* ---------------
* This method checks whether ownership of the pointee
* has been successfully transferred to some persistent
* pointer.
*/
inline void CheckTransfer() const
{
if ( m_ptrVal != 0 ) {
// the '.m_value' is to work around
// a compiler bug
Assert( m_hasBeenTransferred.m_value );
}
}
/**
* SetTransfer()
* -------------
* This method sets the 'm_hasBeenTransferred' data
* member to the specified value.
*/
inline void SetTransfer( bool val )
{
m_hasBeenTransferred = val;
}
/**
* Assert()
* --------
* This method aborts or throws an exception if a given
* condition fails.
*/
private: inline void Assert( bool l_condition ) const
{
if ( ! l_condition ) {
if ( g_abortOnMemoryLeak ) {
AT_Assert( false );
}
else {
throw "Memory Leak exception";
}
}
}
#else // __AT_MEMORY_LEAK_CHECK == false
// These versions of the methods are
// empty - meaning there is no instrumentation
//
inline void MadeTransfer() const {};
inline void CheckTransfer() {};
inline void SetTransfer() {};
#endif // __AT_MEMORY_LEAK_CHECK
public:
/**
* AT_LifeLine( AT_LifeLine<> )
* ----------------------------
* This method contructs an AT_LifeLine from another
* AT_LifeLine which may be based on a different under-
* lying pointer type.
*
* @param i_ptr A reference to the AT_LifeLine pointer
* being copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine(
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Indicate that ownership of the pointee has been
// transferred to the new AT_LifeLine pointer.
// -----------------------------------------------
i_ptr.MadeTransfer();
}
/**
* AT_LifeLine( AT_LifeLine )
* --------------------------
* This method explicitly provides a copy constructor for
* AT_LifeLine. Apparently, without such a method, the
* compiler is unable (or unwilling) to use the above
* templated constructor, and instead generates its own
* code that does the wrong thing.
*
* @param i_ptr A reference to the AT_LifeLine pointer
* being copied.
*/
inline AT_LifeLine(
const AT_LifeLine< w_ClassRef, w_RefTraits > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Indicate that ownership of the pointee has been
// transferred to the new AT_LifeLine pointer.
// -----------------------------------------------
i_ptr.MadeTransfer();
}
/**
* AT_LifeLine( AT_LifeTime )
* --------------------------
* This method contructs an AT_LifeLine pointer from an
* AT_LifeTime pointer.
*
* @param i_ptr A reference to the AT_LifeTime pointer
* being copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine(
const AT_LifeTime < w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Increment the pointee's reference count.
// ----------------------------------------
if ( m_ptrVal ) {
w_RefTraits::IncRefCount( m_ptrVal );
}
}
/**
* AT_LifeLine( AT_LifeView )
* --------------------------
* This method contructs an AT_LifeLine from an AT_LifeView.
*
* @param i_ptr A reference to the AT_LifeView pointer
* being copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine(
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Increment the pointee's reference count.
// ----------------------------------------
if ( m_ptrVal ) {
w_RefTraits::IncRefCount( m_ptrVal );
}
}
/**
* AT_LifeLine( dumb pointer )
* ---------------------------
* This method contructs an AT_LifeLine from a dumb pointer.
*
* @param i_ptr The dumb pointer being copied (optional).
*/
inline AT_LifeLine( w_ClassRef i_ptr = 0 )
: m_ptrVal( i_ptr )
{
}
/**
* AT_LifeLine( dumb pointer, bool )
* ---------------------------------
* This method contructs an AT_LifeLine from a dumb pointer,
* optionally transferring ownership of the pointee to the
* AT_LifeLine pointer.
*
* @param i_ptr The dumb pointer being copied.
*
* @param i_takeOwnership A flag indicating whether owner-
* ship of the pointee should be
* transferred to the AT_LifeLine
* pointer.
*/
inline AT_LifeLine( w_ClassRef i_ptr, bool i_takeOwnership )
: m_ptrVal( i_ptr )
{
if ( i_takeOwnership ) {
if ( i_ptr ) {
w_RefTraits::IncRefCount( i_ptr );
}
}
}
/**
* ~AT_LifeLine()
* --------------
* Destructor.
*/
inline ~AT_LifeLine()
{
// Verify that ownership of the pointee has been
// transferred to some persistent pointer.
// ---------------------------------------------
CheckTransfer();
}
/**
* AT_LifeLine = dumb pointer
* --------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeLine is being set equal to a
* dumb pointer.
*
* @param i_ptr The dumb pointer on the right-hand side
* of the '=' sign.
*
* @return ret A reference to the AT_LifeLine on
* the left-hand side of the '=' sign.
*/
inline AT_LifeLine & operator= ( const w_ClassRef i_ptr )
{
// Verify that ownership of the AT_LifeLine's pointee
// has already been transferred to some persistent
// pointer.
// --------------------------------------------------
CheckTransfer();
// Copy the dumb pointer to the AT_LifeLine.
// -----------------------------------------
m_ptrVal = i_ptr;
// Indicate that ownership of the new pointee has not
// yet been transferred to a persistent pointer.
// --------------------------------------------------
SetTransfer( false );
// Return a reference to the AT_LifeLine, so that
// assignment operations can be chained together.
// ----------------------------------------------
return *this;
}
/**
* AT_LifeLine = AT_LifeLine< >
* ----------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeLine is being set equal to another
* AT_LifeLine.
*
* @param i_ptr A reference to the AT_LifeLine on the
* right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeLine on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine & operator= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraits > & i_ptr
)
{
// Tell the source AT_LifeLine that ownership of its
// pointee is being transferred.
// -------------------------------------------------
i_ptr.MadeTransfer();
// Verify that ownership of the destination AT_LifeLine's
// pointee has already been transferred to some persistent
// pointer.
// -------------------------------------------------------
CheckTransfer();
// Copy the pointer value from source to dest.
// -------------------------------------------
m_ptrVal = i_ptr.m_ptrVal;
// Indicate that ownership of the destination pointee
// has not yet been transferred to some persistent
// pointer.
// --------------------------------------------------
SetTransfer( false );
// Return a reference to the destination AT_LifeLine,
// so that assignment operations can be chained together.
// ------------------------------------------------------
return * this;
}
/**
* AT_LifeLine = AT_LifeTime
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeLine is being set equal to an
* AT_LifeTime.
*
* @param i_ptr A reference to the AT_LifeTime on the
* right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeLine on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine & operator= (
const AT_LifeTime<
w_ClassRefRhs,
w_RefTraitsRhs
{
// Verify that ownership of the AT_LifeLine's pointee
// has already been transferred to some persistent
// pointer.
// --------------------------------------------------
CheckTransfer();
// Copy the pointer.
// -----------------
m_ptrVal = i_ptr.m_ptrVal;
// Increment the new pointee's reference count.
// --------------------------------------------
w_RefTraits::IncRefCount( m_ptrVal );
// Indicate that the ownership of the new pointee has
// not yet been transferred to a persistent pointer.
// --------------------------------------------------
SetTransfer( false );
// Return a reference to the AT_LifeLine, so that
// assignment operations can be chained together.
// ----------------------------------------------
return *this;
}
/**
* AT_LifeLine = AT_LifeView
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeLine is being set equal to an
* AT_LifeView.
*
* @param i_ptr A reference to the AT_LifeView on the
* right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeLine on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeLine & operator= (
const AT_LifeView< w_ClassRefRhs, w_RefTraits > & i_ptr
)
{
// Verify that ownership of the AT_LifeLine's pointee
// has already been transferred to some persistent
// pointer.
// --------------------------------------------------
CheckTransfer();
// Copy the pointer.
// -----------------
m_ptrVal = i_ptr.m_ptrVal;
// Increment the new pointee's reference count.
// --------------------------------------------
w_RefTraits::IncRefCount( m_ptrVal );
// Indicate that the ownership of the new pointee has
// not yet been transferred to a persistent pointer.
// --------------------------------------------------
SetTransfer( false );
// Return a reference to the AT_LifeLine, so that
// assignment operations can be chained together.
// ----------------------------------------------
return *this;
}
/**
* Transfer()
* ----------
* This helper method marks this AT_LifeLine as having had
* its pointee's ownership successfully transferred to a
* persistent pointer, and returns the pointee's address.
*
* @return ret The value of the AT_LifeLine pointer,
* i.e. the address of the pointee.
*/
inline w_ClassRef Transfer() const
{
MadeTransfer();
return m_ptrVal;
}
/**
* LifeView()
* ----------
* This helper method returns an AT_LifeView version of
* this AT_LifeLine pointer.
*
* @return ret An AT_LifeView version of this AT_Life-
* Line pointer.
*/
inline AT_LifeView< w_ClassRef, w_RefTraits > LifeView()
const
{
return m_ptrVal;
}
/**
* AT_LifeLine->
* -------------
* This method overloads the dereference operator.
*
* @return ret The value of the AT_LifeLine smart pointer,
* i.e. the address of the object whose life-
* time is being managed by reference counting.
*/
inline w_ClassRef operator-> () const
{
return m_ptrVal;
}
/**
* w_ClassRef( AT_LifeLine )
* -------------------------
* This method overloads the cast-to-<w_ClassRef> operator.
*
* @return ret The value of the AT_LifeLine smart pointer,
* i.e. the address of the object whose life-
* time is being managed by reference counting.
*/
inline operator w_ClassRef () const
{
return m_ptrVal;
}
/**
* bool( AT_LifeLine )
* -------------------
* This method overloads the cast-to-bool operator.
*
* @return ret A boolean indicating whether (true) or not
* (false) the AT_LifeLine pointer is non-NULL.
*/
inline operator bool () const
{
return m_ptrVal != 0;
}
/**
* ! AT_LifeLine
* -------------
* This method overloads the ! operator.
*
* @return ret A boolean indicating whether (true) or not
* (false) the AT_LifeLine pointer is NULL.
*/
inline bool operator! () const
{
return m_ptrVal == 0;
}
/**
* AT_LifeLine == AT_LifeLine
* AT_LifeLine == AT_LifeTime
* AT_LifeLine == AT_LifeView
* --------------------------
* These methods overload the == operator for the cases where
* an AT_LifeLine is being tested for equality to an AT_Life-
* Line, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '==' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '==' sign are equal, i.e.
* point to the same object.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
/**
* AT_LifeLine != AT_LifeLine
* AT_LifeLine != AT_LifeTime
* AT_LifeLine != AT_LifeView
* --------------------------
* These methods overload the != operator for the cases
* where an AT_LifeLine is being tested for inequality
* to an AT_LifeLine, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '!=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '!=' sign are unequal, i.e.
* point to different objects.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
/**
* AT_LifeLine < AT_LifeLine
* AT_LifeLine < AT_LifeTime
* AT_LifeLine < AT_LifeView
* -------------------------
* These methods overload the < operator for the cases
* where an AT_LifeLine is being tested to see if it is
* less than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is less
* than the right-hand pointer, i.e. whether
* the address of the left-hand pointee is
* less than the address of the right-hand
* pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
/**
* AT_LifeLine > AT_LifeLine
* AT_LifeLine > AT_LifeTime
* AT_LifeLine > AT_LifeView
* -------------------------
* These methods overload the > operator for the cases
* where an AT_LifeLine is being tested to see if it is
* greater than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than the right-hand pointer,
* i.e. whether the address of the left-
* hand pointee is greater than the
* address of the right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
/**
* AT_LifeLine <= AT_LifeLine
* AT_LifeLine <= AT_LifeTime
* AT_LifeLine <= AT_LifeView
* --------------------------
* These methods overload the <= operator for the cases
* where an AT_LifeLine is being tested to see if it is
* less than or equal to an AT_LifeLine, an AT_LifeTime,
* or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* less than or equal to the right-hand
* pointer, i.e. whether the address of
* the left-hand pointee is less than or
* equal to the address of the right-hand
* pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
/**
* AT_LifeLine >= AT_LifeLine
* AT_LifeLine >= AT_LifeTime
* AT_LifeLine >= AT_LifeView
* --------------------------
* These methods overload the >= operator for the cases
* where an AT_LifeLine is being tested to see if it is
* greater than or equal to an AT_LifeLine, an AT_Life-
* Time, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than or equal to the right-hand
* pointer, i.e. whether the address of
* the left-hand pointee is greater than
* or equal to the address of the right-
* hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
};
// ======== AT_LifeTime ================================================
/**
* The AT_LifeTime smart pointer is designed to make it easier to
* work with an object whose lifetime is managed by means of ref-
* erence counting.
*
* With an ordinary pointer, you must remember to call AddRef()
* when you start using the object, and Release() when you are
* done with the object.
*
* The problem is that it is very easy to forget to do an AddRef()
* or a Release(), especially when errors occur.
*
* An AT_LifeTime smart pointer solves this problem, by doing the
* AddRef() and Release() for you automatically.
*
* How is this accomplished? Very simply: When an AT_LifeTime
* pointer is copied or assigned to another one, the constructor
* or overloaded assignment operator automatically does an AddRef().
* Similarly, when an AT_LifeTime pointer is deleted or goes out of
* scope, its destructor automatically does a Release().
*/
template < class w_ClassRef, class w_RefTraits >
class AT_LifeTime
{
AT_Friend_LifeView
AT_Friend_LifeTime
AT_Friend_LifeLine
/**
* m_ptrVal
* --------
* This data member contains the actual pointer value,
* i.e. the address of the object whose lifetime is
* being managed by reference counting.
*/
w_ClassRef m_ptrVal;
private:
/**
* ReleasePointee()
* ----------------
* This method releases the pointee, i.e. decrements
* its reference count.
*/
inline void ReleasePointee()
{
if ( m_ptrVal ) {
w_RefTraits::DecRefCount( m_ptrVal );
}
}
/**
* ReleasePointee( new dumb pointer )
* ----------------------------------
* This method releases the existing pointee, i.e.
* decrements its reference count, and "adopts" a
* new one.
*
* @param i_ptrVal A dumb pointer to the new pointee.
* @return ret A dumb pointer to the new pointee.
*/
inline w_ClassRef ReleasePointee( w_ClassRef i_ptrVal )
{
// Save a pointer to the old pointee.
// ----------------------------------
w_ClassRef l_ptrVal = m_ptrVal;
// Point to the new pointee.
// -------------------------
m_ptrVal = i_ptrVal;
// Decrement the old pointee's reference count.
// --------------------------------------------
if ( l_ptrVal ) {
w_RefTraits::DecRefCount( l_ptrVal );
}
// Return a dumb pointer to the new pointee.
// -----------------------------------------
return i_ptrVal;
}
public:
/**
* AT_LifeTime( dumb pointer )
* ---------------------------
* This method contructs an AT_LifeTime from a dumb pointer.
*
* @param i_ptr The dumb pointer to be copied (optional).
*/
inline AT_LifeTime( w_ClassRef i_ptr = 0 ) : m_ptrVal( i_ptr )
{
}
/**
* AT_LifeTime( dumb pointer, bool )
* ---------------------------------
* This method constructs an AT_LifeTime smart pointer from
* a dumb pointer, optionally taking ownership of the pointee
* (by bumping his reference count).
*
* @param ptr The dumb pointer to be copied.
*
* @param i_takeOwnership A flag indicating whether or not
* to take ownership of the pointee.
*/
inline AT_LifeTime( w_ClassRef ptr, bool i_takeOwnership )
: m_ptrVal( ptr )
{
if ( i_takeOwnership ) {
if ( ptr ) {
w_RefTraits::IncRefCount(ptr);
}
}
}
/**
* AT_LifeTime( AT_LifeTime<> )
* ----------------------------
* This method contructs an AT_LifeTime from another
* AT_LifeTime which may be based on a different under-
* lying pointer type.
*
* @param i_ptr A reference to the AT_LifeTime being
* copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime(
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Bump the pointee's reference count.
// -----------------------------------
if ( m_ptrVal ) {
w_RefTraits::IncRefCount(m_ptrVal);
}
}
/**
* AT_LifeTime( AT_LifeTime )
* --------------------------
* This method provides an explicit copy constructor for
* AT_LifeTime. Apparently, without such a constructor,
* the compiler is unable (or unwilling) to use the above
* templated constructor, and instead generates its own
* code that does the wrong thing.
*
* @param i_ptr A reference to the AT_LifeTime pointer
* being copied.
*/
inline AT_LifeTime(
const AT_LifeTime< w_ClassRef, w_RefTraits > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Bump the pointee's reference count.
// -----------------------------------
if ( m_ptrVal ) {
w_RefTraits::IncRefCount(m_ptrVal);
}
}
/**
* AT_LifeTime( AT_LifeView )
* --------------------------
* This method contructs an AT_LifeTime from an AT_LifeView.
*
* @param i_ptr A reference to the AT_LifeView being copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime(
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Bump the pointee's reference count.
// -----------------------------------
if ( m_ptrVal ) {
w_RefTraits::IncRefCount(m_ptrVal);
}
}
/**
* AT_LifeTime( AT_LifeLine )
* --------------------------
* This method contructs an AT_LifeTime from an AT_LifeLine.
*
* @param i_ptr The AT_LifeLine smart pointer being copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime(
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
: m_ptrVal( i_ptr.m_ptrVal )
{
// Mark the AT_LifeLine to indicate that ownership
// of its pointee has been successfully transferred
// to a persistent pointer.
// ------------------------------------------------
i_ptr.MadeTransfer();
}
/**
* ~AT_LifeTime()
* --------------
* Destructor.
*/
inline ~AT_LifeTime()
{
// Releases the pointee.
// ---------------------
ReleasePointee();
}
/**
* AT_LifeTime = dumb pointer
* --------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeTime is being set equal to a dumb
* pointer.
*
* @param i_ptr The dumb pointer on the right-hand side
* of the '=' sign.
*
* @return ret A reference to the AT_LifeTime pointer
* on the left-hand side of the '=' sign.
*/
inline AT_LifeTime< w_ClassRef, w_RefTraits > & operator= (
w_ClassRef i_ptr
)
{
// Release the old pointee, and adopt the new one.
// -----------------------------------------------
ReleasePointee( i_ptr );
// Return a reference to the AT_LifeTime pointer on
// the left-hand side of the '=' sign, so that assign-
// ment operations can be chained together.
// ---------------------------------------------------
return *this;
}
/**
* AT_LifeTime = AT_LifeTime< >
* ----------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeTime is being set equal to another
* AT_LifeTime which may be based on a different underlying
* pointer type.
*
* @param i_ptr A reference to the AT_LifeTime pointer
* on the right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeTime pointer
* on the left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime< w_ClassRef, w_RefTraits > & operator=(
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
// Save the new pointer.
// ---------------------
w_ClassRef l_ptrVal = i_ptr.m_ptrVal;
// Increment the reference count of the new pointee.
// -------------------------------------------------
if ( l_ptrVal ) {
w_RefTraits::IncRefCount( l_ptrVal );
}
// Release the old pointee, and adopt the new one in
// its place.
// -------------------------------------------------
ReleasePointee( l_ptrVal );
// Return a reference to the AT_LifeTime pointer on
// the left-hand side of the '=' sign, so that assign-
// ment operations can be chained together.
// ---------------------------------------------------
return *this;
}
/**
* AT_LifeTime = AT_LifeTime
* -------------------------
* This method explicitly overloads the assignment operator
* for the case where an AT_LifeTime is being set equal to
* another AT_LifeTime, and both AT_LifeTimes point to the
* same type of reference-counted object.
*
* Apparently, if such a method is not provided, the compiler
* is unable (or unwilling) to use the above template version
* of overloaded assignment, and instead generates its own
* code that does the wrong thing.
*
* @param i_ptr A reference to the AT_LifeTime pointer on
* the right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeTime pointer on
* the left-hand side of the '=' sign.
*/
inline AT_LifeTime< w_ClassRef, w_RefTraits > & operator= (
const AT_LifeTime< w_ClassRef, w_RefTraits > & i_ptr
)
{
// Save the new pointer.
// ---------------------
w_ClassRef l_ptrVal = i_ptr.m_ptrVal;
// Increment the reference count of the new pointee.
// -------------------------------------------------
if ( l_ptrVal ) {
w_RefTraits::IncRefCount( l_ptrVal );
}
// Release the old pointee, and adopt the new one in
// its place.
// -------------------------------------------------
ReleasePointee( l_ptrVal );
// Return a reference to the AT_LifeTime pointer on
// the left-hand side of the '=' sign, so that assign-
// ment operations can be chained together.
// ---------------------------------------------------
return *this;
}
/**
* AT_LifeTime = AT_LifeView
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeTime is being set equal to an
* AT_LifeView.
*
* @param i_ptr A reference to the AT_LifeView pointer
* on the right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeTime pointer
* on the left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime< w_ClassRef, w_RefTraits > & operator=(
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
// Save the new pointer.
// ---------------------
w_ClassRef l_ptrVal = i_ptr.m_ptrVal;
// Increment the reference count of the new pointee.
// -------------------------------------------------
if ( l_ptrVal ) {
w_RefTraits::IncRefCount( l_ptrVal );
}
// Release the old pointee, and adopt the new one in
// its place.
// -------------------------------------------------
ReleasePointee( l_ptrVal );
// Return a reference to the AT_LifeTime pointer on
// the left-hand side of the '=' sign, so that assign-
// ment operations can be chained together.
// ---------------------------------------------------
return *this;
}
/**
* AT_LifeTime = AT_LifeLine
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeTime is being set equal to an
* AT_LifeLine.
*
* @param i_ptr A reference to the AT_LifeLine pointer
* on the right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeTime pointer
* on the left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeTime< w_ClassRef, w_RefTraits > & operator=(
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
// Mark the AT_LifeLine as having successfully trans-
// ferred ownership of its pointee to a persistent
// pointer, release the AT_LifeTime's reference to
// its current pointee, and adopt the AT_LifeLine's
// pointee.
// --------------------------------------------------
ReleasePointee( i_ptr.Transfer() );
// Return a reference to the AT_LifeTime pointer on
// the left-hand side of the '=' sign, so that assign-
// ment operations can be chained together.
// ---------------------------------------------------
return *this;
}
/**
* AT_LifeTime->
* -------------
* This method overloads the dereference operator.
*
* @return ret The address of the pointee.
*/
inline w_ClassRef operator-> () const
{
return m_ptrVal;
}
/**
* InnerReference()
* ----------------
* This method releases the pointee, and returns the
* address of the private data member that is used to
* store the address of the pointee. (USE WITH CARE)
*
* @return ret The address of the private data member
* used to store the address of the pointee.
*/
inline w_ClassRef * InnerReference()
{
// Release the pointee.
// --------------------
ReleasePointee( 0 );
// Return the address of the private data member used
// to store the address of the pointee.
// --------------------------------------------------
return & m_ptrVal;
}
/**
* w_ClassRef()
* -------------------------
* This method overloads the cast-to-<w_ClassRef> operator.
*
* @return ret The address of the pointee.
*/
inline operator w_ClassRef () const
{
return m_ptrVal;
}
/**
* bool( AT_LifeTime )
* -------------------
* This method overloads the cast-to-bool operator.
*
* @return ret A flag indicating whether (true) or not
* (false) the pointee's address is non-NULL.
*/
inline operator bool () const
{
return m_ptrVal != 0;
}
/**
* Adopt( dumb pointer )
* ---------------------
* This helper method "adopts" the pointee of a dumb
* pointer, adding a reference to it in the process.
*
* @param i_ptr The address of the new pointee.
* @return ret The address of the new pointee.
*/
inline w_ClassRef Adopt( const w_ClassRef i_ptr )
{
// Add a reference to the dumb pointer's pointee.
// ----------------------------------------------
if ( i_ptr ) {
w_RefTraits::IncRefCount( i_ptr );
}
// Set this AT_LifeTime equal to the dumb pointer.
// -----------------------------------------------
( * this ) = i_ptr;
return i_ptr;
}
/**
* Adopt( AT_LifeLine )
* --------------------
* This helper method transfers ownership of a pointee
* from an AT_LifeLine pointer to this AT_LifeTime pointer.
*
* @param i_ptr A reference to the AT_LifeLine pointer
* whose pointee is to be "adopted".
*
* @return ret The address of the "adopted" pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline w_ClassRef Adopt(
const AT_LifeLine<
w_ClassRefRhs,
w_RefTraitsRhs
{
// Mark the AT_LifeLine pointer as having success-
// fully transferred the ownership of its pointee
// to a persistent pointer.
// -----------------------------------------------
i_ptr.MadeTransfer();
// Set this AT_LifeTime equal to the AT_LifeLine.
// ----------------------------------------------
( * this ) = i_ptr;
return i_ptr;
}
/**
* Transfer()
* ----------
* This helper method returns the address of the pointee,
* and then sets it to zero.
*
* @return ret The address of the pointee.
*/
inline w_ClassRef Transfer()
{
w_ClassRef l_ptr = m_ptrVal;
m_ptrVal = 0;
return l_ptr;
}
/**
* LifeView()
* ----------
* This helper method returns an AT_LifeView version of
* this AT_LifeTime pointer.
*
* @return ret An AT_LifeView version of this AT_Life-
* Time pointer.
*/
inline AT_LifeView< w_ClassRef > LifeView() const
{
return m_ptrVal;
}
/**
* ! AT_LifeTime
* -------------
* This method overloads the ! operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) this AT_LifeTime pointer
* is zero.
*/
inline bool operator ! () const
{
return m_ptrVal == 0;
}
/**
* AT_LifeTime == AT_LifeLine
* AT_LifeTime == AT_LifeTime
* AT_LifeTime == AT_LifeView
* --------------------------
* These methods overload the '==' operator for the cases
* where an AT_LifeTime is being tested for equality to an
* AT_LifeLine, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '==' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '==' sign are equal, i.e.
* point to the same object.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
/**
* AT_LifeTime != AT_LifeLine
* AT_LifeTime != AT_LifeTime
* AT_LifeTime != AT_LifeView
* --------------------------
* These methods overload the '!=' operator for the cases
* where an AT_LifeTime is being tested for inequality to
* an AT_LifeLine, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '!=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '!=' sign are unequal, i.e.
* point to different objects.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
/**
* AT_LifeTime < AT_LifeLine
* AT_LifeTime < AT_LifeTime
* AT_LifeTime < AT_LifeView
* -------------------------
* These methods overload the < operator for the cases
* where an AT_LifeTime is being tested to see if it is
* less than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is less
* than the right-hand pointer, i.e. whether
* the address of the left-hand pointee is
* less than the address of the right-hand
* pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
/**
* AT_LifeTime > AT_LifeLine
* AT_LifeTime > AT_LifeTime
* AT_LifeTime > AT_LifeView
* -------------------------
* These methods overload the > operator for the cases
* where an AT_LifeTime is being tested to see if it is
* greater than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than the right-hand pointer,
* i.e. whether the address of the left-
* hand pointee is greater than the
* address of the right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr )
{
return m_ptrVal > i_ptr.m_ptrVal;
}
/**
* AT_LifeTime <= AT_LifeLine
* AT_LifeTime <= AT_LifeTime
* AT_LifeTime <= AT_LifeView
* --------------------------
* These methods overload the <= operator for the cases
* where an AT_LifeTime is being tested to see if it is
* less than or equal to an AT_LifeLine, an AT_LifeTime,
* or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is less
* than or equal to the right-hand pointer,
* i.e. whether the address of the left-hand
* pointee is less than or equal to the
* address of the right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
/**
* AT_LifeTime >= AT_LifeLine
* AT_LifeTime >= AT_LifeTime
* AT_LifeTime >= AT_LifeView
* --------------------------
* These methods overload the >= operator for the cases
* where an AT_LifeTime is being tested to see if it is
* greater than or equal to an AT_LifeLine, an AT_Life-
* Time, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than or equal to the right-
* hand pointer, i.e. whether the address
* of the left-hand pointee is greater
* than or equal to the address of the
* right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal >= i_ptr.m_ptrVal;
}
};
// ======== AT_LifeView ================================================
/**
* The AT_LifeView smart pointer is intended to be used in a very
* specific situation: You need to pass an object's smart pointer
* to a function so the function can do something with the object.
*
* However, you know the function will have no further need of the
* object once it returns, and you want the caller to retain owner-
* ship of the object (including the responsibility for releasing
* it eventually).
*
* If you pass the object's pointer as an AT_LifeTime, this will
* cause an implicit AddRef() to be done on the object on entry to
* the function, and an implicit Release() on return from the func-
* tion. While this isn't incorrect, it is unnecessary for this
* kind of function, and thus adds a performance penalty for no
* reason.
*
* The solution to this problem is to declare the passed pointer's
* formal parameter type to be an AT_LifeView. This type of pointer
* will NOT do an implicit AddRef() or Release() on the object.
*
* (Incidentally, the name "AT_LifeView" is meant to evoke the image
* of someone handing an expensive vase to someone else and saying,
* in effect, "Here's an interesting object. You can look at it
* for a little while, but then you have to give it right back.")
*
* To be complete however, there is nothing stopping an AT_LifeView
* recipient to copy an AT_LifeView to an AT_LifeTime pointer which
* will perform an implicit AddRef().
*/
template < class w_ClassRef, class w_RefTraits >
class AT_LifeView
{
AT_Friend_LifeView
AT_Friend_LifeTime
AT_Friend_LifeLine
/**
* m_ptrVal
* --------
* This data member contains the actual pointer value,
* i.e. the address of the object whose lifetime is
* being managed by reference counting.
*/
w_ClassRef m_ptrVal;
public:
/**
* AT_LifeView( dumb pointer )
* ---------------------------
* This method contructs an AT_LifeView smart pointer
* from a dumb pointer.
*
* @param i_ptr The dumb pointer (optional).
*/
inline AT_LifeView( w_ClassRef i_ptr = 0 )
: m_ptrVal( i_ptr )
{
}
/**
* AT_LifeView( AT_LifeView<> )
* ----------------------------
* This method constructs an AT_LifeView from another
* AT_LifeView which may be based on a different under-
* lying pointer type.
*
* @param i_ptr A reference to the AT_LifeView from which
* this one is being constructed.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView(
const AT_LifeView<
w_ClassRefRhs,
w_RefTraitsRhs
: m_ptrVal( i_ptr.m_ptrVal )
{
}
/**
* AT_LifeView( AT_LifeView )
* --------------------------
* This method provides an explicit copy constructor
* for AT_LifeView. Apparently, without such a con-
* structor, the compiler is unable (or unwilling)
* to use the above templated constructor, and instead
* generates its own code that does the wrong thing.
*
* @param i_ptr A reference to the AT_LifeView pointer
* being copied.
*/
inline AT_LifeView(
const AT_LifeView<
w_ClassRef,
w_RefTraits
: m_ptrVal( i_ptr.m_ptrVal )
{
}
/**
* AT_LifeView( AT_LifeTime )
* --------------------------
* This method constructs an AT_LifeView from an
* AT_LifeTime.
*
* @param i_ptr A reference to the AT_LifeTime that
* is to be copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView(
const AT_LifeTime<
w_ClassRefRhs,
w_RefTraitsRhs
: m_ptrVal( i_ptr.m_ptrVal )
{
}
/**
* AT_LifeView( AT_LifeLine )
* --------------------------
* This method constructs an AT_LifeView from an
* AT_LifeLine.
*
* @param i_ptr A reference to the AT_LifeLine that
* is to be copied.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView(
const AT_LifeLine<
w_ClassRefRhs,
w_RefTraitsRhs
: m_ptrVal( i_ptr.m_ptrVal )
{
}
/**
* ~AT_LifeView
* ------------
* Destructor.
*/
inline ~AT_LifeView()
{
}
/**
* AT_LifeView = dumb pointer
* --------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeView is being set equal to a dumb
* pointer.
*
* @param i_ptr The dumb pointer on the right-hand
* side of the '=' sign.
*
* @return ret A reference to the AT_LifeView pointer
* on the left-hand side of the '=' sign.
*/
inline AT_LifeView< w_ClassRef, w_RefTraits > &
operator= ( const w_ClassRef i_ptr )
{
m_ptrVal = i_ptr;
return *this;
}
/**
* AT_LifeView = AT_LifeView
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeView is being set equal to another
* AT_LifeView.
*
* @param i_ptr The AT_LifeView on the right-hand side
* of the '=' sign.
*
* @return ret A reference to the AT_LifeView on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView< w_ClassRef, w_RefTraits > &
operator= (
const AT_LifeView<
w_ClassRefRhs,
w_RefTraitsRhs
m_ptrVal = i_ptr.m_ptrVal;
return *this;
}
/**
* AT_LifeView = AT_LifeTime
* --------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeView is being set equal to an
* AT_LifeTime.
*
* @param i_ptr A reference to the AT_LifeTime on the
* right-hand side of the '=' sign.
*
* @return ret A reference to the AT_LifeView on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView< w_ClassRef, w_RefTraits > &
operator= (
const AT_LifeTime<
w_ClassRefRhs,
w_RefTraitsRhs
m_ptrVal = i_ptr.m_ptrVal;
return *this;
}
/**
* AT_LifeView = AT_LifeLine
* -------------------------
* This method overloads the assignment operator for the
* case where an AT_LifeView is being set equal to an
* AT_LifeLine.
*
* @param i_ptr The AT_LifeLine on the right-hand side
* of the '=' sign.
*
* @return ret A reference to the AT_LifeView on the
* left-hand side of the '=' sign.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline AT_LifeView< w_ClassRef, w_RefTraits > &
operator= (
const AT_LifeLine<
w_ClassRefRhs,
w_RefTraits
m_ptrVal = static_cast< w_ClassRef >( i_ptr );
return *this;
}
/**
* AT_LifeView->
* -------------
* This method overloads the dereference operator.
*
* @return ret The address of the pointed-to object.
*/
inline w_ClassRef operator->() const
{
return m_ptrVal;
}
/**
* w_ClassRef( AT_LifeView )
* -------------------------
* This method overloads the cast-to-w_ClassRef operator.
*
* @return ret The address of the pointed-to object.
*/
inline operator w_ClassRef() const
{
return m_ptrVal;
}
/**
* LifeView()
* ----------
* This method returns an AT_LifeView version of this
* pointer.
*
* @return ret An AT_LifeView version of this pointer.
*/
inline AT_LifeView< w_ClassRef > LifeView() const
{
return *this;
}
/**
* bool( AT_LifeView )
* -------------------
* This method overloads the cast-to-bool operator.
*
* @return ret A boolean indicating whether (true) or not
* (false) the pointee's address is non-zero.
*/
inline operator bool() const
{
return m_ptrVal != 0;
}
/**
* ! ( AT_LifeView )
* -----------------
* This method overloads the ! operator.
*
* @return ret A boolean indicating whether (true) or not
* (false) the pointee's address is zero.
*/
inline bool operator! () const
{
return m_ptrVal == 0;
}
/**
* AT_LifeView == AT_LifeLine
* AT_LifeView == AT_LifeTime
* AT_LifeView == AT_LifeView
* --------------------------
* These methods overload the '==' operator for the cases
* where an AT_LifeView is being tested for equality to an
* AT_LifeLine, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '==' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '==' sign are equal, i.e.
* point to the same object.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator== (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal == i_ptr.m_ptrVal;
}
/**
* AT_LifeView != AT_LifeLine
* AT_LifeView != AT_LifeTime
* AT_LifeView != AT_LifeView
* --------------------------
* These methods overload the '!=' operator for the cases
* where an AT_LifeView is being tested for inequality to
* an AT_LifeLine, an AT_LifeTime, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '!=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the two pointers on each
* side of the '!=' sign are unequal, i.e.
* point to different objects.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator!= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal != i_ptr.m_ptrVal;
}
/**
* AT_LifeView < AT_LifeLine
* AT_LifeView < AT_LifeTime
* AT_LifeView < AT_LifeView
* -------------------------
* These methods overload the < operator for the cases
* where an AT_LifeView is being tested to see if it is
* less than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is less
* than the right-hand pointer, i.e. whether
* the address of the left-hand pointee is
* less than the address of the right-hand
* pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator< (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal < i_ptr.m_ptrVal;
}
/**
* AT_LifeView > AT_LifeLine
* AT_LifeView > AT_LifeTime
* AT_LifeView > AT_LifeView
* -------------------------
* These methods overload the > operator for the cases
* where an AT_LifeView is being tested to see if it is
* greater than an AT_LifeLine, an AT_LifeTime, or an
* AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than the right-hand pointer,
* i.e. whether the address of the left-
* hand pointee is greater than the
* address of the right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator> (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal > i_ptr.m_ptrVal;
}
/**
* AT_LifeView <= AT_LifeLine
* AT_LifeView <= AT_LifeTime
* AT_LifeView <= AT_LifeView
* --------------------------
* These methods overload the <= operator for the cases
* where an AT_LifeView is being tested to see if it is
* less than or equal to an AT_LifeLine, an AT_LifeTime,
* or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '<=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is less
* than or equal to the right-hand pointer,
* i.e. whether the address of the left-hand
* pointee is less than or equal to the
* address of the right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeLine< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeTime< w_ClassRefRhs, w_RefTraitsRhs> & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator<= (
const AT_LifeView< w_ClassRefRhs, w_RefTraitsRhs > & i_ptr
)
{
return m_ptrVal <= i_ptr.m_ptrVal;
}
/**
* AT_LifeView >= AT_LifeLine
* AT_LifeView >= AT_LifeTime
* AT_LifeView >= AT_LifeView
* --------------------------
* These methods overload the >= operator for the cases
* where an AT_LifeView is being tested to see if it is
* greater than or equal to an AT_LifeLine, an AT_Life-
* Time, or an AT_LifeView.
*
* @param i_ptr A reference to the smart pointer on the
* right-hand side of the '>=' operator.
*
* @return ret A boolean indicating whether (true) or
* not (false) the left-hand pointer is
* greater than or equal to the right-
* hand pointer, i.e. whether the address
* of the left-hand pointee is greater
* than or equal to the address of the
* right-hand pointee.
*/
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool operator>= (
const AT_LifeLine<
w_ClassRefRhs,
w_RefTraitsRhs
return m_ptrVal >= i_ptr.m_ptrVal;
}
template < class w_ClassRefRhs, class w_RefTraitsRhs >
inline bool o |
|
| Back to top |
|
 |
David Abrahams Guest
|
Posted: Wed Jul 09, 2003 9:25 pm Post subject: Re: Comments on TR1 smart pointers |
|
|
[email]gi2nospam (AT) mariani (DOT) ws[/email] (Gianni Mariani) writes:
| Quote: | /**
* MadeTransfer()
* --------------
* This method sets a member variable indicating that
* ownership of the pointee has been successfully
* transferred from this AT_LifeLine to some persistent
* pointer.
*/
inline void MadeTransfer() const
{
Assert( ! m_hasBeenTransferred.m_value );
m_hasBeenTransferred.m_value = true;
}
|
Why is setting m_hasBeenTransferred to true better than incrementing
a reference count? It doesn't seem like you can achieve much of a
savings here.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
|
|
| Back to top |
| |