lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
00001 /*****************************************************/ 00002 /* lean Smart (c) Tobias Zirr 2011 */ 00003 /*****************************************************/ 00004 00005 #ifndef LEAN_SMART_COM_PTR 00006 #define LEAN_SMART_COM_PTR 00007 00008 #include "../lean.h" 00009 #include "../meta/dependent_false.h" 00010 00011 namespace lean 00012 { 00013 namespace smart 00014 { 00015 00017 template <class COMType> 00018 LEAN_INLINE void acquire_com(COMType &object) 00019 { 00020 object.AddRef(); 00021 } 00023 template <class COMType> 00024 LEAN_INLINE void release_com(COMType *object) 00025 { 00026 if (object) 00027 object->Release(); 00028 } 00029 00031 template <class COMType, bool Critical = false> 00032 class com_ptr 00033 { 00034 private: 00035 COMType *m_object; 00036 00038 static COMType* acquire(COMType *object) 00039 { 00040 if (object) 00041 acquire_com(*object); 00042 00043 return object; 00044 } 00045 00047 static void release(COMType *object) 00048 { 00049 release_com(object); 00050 } 00051 00052 public: 00054 typedef COMType com_type; 00056 typedef COMType* value_type; 00057 00059 com_ptr(com_type *object = nullptr) 00060 : m_object( acquire(object) ) { }; 00062 template <class COMType2> 00063 com_ptr(COMType2 *object) 00064 : m_object( acquire(object) ) { }; 00065 00067 enum bind_reference_t 00068 { 00069 bind_reference 00070 }; 00072 com_ptr(COMType *object, bind_reference_t) 00073 : m_object(object) { }; 00074 00076 com_ptr(const com_ptr &right) 00077 : m_object( acquire(right.m_object) ) { }; 00079 template <class COMType2, bool Critical2> 00080 com_ptr(const com_ptr<COMType2, Critical2> &right) 00081 : m_object( acquire(right.get()) ) { }; 00082 00083 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00084 00085 template <class COMType2, bool Critical2> 00086 com_ptr(com_ptr<COMType2, Critical2> &&right) 00087 : m_object(right.unbind()) { } 00088 #endif 00089 00091 ~com_ptr() throw() 00092 { 00093 release(m_object); 00094 } 00095 00097 static LEAN_INLINE com_ptr<com_type, true> bind(com_type *object) 00098 { 00099 return com_ptr<com_type, true>(object, com_ptr<com_type, true>::bind_reference); 00100 } 00102 LEAN_INLINE com_type* unbind() 00103 { 00104 COMType *preObject = m_object; 00105 m_object = nullptr; 00106 return preObject; 00107 } 00109 LEAN_INLINE com_ptr<com_type, true> transfer() 00110 { 00111 // Visual C++ won't inline delegating function calls 00112 return com_ptr<com_type, true>(unbind(), com_ptr<com_type, true>::bind_reference); 00113 } 00114 00116 com_ptr& operator =(com_type *object) 00117 { 00118 // Do not check for redundant assignment 00119 // -> The code handles redundant assignment just fine 00120 // -> Checking generates up to twice the code due to unfortunate compiler optimization application order 00121 COMType *prevObject = m_object; 00122 m_object = acquire(object); 00123 release(prevObject); 00124 00125 return *this; 00126 } 00127 00129 com_ptr& operator =(const com_ptr &right) 00130 { 00131 return (*this = right.m_object); 00132 } 00134 template <class COMType2, bool Critical2> 00135 com_ptr& operator =(const com_ptr<COMType2, Critical2> &right) 00136 { 00137 return (*this = right.get()); 00138 } 00139 00140 #ifndef LEAN0X_NO_RVALUE_REFERENCES 00141 00142 template <class COMType2, bool Critical2> 00143 com_ptr& operator =(com_ptr<COMType2, Critical2> &&right) 00144 { 00145 // Self-assignment would be wrong 00146 if (right.get() != m_object) 00147 { 00148 COMType *prevObject = m_object; 00149 m_object = right.unbind(); 00150 release(prevObject); 00151 } 00152 00153 return *this; 00154 } 00155 #endif 00156 00158 LEAN_INLINE com_type*const& get(void) const { return m_object; }; 00159 00161 LEAN_INLINE com_type& operator *() const { return *get(); }; 00163 LEAN_INLINE com_type* operator ->() const { return get(); }; 00164 00166 LEAN_INLINE operator com_type*() const 00167 { 00168 LEAN_STATIC_ASSERT_MSG_ALT(!Critical, 00169 "Cannot implicitly cast critical reference, use unbind() for (insecure) storage.", 00170 Cannot_implicitly_cast_critical_reference__use_unbind_for_insecure_storage); 00171 return get(); 00172 }; 00173 00176 LEAN_INLINE com_type** rebind() 00177 { 00178 *this = nullptr; 00179 return &m_object; 00180 } 00181 }; 00182 00184 template <class COMType> 00185 LEAN_INLINE com_ptr<COMType, true> bind_com(COMType *object) 00186 { 00187 // Visual C++ won't inline delegating function calls 00188 return com_ptr<COMType, true>(object, com_ptr<COMType, true>::bind_reference); 00189 } 00190 00191 } // namespace 00192 00193 using smart::com_ptr; 00194 00195 using smart::bind_com; 00196 00197 } // namespace 00198 00199 #endif