1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2006 Rich Sposato
4 // The copyright on this file is protected under the terms of the MIT license.
5 //
6 // Permission to use, copy, modify, distribute and sell this software for any
7 //     purpose is hereby granted without fee, provided that the above copyright
8 //     notice appear in all copies and that both that copyright notice and this
9 //     permission notice appear in supporting documentation.
10 // The author makes no representations about the
11 //     suitability of this software for any purpose. It is provided "as is"
12 //     without express or implied warranty.
13 ////////////////////////////////////////////////////////////////////////////////
14 #ifndef LOKI_STRONG_PTR_INC_
15 #define LOKI_STRONG_PTR_INC_
16 
17 // $Id: StrongPtr.h 914 2008-12-19 00:39:29Z rich_sposato $
18 
19 
20 #include <loki/SmartPtr.h>
21 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
22     #include <loki/Threads.h>
23 #endif
24 
25 
26 ////////////////////////////////////////////////////////////////////////////////
27 ///
28 ///  \par Terminology
29 ///   These terms are used within this file's comments.
30 ///   -# StrongPtr : Class used to implement both strong and weak pointers. The
31 ///      second template parameter determines if a StrongPtr is weak or strong.
32 ///   -# Strong pointer : A pointer that claims ownership of a shared object.
33 ///      When the last strong copointer dies, the object is destroyed even if
34 ///      there are weak copointers.
35 ///   -# Weak pointer : A pointer that does not own the shared object it points
36 ///       to.  It only destroys the shared object if there no strong copointers
37 ///       exist when it dies.
38 ///   -# Copointers : All the pointers that refer to the same shared object.
39 ///      The copointers must have the same ownership policy, but the other
40 ///      policies may be different.
41 ///   -# Pointee : The shared object.
42 ///
43 ///  \par OwnershipPolicy
44 ///   The ownership policy has the pointer to the actual object, and it also
45 ///   keeps track of the strong and weak copointers so that it can know if any
46 ///   strong copointers remain.  The plain pointer it maintains is stored as a
47 ///   void pointer, which allows the ownership policy classes to be monolithic
48 ///   classes instead of template classes.  As monolithic classes, they reduce
49 ///   amount of code-bloat.
50 ///
51 ///  \par Writing Your Own OwnershipPolicy
52 ///   If you write your own policy, you must implement these 12 functions:
53 ///   -# explicit YourPolicy( bool strong )
54 ///   -# YourPolicy( void * p, bool strong )
55 ///   -# YourPolicy( const YourPolicy & rhs, bool strong )
56 ///   -# bool Release( bool strong )
57 ///   -# void Increment( bool strong )
58 ///   -# bool Decrement( bool strong )
59 ///   -# bool HasStrongPointer( void ) const
60 ///   -# void Swap( YourPolicy & rhs )
61 ///   -# void SetPointer( void * p )
62 ///   -# void ZapPointer( void )
63 ///   -# void * GetPointer( void ) const
64 ///   -# void * & GetPointerRef( void ) const
65 ///   It is strongly recommended that all 12 of these functions be protected
66 ///   instead of public.  These two functions are optional for single-threaded
67 ///   policies, but required for multi-threaded policies:
68 ///   -# void Lock( void ) const
69 ///   -# void Unlock( void ) const
70 ///   This function is entirely optional:
71 ///   -# bool Merge( TwoRefLinks & rhs )
72 ///
73 ///  \par DeletePolicy
74 ///   The delete policy provides a mechanism to destroy an object and a default
75 ///   value for an uninitialized pointer.  You can override this policy with
76 ///   your own when using the Singleton, NullObject, or Prototype design
77 ///   patterns.
78 ///
79 ///  \par Writing Your Own DeletePolicy
80 ///   If you write your own policy, you must implement these 3 functions:
81 ///   -# void static Delete( const P * p )
82 ///   -# static P * Default( void )
83 ///   -# void Swap( YourResetPolicy & )
84 ///
85 ///  \par ResetPolicy
86 ///   A reset policy tells the ReleaseAll and ResetAll functions whether they
87 ///   should release or reset the StrongPtr copointers.  These functions do
88 ///   not affect just one StrongPtr, but all copointers.  That is unlike
89 ///   SmartPtr where the Release and Reset functions only affect 1 SmartPtr,
90 ///   and leave all copointers untouched.  A useful trick you can do with the
91 ///   ResetPolicy is to not allow reset when a strong pointer exists, and then
92 ///   use the NoCheck policy for all strong pointers.  The reset policy
93 ///   guarantees the strong pointers always have a valid pointee, so checking
94 ///   is not required; but weak pointers may still require checking.
95 ///
96 ///  \par Writing Your Own ResetPolicy
97 ///   If you write your own policy, you must implement these 2 functions:
98 ///   -# bool OnReleaseAll( bool ) const
99 ///   -# bool OnResetAll( bool ) const
100 ///   The bool parameter means that this was called with a strong pointer or
101 ///   one of its copointers is strong.  The return value means the pointer
102 ///   can be reset or released.
103 ///
104 ///  \defgroup  StrongPointerOwnershipGroup StrongPtr Ownership policies
105 ///  \ingroup   SmartPointerGroup
106 ///  \defgroup  StrongPointerDeleteGroup Delete policies
107 ///  \ingroup   SmartPointerGroup
108 ///  \defgroup  StrongPointerResetGroup Reset policies
109 ///  \ingroup   SmartPointerGroup
110 ////////////////////////////////////////////////////////////////////////////////
111 
112 
113 namespace Loki
114 {
115 
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 ///  \class DeleteUsingFree
119 ///
120 ///  \ingroup  StrongPointerDeleteGroup
121 ///  Implementation of the DeletePolicy used by StrongPtr.  Uses explicit call
122 ///   to T's destructor followed by call to free.  This policy is useful for
123 ///   managing the lifetime of pointers to structs returned by C functions.
124 ////////////////////////////////////////////////////////////////////////////////
125 
126 template < class P >
127 class DeleteUsingFree
128 {
129 public:
Delete(const P * p)130     inline void static Delete( const P * p )
131     {
132         if ( 0 != p )
133         {
134             p->~P();
135             ::free( p );
136         }
137     }
138 
139     /// Provides default value to initialize the pointer
Default(void)140     inline static P * Default( void )
141     {
142         return 0;
143     }
144 
Swap(DeleteUsingFree &)145     inline void Swap( DeleteUsingFree & ) {}
146 };
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 ///  \class DeleteNothing
150 ///
151 ///  \ingroup  StrongPointerDeleteGroup
152 ///  Implementation of the DeletePolicy used by StrongPtr.  This will never
153 ///   delete anything.  You can use this policy with pointers to an undefined
154 ///   type or a pure interface class with a protected destructor.
155 ////////////////////////////////////////////////////////////////////////////////
156 
157 template < class P >
158 class DeleteNothing
159 {
160 public:
Delete(const P *)161     inline static void Delete( const P * )
162     {
163         // Do nothing at all!
164     }
165 
Default(void)166     inline static P * Default( void )
167     {
168         return 0;
169     }
170 
Swap(DeleteNothing &)171     inline void Swap( DeleteNothing & ) {}
172 };
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 ///  \class DeleteSingle
176 ///
177 ///  \ingroup  StrongPointerDeleteGroup
178 ///  Implementation of the DeletePolicy used by StrongPtr.  This deletes just
179 ///   one shared object.  This is the default class for the DeletePolicy.
180 ////////////////////////////////////////////////////////////////////////////////
181 
182 template < class P >
183 class DeleteSingle
184 {
185 public:
Delete(const P * p)186     inline static void Delete( const P * p )
187     {
188         /** @note If you see an error message about a negative subscript, that
189          means your are attempting to use Loki to delete an incomplete type.
190          Please don't use this policy with incomplete types; you may want to
191          use DeleteNothing instead.
192          */
193         typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
194         delete p;
195     }
196 
Default(void)197     inline static P * Default( void )
198     {
199         return 0;
200     }
201 
Swap(DeleteSingle &)202     inline void Swap( DeleteSingle & ) {}
203 };
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 ///  \class DeleteArray
207 ///
208 ///  \ingroup  StrongPointerDeleteGroup
209 ///  Implementation of the DeletePolicy used by StrongPtr.  This deletes an
210 ///   array of shared objects.
211 ////////////////////////////////////////////////////////////////////////////////
212 
213 template < class P >
214 class DeleteArray
215 {
216 public:
Delete(const P * p)217     inline static void Delete( const P * p )
218     {
219         /** @note If you see an error message about a negative subscript, that
220          means your are attempting to use Loki to delete an incomplete type.
221          Please don't use this policy with incomplete types; you may want to
222          use DeleteNothing instead.
223          */
224         typedef char Type_Must_Be_Defined[ sizeof(P) ? 1 : -1 ];
225         delete [] p;
226     }
227 
Default(void)228     inline static P * Default( void )
229     {
230         return 0;
231     }
232 
Swap(DeleteArray &)233     inline void Swap( DeleteArray & ) {}
234 };
235 
236 ////////////////////////////////////////////////////////////////////////////////
237 ///  \class CantResetWithStrong
238 ///
239 ///  \ingroup  StrongPointerResetGroup
240 ///  Implementation of the ResetPolicy used by StrongPtr.  This is the default
241 ///   ResetPolicy for StrongPtr.  It forbids reset and release only if a strong
242 ///   copointer exists.
243 ////////////////////////////////////////////////////////////////////////////////
244 
245 template < class P >
246 struct CantResetWithStrong
247 {
OnReleaseAllCantResetWithStrong248     inline bool OnReleaseAll( bool hasStrongPtr ) const
249     {
250         return ! hasStrongPtr;
251     }
252 
OnResetAllCantResetWithStrong253     inline bool OnResetAll( bool hasStrongPtr ) const
254     {
255         return ! hasStrongPtr;
256     }
257 };
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 ///  \class AllowReset
261 ///
262 ///  \ingroup  StrongPointerResetGroup
263 ///  Implementation of the ResetPolicy used by StrongPtr.  It allows reset and
264 ///   release under any circumstance.
265 ////////////////////////////////////////////////////////////////////////////////
266 
267 template < class P >
268 struct AllowReset
269 {
OnReleaseAllAllowReset270     inline bool OnReleaseAll( bool ) const
271     {
272         return true;
273     }
OnResetAllAllowReset274     inline bool OnResetAll( bool ) const
275     {
276         return true;
277     }
278 };
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 ///  \class NeverReset
282 ///
283 ///  \ingroup  StrongPointerResetGroup
284 ///  Implementation of the ResetPolicy used by StrongPtr.  It forbids reset and
285 ///   release under any circumstance.
286 ////////////////////////////////////////////////////////////////////////////////
287 
288 template < class P >
289 struct NeverReset
290 {
OnReleaseAllNeverReset291     inline bool OnReleaseAll( bool ) const
292     {
293         return false;
294     }
OnResetAllNeverReset295     inline bool OnResetAll( bool ) const
296     {
297         return false;
298     }
299 };
300 
301 // ----------------------------------------------------------------------------
302 
303 namespace Private
304 {
305 
306 ////////////////////////////////////////////////////////////////////////////////
307 ///  \class TwoRefCountInfo
308 ///
309 ///  \ingroup  StrongPointerOwnershipGroup
310 ///   Implementation detail for reference counting strong and weak pointers.
311 ///   It maintains a void pointer and 2 reference counts.  Since it is just a
312 ///   class for managing implementation details, it is not intended to be used
313 ///   directly - which is why it is in a private namespace.  Each instance is a
314 ///   shared resource for all copointers, and there should be only one of these
315 ///   for each set of copointers.  This class is small, trivial, and inline.
316 ////////////////////////////////////////////////////////////////////////////////
317 
318 class LOKI_EXPORT TwoRefCountInfo
319 {
320 public:
321 
TwoRefCountInfo(bool strong)322     inline explicit TwoRefCountInfo( bool strong )
323         : m_pointer( 0 )
324         , m_strongCount( strong ? 1 : 0 )
325         , m_weakCount( strong ? 0 : 1 )
326     {
327     }
328 
TwoRefCountInfo(void * p,bool strong)329     inline TwoRefCountInfo( void * p, bool strong )
330         : m_pointer( p )
331         , m_strongCount( strong ? 1 : 0 )
332         , m_weakCount( strong ? 0 : 1 )
333     {
334     }
335 
~TwoRefCountInfo(void)336     inline ~TwoRefCountInfo( void )
337     {
338         assert( 0 == m_strongCount );
339         assert( 0 == m_weakCount );
340     }
341 
HasStrongPointer(void)342     inline bool HasStrongPointer( void ) const
343     {
344         return ( 0 < m_strongCount );
345     }
346 
HasWeakPointer(void)347     inline bool HasWeakPointer( void ) const
348     {
349         return ( 0 < m_weakCount );
350     }
351 
IncStrongCount(void)352     inline void IncStrongCount( void )
353     {
354         ++m_strongCount;
355     }
356 
IncWeakCount(void)357     inline void IncWeakCount( void )
358     {
359         ++m_weakCount;
360     }
361 
DecStrongCount(void)362     inline bool DecStrongCount( void )
363     {
364         assert( 0 < m_strongCount );
365         --m_strongCount;
366         const bool isZero = ( 0 == m_strongCount );
367         return isZero;
368     }
369 
DecWeakCount(void)370     inline void DecWeakCount( void )
371     {
372         assert( 0 < m_weakCount );
373         --m_weakCount;
374     }
375 
ZapPointer(void)376     inline void ZapPointer( void )
377     {
378         m_pointer = 0;
379     }
380 
SetPointer(void * p)381     void SetPointer( void * p )
382     {
383         m_pointer = p;
384     }
385 
GetPointer(void)386     inline void * GetPointer( void ) const
387     {
388         return m_pointer;
389     }
390 
GetPointerRef(void)391     inline void * & GetPointerRef( void ) const
392     {
393         return const_cast< void * & >( m_pointer );
394     }
395 
396 private:
397     /// Copy-constructor not implemented.
398     TwoRefCountInfo( const TwoRefCountInfo & );
399     /// Copy-assignment operator not implemented.
400     TwoRefCountInfo & operator = ( const TwoRefCountInfo & );
401 
402     void * m_pointer;
403     unsigned int m_strongCount;
404     unsigned int m_weakCount;
405 };
406 
407 ////////////////////////////////////////////////////////////////////////////////
408 ///  \class LockableTwoRefCountInfo
409 ///
410 ///  \ingroup  StrongPointerOwnershipGroup
411 ///   Implementation detail for thread-safe reference counting for strong and
412 ///   weak pointers.  It uses TwoRefCountInfo to manage the pointer and counts.
413 ///   All this does is provide a thread safety mechanism.  Since it is just a
414 ///   class for managing implementation details, it is not intended to be used
415 ///   directly - which is why it is in a private namespace.  Each instance is a
416 ///   shared resource for all copointers, and there should be only one of these
417 ///   for each set of copointers.  This class is small, trivial, and inline.
418 ///
419 ///  \note This class is not designed for use with a single-threaded model.
420 ///   Tests using a single-threaded model will not run properly, but tests in a
421 ///   multi-threaded model with either class-level-locking or object-level-locking
422 ///   do run properly.
423 ////////////////////////////////////////////////////////////////////////////////
424 
425 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
426 
427 class LOKI_EXPORT LockableTwoRefCountInfo
428     : private Loki::Private::TwoRefCountInfo
429 {
430 public:
431 
LockableTwoRefCountInfo(bool strong)432     inline explicit LockableTwoRefCountInfo( bool strong )
433         : TwoRefCountInfo( strong )
434         , m_Mutex()
435     {
436     }
437 
LockableTwoRefCountInfo(void * p,bool strong)438     LockableTwoRefCountInfo( void * p, bool strong )
439         : TwoRefCountInfo( p, strong )
440         , m_Mutex()
441     {
442     }
443 
~LockableTwoRefCountInfo(void)444     inline ~LockableTwoRefCountInfo( void )
445     {
446     }
447 
Lock(void)448     inline void Lock( void ) const
449     {
450         m_Mutex.Lock();
451     }
452 
Unlock(void)453     inline void Unlock( void ) const
454     {
455         m_Mutex.Unlock();
456     }
457 
HasStrongPointer(void)458     inline bool HasStrongPointer( void ) const
459     {
460         m_Mutex.Lock();
461         const bool has = TwoRefCountInfo::HasStrongPointer();
462         m_Mutex.Unlock();
463         return has;
464     }
465 
HasWeakPointer(void)466     inline bool HasWeakPointer( void ) const
467     {
468         m_Mutex.Lock();
469         const bool has = TwoRefCountInfo::HasWeakPointer();
470         m_Mutex.Unlock();
471         return has;
472     }
473 
IncStrongCount(void)474     inline void IncStrongCount( void )
475     {
476         m_Mutex.Lock();
477         TwoRefCountInfo::IncStrongCount();
478         m_Mutex.Unlock();
479     }
480 
IncWeakCount(void)481     inline void IncWeakCount( void )
482     {
483         m_Mutex.Lock();
484         TwoRefCountInfo::IncWeakCount();
485         m_Mutex.Unlock();
486     }
487 
DecStrongCount(void)488     inline bool DecStrongCount( void )
489     {
490         m_Mutex.Lock();
491         const bool isZero = TwoRefCountInfo::DecStrongCount();
492         m_Mutex.Unlock();
493         return isZero;
494     }
495 
DecWeakCount(void)496     inline void DecWeakCount( void )
497     {
498         m_Mutex.Lock();
499         TwoRefCountInfo::DecWeakCount();
500         m_Mutex.Unlock();
501     }
502 
ZapPointer(void)503     inline void ZapPointer( void )
504     {
505         m_Mutex.Lock();
506         TwoRefCountInfo::ZapPointer();
507         m_Mutex.Unlock();
508     }
509 
SetPointer(void * p)510     void SetPointer( void * p )
511     {
512         m_Mutex.Lock();
513         TwoRefCountInfo::SetPointer( p );
514         m_Mutex.Unlock();
515     }
516 
GetPointer(void)517     inline void * GetPointer( void ) const
518     {
519         return TwoRefCountInfo::GetPointer();
520     }
521 
GetPointerRef(void)522     inline void * & GetPointerRef( void ) const
523     {
524         return TwoRefCountInfo::GetPointerRef();
525     }
526 
527 private:
528     /// Default constructor is not available.
529     LockableTwoRefCountInfo( void );
530     /// Copy constructor is not available.
531     LockableTwoRefCountInfo( const LockableTwoRefCountInfo & );
532     /// Copy-assignment operator is not available.
533     LockableTwoRefCountInfo & operator = ( const LockableTwoRefCountInfo & );
534 
535     mutable LOKI_DEFAULT_MUTEX m_Mutex;
536 };
537 
538 #endif // if object-level-locking or class-level-locking
539 
540 } // end namespace Private
541 
542 ////////////////////////////////////////////////////////////////////////////////
543 ///  \class TwoRefCounts
544 ///
545 ///  \ingroup  StrongPointerOwnershipGroup
546 ///   This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
547 ///   shared instance of TwoRefCountInfo.  This is the default policy for
548 ///   OwnershipPolicy.  Some functions are trivial enough to be inline, while
549 ///   others are implemented elsewhere.  It is not thread safe, and is intended
550 ///   for single-threaded environments.
551 ////////////////////////////////////////////////////////////////////////////////
552 
553 class LOKI_EXPORT TwoRefCounts
554 {
555 protected:
556 
557     explicit TwoRefCounts( bool strong );
558 
559     TwoRefCounts( const void * p, bool strong );
560 
TwoRefCounts(const TwoRefCounts & rhs,bool strong)561     TwoRefCounts( const TwoRefCounts & rhs, bool strong ) :
562         m_counts( rhs.m_counts )
563     {
564         Increment( strong );
565     }
566 
567     /** The destructor does not need to do anything since the call to
568      ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
569      this dtor would have done.
570      */
~TwoRefCounts(void)571     inline ~TwoRefCounts( void ) {}
572 
Release(bool strong)573     inline bool Release( bool strong )
574     {
575         return Decrement( strong );
576     }
577 
HasStrongPointer(void)578     bool HasStrongPointer( void ) const
579     {
580         return m_counts->HasStrongPointer();
581     }
582 
583     void Swap( TwoRefCounts & rhs );
584 
SetPointer(void * p)585     void SetPointer( void * p )
586     {
587         m_counts->SetPointer( p );
588     }
589 
590     void ZapPointer( void );
591 
GetPointerRef(void)592     inline void * & GetPointerRef( void ) const
593     {
594         return m_counts->GetPointerRef();
595     }
596 
GetPointer(void)597     inline void * GetPointer( void ) const
598     {
599         return m_counts->GetPointer();
600     }
601 
602 private:
603     TwoRefCounts( void );
604     TwoRefCounts & operator = ( const TwoRefCounts & );
605 
606     void Increment( bool strong );
607 
608     bool Decrement( bool strong );
609 
610     /// Pointer to all shared data.
611     Loki::Private::TwoRefCountInfo * m_counts;
612 };
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 ///  \class LockableTwoRefCounts
616 ///
617 ///  \ingroup  StrongPointerOwnershipGroup
618 ///   This implementation of StrongPtr's OwnershipPolicy uses a pointer to a
619 ///   shared instance of LockableTwoRefCountInfo.  It behaves very similarly to
620 ///   TwoRefCounts, except that it provides thread-safety.  Some functions are
621 ///   trivial enough to be inline, while others are implemented elsewhere.
622 ///
623 ///  \note This class is not designed for use with a single-threaded model.
624 ///   Tests using a single-threaded model will not run properly, but tests in a
625 ///   multi-threaded model with either class-level-locking or object-level-locking
626 ///   do run properly.
627 ////////////////////////////////////////////////////////////////////////////////
628 
629 #if defined (LOKI_OBJECT_LEVEL_THREADING) || defined (LOKI_CLASS_LEVEL_THREADING)
630 
631 class LOKI_EXPORT LockableTwoRefCounts
632 {
633     typedef SmallValueObject< ::Loki::ClassLevelLockable > ThreadSafePointerAllocator;
634 
635 protected:
636 
LockableTwoRefCounts(bool strong)637     explicit LockableTwoRefCounts( bool strong )
638         : m_counts( NULL )
639     {
640         void * temp = ThreadSafePointerAllocator::operator new(
641             sizeof(Loki::Private::LockableTwoRefCountInfo) );
642 #ifdef DO_EXTRA_LOKI_TESTS
643         assert( temp != 0 );
644 #endif
645         m_counts = new ( temp ) Loki::Private::LockableTwoRefCountInfo( strong );
646     }
647 
LockableTwoRefCounts(const void * p,bool strong)648     LockableTwoRefCounts( const void * p, bool strong )
649         : m_counts( NULL )
650     {
651         void * temp = ThreadSafePointerAllocator::operator new(
652             sizeof(Loki::Private::LockableTwoRefCountInfo) );
653 #ifdef DO_EXTRA_LOKI_TESTS
654         assert( temp != 0 );
655 #endif
656         void * p2 = const_cast< void * >( p );
657         m_counts = new ( temp )
658             Loki::Private::LockableTwoRefCountInfo( p2, strong );
659     }
660 
LockableTwoRefCounts(const LockableTwoRefCounts & rhs,bool strong)661     LockableTwoRefCounts( const LockableTwoRefCounts & rhs, bool strong ) :
662         m_counts( rhs.m_counts )
663     {
664         Increment( strong );
665     }
666 
667     /** The destructor does not need to do anything since the call to
668      ZapPointer inside StrongPtr::~StrongPtr will do the cleanup which
669      this dtor would have done.
670      */
~LockableTwoRefCounts(void)671     inline ~LockableTwoRefCounts( void ) {}
672 
Lock(void)673     inline void Lock( void ) const
674     {
675         m_counts->Lock();
676     }
677 
Unlock(void)678     inline void Unlock( void ) const
679     {
680         m_counts->Unlock();
681     }
682 
Release(bool strong)683     inline bool Release( bool strong )
684     {
685         return Decrement( strong );
686     }
687 
Increment(bool strong)688     void Increment( bool strong )
689     {
690         if ( strong )
691         {
692             m_counts->IncStrongCount();
693         }
694         else
695         {
696             m_counts->IncWeakCount();
697         }
698     }
699 
Decrement(bool strong)700     bool Decrement( bool strong )
701     {
702         bool noStrongPointers = false;
703         if ( strong )
704         {
705             noStrongPointers = m_counts->DecStrongCount();
706         }
707         else
708         {
709             m_counts->DecWeakCount();
710             noStrongPointers = !m_counts->HasStrongPointer();
711         }
712         return noStrongPointers;
713     }
714 
HasStrongPointer(void)715     bool HasStrongPointer( void ) const
716     {
717         return m_counts->HasStrongPointer();
718     }
719 
Swap(LockableTwoRefCounts & rhs)720     void Swap( LockableTwoRefCounts & rhs )
721     {
722         std::swap( m_counts, rhs.m_counts );
723     }
724 
SetPointer(void * p)725     void SetPointer( void * p )
726     {
727         m_counts->SetPointer( p );
728     }
729 
ZapPointer(void)730     void ZapPointer( void )
731     {
732 #ifdef DO_EXTRA_LOKI_TESTS
733         assert( !m_counts->HasStrongPointer() );
734 #endif
735         if ( m_counts->HasWeakPointer() )
736         {
737             m_counts->ZapPointer();
738         }
739         else
740         {
741             ThreadSafePointerAllocator::operator delete ( m_counts,
742                 sizeof(Loki::Private::LockableTwoRefCountInfo) );
743             m_counts = NULL;
744         }
745     }
746 
GetPointer(void)747     inline void * GetPointer( void ) const
748     {
749         return m_counts->GetPointer();
750     }
751 
GetPointerRef(void)752     inline void * & GetPointerRef( void ) const
753     {
754         return m_counts->GetPointerRef();
755     }
756 
757 private:
758     LockableTwoRefCounts( void );
759     LockableTwoRefCounts & operator = ( const LockableTwoRefCounts & );
760 
761     /// Pointer to all shared data.
762     Loki::Private::LockableTwoRefCountInfo * m_counts;
763 };
764 
765 #endif // if object-level-locking or class-level-locking
766 
767 ////////////////////////////////////////////////////////////////////////////////
768 ///  \class TwoRefLinks
769 ///
770 ///  \ingroup  StrongPointerOwnershipGroup
771 ///   This implementation of StrongPtr's OwnershipPolicy uses a doubly-linked
772 ///   cycle of copointers to a shared object. Some functions are trivial enough
773 ///   to be inline, while others are implemented in elsewhere.  It is not thread
774 ///   safe, and is intended for single-threaded environments.
775 ////////////////////////////////////////////////////////////////////////////////
776 
777 class LOKI_EXPORT TwoRefLinks
778 {
779 protected:
780 
TwoRefLinks(bool strong)781     inline explicit TwoRefLinks( bool strong )
782         : m_pointer( 0 )
783         , m_strong( strong )
784     {
785         m_prev = m_next = this;
786     }
787 
788     TwoRefLinks( const void * p, bool strong );
789 
790     TwoRefLinks( const TwoRefLinks & rhs, bool strong );
791 
792     bool Release( bool strong );
793 
794     void Swap( TwoRefLinks & rhs );
795 
796     bool Merge( TwoRefLinks & rhs );
797 
798     bool HasStrongPointer( void ) const;
799 
ZapPointer(void)800     inline void ZapPointer( void )
801     {
802         ZapAllNodes();
803     }
804 
805     void SetPointer( void * p );
806 
GetPointer(void)807     inline void * GetPointer( void ) const
808     {
809         return m_pointer;
810     }
811 
GetPointerRef(void)812     inline void * & GetPointerRef( void ) const
813     {
814         return const_cast< void * & >( m_pointer );
815     }
816 
817 private:
818     static unsigned int CountPrevCycle( const TwoRefLinks * pThis );
819     static unsigned int CountNextCycle( const TwoRefLinks * pThis );
820 
821     /// Not implemented.
822     TwoRefLinks( void );
823     /// Not implemented.
824     TwoRefLinks & operator = ( const TwoRefLinks & );
825 
826     bool HasPrevNode( const TwoRefLinks * p ) const;
827     bool HasNextNode( const TwoRefLinks * p ) const;
828     bool AllNodesHaveSamePointer( void ) const;
829     void ZapAllNodes( void );
830 
831     void * m_pointer;
832     mutable TwoRefLinks * m_prev;
833     mutable TwoRefLinks * m_next;
834     const bool m_strong;
835 };
836 
837 ////////////////////////////////////////////////////////////////////////////////
838 ///  \class StrongPtr
839 ///
840 ///  \ingroup SmartPointerGroup
841 ///
842 ///  \param Strong           default = true,
843 ///  \param OwnershipPolicy  default = TwoRefCounts,
844 ///  \param ConversionPolicy default = DisallowConversion,
845 ///  \param CheckingPolicy   default = AssertCheck,
846 ///  \param ResetPolicy      default = CantResetWithStrong,
847 ///  \param DeletePolicy     default = DeleteSingle
848 ///  \param ConstnessPolicy  default = LOKI_DEFAULT_CONSTNESS
849 ////////////////////////////////////////////////////////////////////////////////
850 
851 template
852 <
853     typename T,
854     bool Strong = true,
855     class OwnershipPolicy = Loki::TwoRefCounts,
856     class ConversionPolicy = Loki::DisallowConversion,
857     template < class > class CheckingPolicy = Loki::AssertCheck,
858     template < class > class ResetPolicy = Loki::CantResetWithStrong,
859     template < class > class DeletePolicy = Loki::DeleteSingle,
860     template < class > class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS
861 >
862 class StrongPtr
863     : public OwnershipPolicy
864     , public ConversionPolicy
865     , public CheckingPolicy< T * >
866     , public ResetPolicy< T >
867     , public DeletePolicy< T >
868 {
869     typedef ConversionPolicy CP;
870     typedef CheckingPolicy< T * > KP;
871     typedef ResetPolicy< T > RP;
872     typedef DeletePolicy< T > DP;
873 
874 public:
875 
876     typedef OwnershipPolicy OP;
877 
878     typedef T * StoredType;    // the type of the pointer
879     typedef T * PointerType;   // type returned by operator->
880     typedef T & ReferenceType; // type returned by operator*
881 
882     typedef typename ConstnessPolicy< T >::Type * ConstPointerType;
883     typedef typename ConstnessPolicy< T >::Type & ConstReferenceType;
884 
885 private:
886     struct NeverMatched {};
887 
888 #ifdef LOKI_SMARTPTR_CONVERSION_CONSTRUCTOR_POLICY
889     typedef typename Select< CP::allow, const StoredType&, NeverMatched>::Result ImplicitArg;
890     typedef typename Select<!CP::allow, const StoredType&, NeverMatched>::Result ExplicitArg;
891 #else
892     typedef const StoredType& ImplicitArg;
893     typedef typename Select<false, const StoredType&, NeverMatched>::Result ExplicitArg;
894 #endif
895 
896 public:
897 
StrongPtr(void)898     StrongPtr( void ) : OP( Strong )
899     {
900         KP::OnDefault( GetPointer() );
901     }
902 
StrongPtr(ExplicitArg p)903     explicit StrongPtr( ExplicitArg p ) : OP( p, Strong )
904     {
905         KP::OnInit( GetPointer() );
906     }
907 
StrongPtr(ImplicitArg p)908     StrongPtr( ImplicitArg p ) : OP( p, Strong )
909     {
910         KP::OnInit( GetPointer() );
911     }
912 
StrongPtr(const StrongPtr & rhs)913     StrongPtr( const StrongPtr & rhs )
914         : OP( rhs, Strong ), CP( rhs ), KP( rhs ), DP( rhs )
915     {
916     }
917 
918     template
919     <
920         typename T1,
921         bool S1,
922         class OP1,
923         class CP1,
924         template < class > class KP1,
925         template < class > class RP1,
926         template < class > class DP1,
927         template < class > class CNP1
928     >
StrongPtr(const StrongPtr<T1,S1,OP1,CP1,KP1,RP1,DP1,CNP1> & rhs)929     StrongPtr(
930         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
931         : OP( rhs, Strong )
932     {
933     }
934 
935     template
936     <
937         typename T1,
938         bool S1,
939         class OP1,
940         class CP1,
941         template < class > class KP1,
942         template < class > class RP1,
943         template < class > class DP1,
944         template < class > class CNP1
945     >
StrongPtr(StrongPtr<T1,S1,OP1,CP1,KP1,RP1,DP1,CNP1> & rhs)946     StrongPtr(
947         StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
948         : OP( rhs, Strong )
949     {
950     }
951 
StrongPtr(RefToValue<StrongPtr> rhs)952     StrongPtr( RefToValue< StrongPtr > rhs )
953         : OP( rhs, Strong ), KP( rhs ), CP( rhs ), DP( rhs )
954     {
955     }
956 
957     operator RefToValue< StrongPtr >( void )
958     {
959         return RefToValue< StrongPtr >( *this );
960     }
961 
962     StrongPtr & operator = ( const StrongPtr & rhs )
963     {
964         if ( GetPointer() != rhs.GetPointer() )
965         {
966             StrongPtr temp( rhs );
967             temp.Swap( *this );
968         }
969         return *this;
970     }
971 
972     StrongPtr & operator = ( T * p )
973     {
974         if ( GetPointer() != p )
975         {
976             StrongPtr temp( p );
977             Swap( temp );
978         }
979         return *this;
980     }
981 
982     template
983     <
984         typename T1,
985         bool S1,
986         class OP1,
987         class CP1,
988         template < class > class KP1,
989         template < class > class RP1,
990         template < class > class DP1,
991         template < class > class CNP1
992     >
993     StrongPtr & operator = (
994         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
995     {
996         if ( !rhs.Equals( GetPointer() ) )
997         {
998             StrongPtr temp( rhs );
999             temp.Swap( *this );
1000         }
1001         return *this;
1002     }
1003 
IsStrong(void)1004     bool IsStrong( void ) const
1005     {
1006         return Strong;
1007     }
1008 
Swap(StrongPtr & rhs)1009     void Swap( StrongPtr & rhs )
1010     {
1011         OP::Swap( rhs );
1012         CP::Swap( rhs );
1013         KP::Swap( rhs );
1014         DP::Swap( rhs );
1015     }
1016 
~StrongPtr()1017     ~StrongPtr()
1018     {
1019         if ( OP::Release( Strong ) )
1020         {
1021             // Must zap the pointer before deleteing the object. Otherwise a
1022             // cycle of weak pointers will lead to recursion, which leads to
1023             // to deleting the shared object multiple times, which leads to
1024             // undefined behavior.  Therefore, this must get pointer before
1025             // zapping it, and then delete the temp pointer.
1026             T * p = GetPointer();
1027             OP::ZapPointer();
1028             if ( p != 0 )
1029             {
1030                 DP::Delete( p );
1031             }
1032         }
1033     }
1034 
1035 #ifdef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1036 
1037     // old non standard in class definition of friends
ReleaseAll(StrongPtr & sp,typename StrongPtr::StoredType & p)1038     friend bool ReleaseAll( StrongPtr & sp,
1039         typename StrongPtr::StoredType & p )
1040     {
1041         if ( !sp.RP::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1042         {
1043             return false;
1044         }
1045         p = sp.GetPointer();
1046         sp.OP::SetPointer( sp.DP::Default() );
1047         return true;
1048     }
1049 
ResetAll(StrongPtr & sp,typename StrongPtr::StoredType p)1050     friend bool ResetAll( StrongPtr & sp,
1051         typename StrongPtr::StoredType p )
1052     {
1053         if ( sp.OP::GetPointer() == p )
1054         {
1055             return true;
1056         }
1057         if ( !sp.RP::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1058         {
1059             return false;
1060         }
1061         sp.DP::Delete( sp.GetPointer() );
1062         sp.OP::SetPointer( p );
1063         return true;
1064     }
1065 
1066 #else
1067 
1068     template
1069     <
1070         typename T1,
1071         bool S1,
1072         class OP1,
1073         class CP1,
1074         template < class > class KP1,
1075         template < class > class RP1,
1076         template < class > class DP1,
1077         template < class > class CNP1
1078     >
1079     friend bool ReleaseAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1080         typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType & p );
1081 
1082 
1083     template
1084     <
1085         typename T1,
1086         bool S1,
1087         class OP1,
1088         class CP1,
1089         template < class > class KP1,
1090         template < class > class RP1,
1091         template < class > class DP1,
1092         template < class > class CNP1
1093     >
1094     friend bool ResetAll( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & sp,
1095         typename StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 >::StoredType p );
1096 
1097 #endif
1098 
1099 
1100     /** Merges ownership of two StrongPtr's that point to same shared object
1101       but are not copointers.  Requires Merge function in OwnershipPolicy.
1102       \return True for success, false if not pointer to same object.
1103      */
1104     template
1105     <
1106         typename T1,
1107         bool S1,
1108         class OP1,
1109         class CP1,
1110         template < class > class KP1,
1111         template < class > class RP1,
1112         template < class > class DP1,
1113         template < class > class CNP1
1114     >
Merge(StrongPtr<T1,S1,OP1,CP1,KP1,RP1,DP1,CNP1> & rhs)1115     bool Merge( StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs )
1116     {
1117         if ( OP::GetPointer() != rhs.OP::GetPointer() )
1118         {
1119             return false;
1120         }
1121         return OP::Merge( rhs );
1122     }
1123 
1124     /** Locks StrongPtr so other threads can't affect pointer.  Requires the
1125      OwnershipPolicy to have Lock function.
1126      */
Lock(void)1127     void Lock( void )
1128     {
1129         OP::Lock();
1130     }
1131 
1132     /** Unlocks StrongPtr so other threads can affect pointer.  Requires the
1133      OwnershipPolicy to have Unlock function.
1134      */
Unlock(void)1135     void Unlock( void )
1136     {
1137         OP::Unlock();
1138     }
1139 
1140     PointerType operator -> ()
1141     {
1142         KP::OnDereference( GetPointer() );
1143         return GetPointer();
1144     }
1145 
1146     ConstPointerType operator -> () const
1147     {
1148         KP::OnDereference( GetPointer() );
1149         return GetPointer();
1150     }
1151 
1152     ReferenceType operator * ()
1153     {
1154         KP::OnDereference( GetPointer() );
1155         return * GetPointer();
1156     }
1157 
1158     ConstReferenceType operator * () const
1159     {
1160         KP::OnDereference( GetPointer() );
1161         return * GetPointer();
1162     }
1163 
1164     /// Helper function which can be called to avoid exposing GetPointer function.
1165     template < class T1 >
Equals(const T1 * p)1166     bool Equals( const T1 * p ) const
1167     {
1168         return ( GetPointer() == p );
1169     }
1170 
1171     /// Helper function which can be called to avoid exposing GetPointer function.
1172     template < class T1 >
LessThan(const T1 * p)1173     bool LessThan( const T1 * p ) const
1174     {
1175         return ( GetPointer() < p );
1176     }
1177 
1178     /// Helper function which can be called to avoid exposing GetPointer function.
1179     template < class T1 >
GreaterThan(const T1 * p)1180     bool GreaterThan( const T1 * p ) const
1181     {
1182         return ( GetPointer() > p );
1183     }
1184 
1185     /// Equality comparison operator is templated to handle ambiguity.
1186     template
1187     <
1188         typename T1,
1189         bool S1,
1190         class OP1,
1191         class CP1,
1192         template < class > class KP1,
1193         template < class > class RP1,
1194         template < class > class DP1,
1195         template < class > class CNP1
1196     >
1197     bool operator == (
1198         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1199     {
1200         return ( rhs.Equals( GetPointer() ) );
1201     }
1202 
1203     /// Inequality comparison operator is templated to handle ambiguity.
1204     template
1205     <
1206         typename T1,
1207         bool S1,
1208         class OP1,
1209         class CP1,
1210         template < class > class KP1,
1211         template < class > class RP1,
1212         template < class > class DP1,
1213         template < class > class CNP1
1214     >
1215     bool operator != (
1216         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1217     {
1218         return !( rhs.Equals( GetPointer() ) );
1219     }
1220 
1221     /// Less-than comparison operator is templated to handle ambiguity.
1222     template
1223     <
1224         typename T1,
1225         bool S1,
1226         class OP1,
1227         class CP1,
1228         template < class > class KP1,
1229         template < class > class RP1,
1230         template < class > class DP1,
1231         template < class > class CNP1
1232     >
1233     bool operator < (
1234         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1235     {
1236         return ( rhs.GreaterThan( GetPointer() ) );
1237     }
1238 
1239     /// Greater-than comparison operator is templated to handle ambiguity.
1240     template
1241     <
1242         typename T1,
1243         bool S1,
1244         class OP1,
1245         class CP1,
1246         template < class > class KP1,
1247         template < class > class RP1,
1248         template < class > class DP1,
1249         template < class > class CNP1
1250     >
1251     inline bool operator > (
1252         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1253     {
1254         return ( rhs.LessThan( GetPointer() ) );
1255     }
1256 
1257     /// Less-than-or-equal-to operator is templated to handle ambiguity.
1258     template
1259     <
1260         typename T1,
1261         bool S1,
1262         class OP1,
1263         class CP1,
1264         template < class > class KP1,
1265         template < class > class RP1,
1266         template < class > class DP1,
1267         template < class > class CNP1
1268     >
1269     inline bool operator <= (
1270         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1271     {
1272         return !( rhs.LessThan( GetPointer() ) );
1273     }
1274 
1275     /// Greater-than-or-equal-to operator is templated to handle ambiguity.
1276     template
1277     <
1278         typename T1,
1279         bool S1,
1280         class OP1,
1281         class CP1,
1282         template < class > class KP1,
1283         template < class > class RP1,
1284         template < class > class DP1,
1285         template < class > class CNP1
1286     >
1287     inline bool operator >= (
1288         const StrongPtr< T1, S1, OP1, CP1, KP1, RP1, DP1, CNP1 > & rhs ) const
1289     {
1290         return !( rhs.GreaterThan( GetPointer() ) );
1291     }
1292 
1293     inline bool operator ! () const // Enables "if ( !sp ) ..."
1294     {
1295         return ( 0 == OP::GetPointer() );
1296     }
1297 
1298 protected:
1299 
GetPointer(void)1300     inline PointerType GetPointer( void )
1301     {
1302         return reinterpret_cast< PointerType >( OP::GetPointer() );
1303     }
1304 
GetPointer(void)1305     inline ConstPointerType GetPointer( void ) const
1306     {
1307         return reinterpret_cast< ConstPointerType >( OP::GetPointer() );
1308     }
1309 
1310 private:
1311 
GetPointerRef(void)1312     inline ReferenceType GetPointerRef( void )
1313     {
1314         return reinterpret_cast< ReferenceType >( OP::GetPointerRef() );
1315     }
1316 
GetPointerRef(void)1317     inline ConstReferenceType GetPointerRef( void ) const
1318     {
1319         return reinterpret_cast< ConstReferenceType >( OP::GetPointerRef() );
1320     }
1321 
1322     // Helper for enabling 'if (sp)'
1323     struct Tester
1324     {
TesterTester1325         Tester(int) {}
dummyTester1326         void dummy() {}
1327     };
1328 
1329     typedef void (Tester::*unspecified_boolean_type_)();
1330 
1331     typedef typename Select< CP::allow, Tester, unspecified_boolean_type_ >::Result
1332         unspecified_boolean_type;
1333 
1334 public:
1335     // enable 'if (sp)'
unspecified_boolean_type()1336     operator unspecified_boolean_type() const
1337     {
1338         return !*this ? 0 : &Tester::dummy;
1339     }
1340 
1341 private:
1342     // Helper for disallowing automatic conversion
1343     struct Insipid
1344     {
InsipidInsipid1345         Insipid(PointerType) {}
1346     };
1347 
1348     typedef typename Select< CP::allow, PointerType, Insipid >::Result
1349         AutomaticConversionResult;
1350 
1351 public:
AutomaticConversionResult()1352     operator AutomaticConversionResult() const
1353     {
1354         return GetPointer();
1355     }
1356 
1357 };
1358 
1359 // ----------------------------------------------------------------------------
1360 
1361 // friend functions
1362 
1363 #ifndef LOKI_ENABLE_FRIEND_TEMPLATE_TEMPLATE_PARAMETER_WORKAROUND
1364 
1365 template
1366 <
1367     typename U,
1368     typename T,
1369     bool S,
1370     class OP,
1371     class CP,
1372     template < class > class KP,
1373     template < class > class RP,
1374     template < class > class DP,
1375     template < class > class CNP
1376 >
ReleaseAll(StrongPtr<T,S,OP,CP,KP,RP,DP,CNP> & sp,typename StrongPtr<T,S,OP,CP,KP,RP,DP,CNP>::StoredType & p)1377 bool ReleaseAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1378                  typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType & p )
1379 {
1380   if ( !sp.RP<T>::OnReleaseAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1381   {
1382     return false;
1383   }
1384   p = sp.GetPointer();
1385   sp.OP::SetPointer( sp.DP<T>::Default() );
1386   return true;
1387 }
1388 
1389 template
1390 <
1391     typename U,
1392     typename T,
1393     bool S,
1394     class OP,
1395     class CP,
1396     template < class > class KP,
1397     template < class > class RP,
1398     template < class > class DP,
1399     template < class > class CNP
1400 >
ResetAll(StrongPtr<T,S,OP,CP,KP,RP,DP,CNP> & sp,typename StrongPtr<T,S,OP,CP,KP,RP,DP,CNP>::StoredType p)1401 bool ResetAll( StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & sp,
1402                typename StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >::StoredType p )
1403 {
1404   if ( sp.OP::GetPointer() == p )
1405   {
1406     return true;
1407   }
1408   if ( !sp.RP<T>::OnResetAll( sp.IsStrong() || sp.OP::HasStrongPointer() ) )
1409   {
1410     return false;
1411   }
1412   sp.DP<T>::Delete( sp.GetPointer() );
1413   sp.OP::SetPointer( p );
1414   return true;
1415 }
1416 #endif
1417 
1418 
1419 // free comparison operators for class template StrongPtr
1420 
1421 ///  operator== for lhs = StrongPtr, rhs = raw pointer
1422 ///  \ingroup SmartPointerGroup
1423 template
1424 <
1425     typename U,
1426     typename T,
1427     bool S,
1428     class OP,
1429     class CP,
1430     template < class > class KP,
1431     template < class > class RP,
1432     template < class > class DP,
1433     template < class > class CNP
1434 >
1435 inline bool operator == (
1436     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1437 {
1438     return ( lhs.Equals( rhs ) );
1439 }
1440 
1441 ///  operator== for lhs = raw pointer, rhs = StrongPtr
1442 ///  \ingroup SmartPointerGroup
1443 template
1444 <
1445     typename U,
1446     typename T,
1447     bool S,
1448     class OP,
1449     class CP,
1450     template < class > class KP,
1451     template < class > class RP,
1452     template < class > class DP,
1453     template < class > class CNP
1454 >
1455 inline bool operator == ( U * lhs,
1456     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1457 {
1458     return ( rhs.Equals( lhs ) );
1459 }
1460 
1461 ///  operator!= for lhs = StrongPtr, rhs = raw pointer
1462 ///  \ingroup SmartPointerGroup
1463 template
1464 <
1465     typename U,
1466     typename T,
1467     bool S,
1468     class OP,
1469     class CP,
1470     template < class > class KP,
1471     template < class > class RP,
1472     template < class > class DP,
1473     template < class > class CNP
1474 >
1475 inline bool operator != (
1476     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1477 {
1478     return !( lhs.Equals( rhs ) );
1479 }
1480 
1481 ///  operator!= for lhs = raw pointer, rhs = StrongPtr
1482 ///  \ingroup SmartPointerGroup
1483 template
1484 <
1485     typename U,
1486     typename T,
1487     bool S,
1488     class OP,
1489     class CP,
1490     template < class > class KP,
1491     template < class > class RP,
1492     template < class > class DP,
1493     template < class > class CNP
1494 >
1495 inline bool operator != ( U * lhs,
1496     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1497 {
1498     return !( rhs.Equals( lhs ) );
1499 }
1500 
1501 ///  operator< for lhs = StrongPtr, rhs = raw pointer
1502 ///  \ingroup SmartPointerGroup
1503 template
1504 <
1505     typename U,
1506     typename T,
1507     bool S,
1508     class OP,
1509     class CP,
1510     template < class > class KP,
1511     template < class > class RP,
1512     template < class > class DP,
1513     template < class > class CNP
1514 >
1515 inline bool operator < (
1516     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1517 {
1518     return ( lhs.LessThan( rhs ) );
1519 }
1520 
1521 ///  operator< for lhs = raw pointer, rhs = StrongPtr
1522 ///  \ingroup SmartPointerGroup
1523 template
1524 <
1525     typename U,
1526     typename T,
1527     bool S,
1528     class OP,
1529     class CP,
1530     template < class > class KP,
1531     template < class > class RP,
1532     template < class > class DP,
1533     template < class > class CNP
1534 >
1535 inline bool operator < ( U * lhs,
1536     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1537 {
1538     return ( rhs.GreaterThan( lhs ) );
1539 }
1540 
1541 //  operator> for lhs = StrongPtr, rhs = raw pointer
1542 ///  \ingroup SmartPointerGroup
1543 template
1544 <
1545     typename U,
1546     typename T,
1547     bool S,
1548     class OP,
1549     class CP,
1550     template < class > class KP,
1551     template < class > class RP,
1552     template < class > class DP,
1553     template < class > class CNP
1554 >
1555 inline bool operator > (
1556     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1557 {
1558     return ( lhs.GreaterThan( rhs ) );
1559 }
1560 
1561 ///  operator> for lhs = raw pointer, rhs = StrongPtr
1562 ///  \ingroup SmartPointerGroup
1563 template
1564 <
1565     typename U,
1566     typename T,
1567     bool S,
1568     class OP,
1569     class CP,
1570     template < class > class KP,
1571     template < class > class RP,
1572     template < class > class DP,
1573     template < class > class CNP
1574 >
1575 inline bool operator > ( U * lhs,
1576     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1577 {
1578     return ( rhs.LessThan( lhs ) );
1579 }
1580 
1581 ///  operator<= for lhs = StrongPtr, rhs = raw pointer
1582 ///  \ingroup SmartPointerGroup
1583 template
1584 <
1585     typename U,
1586     typename T,
1587     bool S,
1588     class OP,
1589     class CP,
1590     template < class > class KP,
1591     template < class > class RP,
1592     template < class > class DP,
1593     template < class > class CNP
1594 >
1595 inline bool operator <= (
1596     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1597 {
1598     return !( lhs.GreaterThan( rhs ) );
1599 }
1600 
1601 ///  operator<= for lhs = raw pointer, rhs = StrongPtr
1602 ///  \ingroup SmartPointerGroup
1603 template
1604 <
1605     typename U,
1606     typename T,
1607     bool S,
1608     class OP,
1609     class CP,
1610     template < class > class KP,
1611     template < class > class RP,
1612     template < class > class DP,
1613     template < class > class CNP
1614 >
1615 inline bool operator <= ( U * lhs,
1616     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1617 {
1618     return !( rhs.LessThan( lhs ) );
1619 }
1620 
1621 ///  operator>= for lhs = StrongPtr, rhs = raw pointer
1622 ///  \ingroup SmartPointerGroup
1623 template
1624 <
1625     typename U,
1626     typename T,
1627     bool S,
1628     class OP,
1629     class CP,
1630     template < class > class KP,
1631     template < class > class RP,
1632     template < class > class DP,
1633     template < class > class CNP
1634 >
1635 inline bool operator >= (
1636     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs, U * rhs )
1637 {
1638     return !( lhs.LessThan( rhs ) );
1639 }
1640 
1641 ///  operator>= for lhs = raw pointer, rhs = StrongPtr
1642 ///  \ingroup SmartPointerGroup
1643 template
1644 <
1645     typename U,
1646     typename T,
1647     bool S,
1648     class OP,
1649     class CP,
1650     template < class > class KP,
1651     template < class > class RP,
1652     template < class > class DP,
1653     template < class > class CNP
1654 >
1655 inline bool operator >= ( U * lhs,
1656     const StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs )
1657 {
1658     return !( rhs.GreaterThan( lhs ) );
1659 }
1660 
1661 } // namespace Loki
1662 
1663 namespace std
1664 {
1665     ////////////////////////////////////////////////////////////////////////////////
1666     ///  specialization of std::less for StrongPtr
1667     ///  \ingroup SmartPointerGroup
1668     ////////////////////////////////////////////////////////////////////////////////
1669     template
1670     <
1671         typename T,
1672         bool S,
1673         class OP,
1674         class CP,
1675         template < class > class KP,
1676         template < class > class RP,
1677         template < class > class DP,
1678         template < class > class CNP
1679     >
1680     struct less< Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > >
1681         : public binary_function<
1682             Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >,
1683             Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP >, bool >
1684     {
1685         bool operator () (
1686             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & lhs,
1687             const Loki::StrongPtr< T, S, OP, CP, KP, RP, DP, CNP > & rhs ) const
1688         {
1689             return ( lhs < rhs );
1690         }
1691     };
1692 }
1693 
1694 ////////////////////////////////////////////////////////////////////////////////
1695 
1696 #endif // end file guardian
1697 
1698