llsafehandle.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /**
  2. * @file llsafehandle.h
  3. * @brief Reference-counted object where Object() is valid, not NULL.
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2010, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LLSAFEHANDLE_H
  33. #define LLSAFEHANDLE_H
  34. #include "llpreprocessor.h"
  35. // This is to avoid inlining a llwarns...
  36. LL_NO_INLINE void warnUnreferenceDidAssignment2();
  37. // Expands LLPointer to return a pointer to a special instance of class Type
  38. // instead of NULL. This is useful in instances where operations on NULL
  39. // pointers are semantically safe and/or when error checking occurs at a
  40. // different granularity or in a different part of the code than when
  41. // referencing an object via a LLSafeHandle.
  42. template <class Type>
  43. class LLSafeHandle
  44. {
  45. public:
  46. LL_INLINE LLSafeHandle() noexcept
  47. : mPointer(NULL)
  48. {
  49. }
  50. LL_INLINE LLSafeHandle(Type* ptr) noexcept
  51. : mPointer(NULL)
  52. {
  53. assign(ptr);
  54. }
  55. LL_INLINE LLSafeHandle(const LLSafeHandle<Type>& ptr) noexcept
  56. : mPointer(NULL)
  57. {
  58. assign(ptr.mPointer);
  59. }
  60. // This C++11 move constructor saves us an unref() on the moved handle
  61. // and consequently a corresponding ref() on the constructed handle.
  62. // Note: LLSafeHandle::unref() still happens in ~LLSafeHandle() of the
  63. // moved handle, but it is not propagated down to the unref() method of the
  64. // object we point at, since mPointer is NULL when ~LLSafeHandle() is
  65. // called.
  66. LL_INLINE LLSafeHandle(LLSafeHandle<Type>&& ptr) noexcept
  67. : mPointer(ptr.mPointer)
  68. {
  69. ptr.mPointer = NULL;
  70. }
  71. // Support conversion up the type hierarchy. See Item 45 in Effective C++,
  72. // 3rd Ed.
  73. template<typename Subclass>
  74. LL_INLINE LLSafeHandle(const LLSafeHandle<Subclass>& ptr) noexcept
  75. : mPointer(NULL)
  76. {
  77. assign(ptr.get());
  78. }
  79. LL_INLINE ~LLSafeHandle()
  80. {
  81. unref();
  82. }
  83. LL_INLINE const Type* operator->() const { return nonNull(mPointer); }
  84. LL_INLINE Type* operator->() { return nonNull(mPointer); }
  85. LL_INLINE Type* get() const { return mPointer; }
  86. LL_INLINE void clear() { assign(NULL); }
  87. #if 0 // we disallow these operations as they expose our null objects to
  88. // direct manipulation and bypass the reference counting semantics
  89. LL_INLINE const Type& operator*() const { return *nonNull(mPointer); }
  90. LL_INLINE Type& operator*() { return *nonNull(mPointer); }
  91. #endif
  92. LL_INLINE operator bool() const { return mPointer != NULL; }
  93. LL_INLINE bool operator!() const { return mPointer == NULL; }
  94. LL_INLINE bool isNull() const { return mPointer == NULL; }
  95. LL_INLINE bool notNull() const { return mPointer != NULL; }
  96. LL_INLINE operator Type*() const { return mPointer; }
  97. LL_INLINE operator const Type*() const { return mPointer; }
  98. LL_INLINE bool operator!=(Type* ptr) const { return mPointer != ptr; }
  99. LL_INLINE bool operator==(Type* ptr) const { return mPointer == ptr; }
  100. LL_INLINE bool operator==(const LLSafeHandle<Type>& ptr) const
  101. {
  102. return mPointer == ptr.mPointer;
  103. }
  104. LL_INLINE bool operator<(const LLSafeHandle<Type>& ptr) const
  105. {
  106. return mPointer < ptr.mPointer;
  107. }
  108. LL_INLINE bool operator>(const LLSafeHandle<Type>& ptr) const
  109. {
  110. return mPointer > ptr.mPointer;
  111. }
  112. LL_INLINE LLSafeHandle<Type>& operator=(Type* ptr)
  113. {
  114. assign(ptr);
  115. return *this;
  116. }
  117. LL_INLINE LLSafeHandle<Type>& operator=(const LLSafeHandle<Type>& ptr)
  118. {
  119. assign(ptr.mPointer);
  120. return *this;
  121. }
  122. // Support assignment up the type hierarchy. See Item 45 in Effective C++,
  123. // 3rd Ed.
  124. template<typename Subclass>
  125. LL_INLINE LLSafeHandle<Type>& operator=(const LLSafeHandle<Subclass>& ptr)
  126. {
  127. assign(ptr.get());
  128. return *this;
  129. }
  130. protected:
  131. LL_INLINE void ref() noexcept
  132. {
  133. if (mPointer)
  134. {
  135. mPointer->ref();
  136. }
  137. }
  138. LL_INLINE void unref()
  139. {
  140. if (mPointer)
  141. {
  142. Type* tempp = mPointer;
  143. mPointer = NULL;
  144. tempp->unref();
  145. if (mPointer != NULL)
  146. {
  147. warnUnreferenceDidAssignment2();
  148. unref();
  149. }
  150. }
  151. }
  152. LL_INLINE void assign(Type* ptr)
  153. {
  154. if (mPointer != ptr)
  155. {
  156. unref();
  157. mPointer = ptr;
  158. ref();
  159. }
  160. }
  161. LL_INLINE static Type* nonNull(Type* ptr)
  162. {
  163. return ptr ? ptr : sNullFunc();
  164. }
  165. static Type* sNullFunc()
  166. {
  167. static Type sInstance;
  168. return &sInstance;
  169. }
  170. protected:
  171. Type* mPointer;
  172. };
  173. #endif