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