00001 #ifndef DYNWEAKREF_HPP
00002 #define DYNWEAKREF_HPP
00003
00004
00005 #include "DynObj.h"
00006 #include "DoError.h"
00007 #include "RefCount.h"
00008 #include "DORT.h"
00009 #include "DortInternal.h"
00010 #include "DoBase.hpp"
00011
00012
00017 template<class T>
00018 struct DynWeakRef : public NotifiableI {
00020 explicit DynWeakRef( ) : m_pt(0) { }
00024 explicit DynWeakRef( T* pt ) : m_pt(0) {
00025 InternalAssign(pt);
00026 }
00030 explicit DynWeakRef( DynWeakRef& dop ) : m_pt(0) {
00031 InternalAssign(dop);
00032 }
00033 ~DynWeakRef(){
00034 InternalRelease();
00035 }
00036
00039 DynWeakRef& operator = (T* pt){
00040 InternalRelease();
00041 InternalAssign(pt);
00042 return *this;
00043 }
00046 DynWeakRef& operator = (DynWeakRef<T>& dop){
00047 return operator = (dop.Get());
00048 }
00049
00052 DynWeakRef& Assign( T* pt ){
00053 InternalRelease();
00054 bool r = InternalAssign( pt );
00055 return *this;
00056 }
00057
00058
00060 operator T* () { return m_pt; }
00062 operator T& () { return *m_pt; }
00064 T& operator * () { return *m_pt; }
00066 T* operator -> () { return m_pt; }
00068 T* Get() { return m_pt; }
00069
00071 bool IsOk(){ return m_pt!=NULL; }
00072
00074 bool Release(){ T*pt=m_pt; InternalRelease(); return pt && !m_pt; }
00075
00076 protected:
00077
00078 bool InternalAssign( T* pt ){
00079 DO_ASSERT_MSG(!m_pt,"T* m_pt should be NULL");
00080 if( !pt ) return true;
00081
00082 typename VBaseSelect<T>::type *pt1 = (typename VBaseSelect<T>::type*)pt;
00083 DO_ASSERT_MSG( ((void*)pt)==((void*)pt1), "VBaseSelect<T>::type should keep ptr representation" );
00084 DynObjType *pdt = ::doGetType( pt1 );
00085 if( !pdt ) return false;
00086
00087
00088 NotifierI *pni = DoCasterSelect<T,NotifierI,DoIsTypeA<T,NotifierI>::v>::Cast(pt,pdt);
00089 if( pni ){
00090 if( !pni->AddNotifiable(this,NOT_EVT_DTOR) )
00091 return false;
00092 m_pt = pt;
00093 return true;
00094 }
00095 else return false;
00096 }
00097
00098 void InternalRelease(){
00099 if( !m_pt ) return;
00100
00101
00102 DynObjType *pdt = ::doGetType( (typename VBaseSelect<T>::type*)m_pt );
00103 NotifierI *pni = DoCasterSelect<T,NotifierI,DoIsTypeA<T,NotifierI>::v>::Cast(m_pt,pdt);
00104 if( !pni ) return;
00105
00106 bool r = pni->RemoveNotifiable(this,NOT_EVT_DTOR);
00107 DO_ASSERT_MSG(r,"Should succeed removing NotifiableI");
00108 m_pt = NULL;
00109 }
00110
00111
00112 virtual bool docall OnNotify( NotifierI *pni, int evt, NotifDataI *pnd ){
00113 DO_ASSERT_MSG(m_pt,"Should have tracked object");
00114 m_pt = NULL;
00115 return true;
00116 }
00117
00118 T* m_pt;
00119 };
00120
00121 #endif // DYNWEAKREF_HPP