add comment
[enigma2.git] / lib / base / smartptr.h
index c89763e37fe98ed8666ee1593de17ea0d0dcd030..6c3dbc2f0f9c6502a8df06e3f13c8caa311fb601 100644 (file)
@@ -3,26 +3,13 @@
 
 #include "object.h"
 #include <stdio.h>
+#include <lib/python/swig.h>
+
+inline void ptrAssert(void *p) { if (!p) *(unsigned long*)0=0; }
 
 template<class T>
 class ePtr
 {
-               /* read doc/iObject about the ePtrHelper */
-       template<class T1>
-       class ePtrHelper
-       {
-               T1 *m_obj;
-       public:
-               inline ePtrHelper(T1 *obj): m_obj(obj)
-               {
-                       m_obj->AddRef();
-               }
-               inline ~ePtrHelper()
-               {
-                       m_obj->Release();
-               }
-               inline T1* operator->() { return m_obj; }
-       };
 protected:
        T *ptr;
 public:
@@ -43,39 +30,165 @@ public:
        }
        ePtr &operator=(T *c)
        {
+               if (c)
+                       c->AddRef();
                if (ptr)
                        ptr->Release();
                ptr=c;
-               if (ptr)
-                       ptr->AddRef();
                return *this;
        }
        
        ePtr &operator=(ePtr<T> &c)
        {
+               if (c.ptr)
+                       c.ptr->AddRef();
                if (ptr)
                        ptr->Release();
                ptr=c.ptr;
+               return *this;
+       }
+       
+       ~ePtr()
+       {
+               if (ptr)
+                       ptr->Release();
+       }
+       
+       T* grabRef() { if (!ptr) return 0; ptr->AddRef(); return ptr; }
+       T* &ptrref() { assert(!ptr); return ptr; }
+       T* operator->() const { ptrAssert(ptr); return ptr; }
+       operator T*() const { return this->ptr; }
+       
+       operator bool() const { return !!this->ptr; }
+};
+
+
+template<class T>
+class eUsePtr
+{
+protected:
+       T *ptr;
+public:
+       T &operator*() { return *ptr; }
+       eUsePtr(): ptr(0)
+       {
+       }
+       eUsePtr(T *c): ptr(c)
+       {
+               if (c)
+               {
+                       c->AddRef();
+                       c->AddUse();
+               }
+       }
+       eUsePtr(const eUsePtr &c)
+       {
+               ptr=c.ptr;
                if (ptr)
+               {
                        ptr->AddRef();
+                       ptr->AddUse();
+               }
+       }
+       eUsePtr &operator=(T *c)
+       {
+               if (c)
+               {
+                       c->AddRef();
+                       c->AddUse();
+               }
+               if (ptr)
+               {
+                       ptr->ReleaseUse();
+                       ptr->Release();
+               }
+               ptr=c;
                return *this;
        }
        
-       ~ePtr()
+       eUsePtr &operator=(eUsePtr<T> &c)
        {
+               if (c.ptr)
+               {
+                       c.ptr->AddRef();
+                       c.ptr->AddUse();
+               }
                if (ptr)
+               {
+                       ptr->ReleaseUse();
                        ptr->Release();
+               }
+               ptr=c.ptr;
+               return *this;
        }
+       
+       ~eUsePtr()
+       {
+               if (ptr)
+               {
+                       ptr->ReleaseUse();
+                       ptr->Release();
+               }
+       }
+       
+       T* grabRef() { if (!ptr) return 0; ptr->AddRef(); ptr->AddUse(); return ptr; }
        T* &ptrref() { assert(!ptr); return ptr; }
-       ePtrHelper<T> operator->() { assert(ptr); return ePtrHelper<T>(ptr); }
+       T* operator->() const { ptrAssert(ptr); return ptr; }
+       operator T*() const { return this->ptr; }
+};
+
+
+
+#ifndef SWIG
+template<class T>
+class eMutablePtr: public ePtr<T>
+{
+               /* read doc/iObject about the ePtrHelper */
+       template<class T1>
+       class ePtrHelper
+       {
+               T1 *m_obj;
+       public:
+               inline ePtrHelper(T1 *obj): m_obj(obj)
+               {
+                       m_obj->AddRef();
+               }
+               inline ~ePtrHelper()
+               {
+                       m_obj->Release();
+               }
+               inline T1* operator->() { return m_obj; }
+       };
+protected:
+       T *ptr;
+public:
+       eMutablePtr(): ePtr<T>(0)
+       {
+       }
+       
+       eMutablePtr(T *c): ePtr<T>(c)
+       {
+       }
+
+       eMutablePtr(const eMutablePtr &c): ePtr<T>(c)
+       {
+       }
+       
+       eMutablePtr &operator=(T *c)
+       {
+               ePtr<T>::operator=(c);
+               return *this;
+       }
+       
+       
+       ePtrHelper<T> operator->() { ptrAssert(ptr); return ePtrHelper<T>(ptr); }
 
                        /* for const objects, we don't need the helper, as they can't */
                        /* be changed outside the program flow. at least this is */
                        /* what the compiler assumes, so in case you're using const */
-                       /* ePtrs note that they have to be const. */
-       const T* operator->() const { assert(ptr); return ptr; }
-       operator T*() const { return this->ptr; }
+                       /* eMutablePtrs note that they have to be const. */
+       const T* operator->() const { ptrAssert(ptr); return ptr; }
 };
-
+#endif
 
 #endif