lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
com_ptr.h
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