00001
00002
00003
00004
00005 #ifndef DYNOBJ_HOLDER_HPP
00006 #define DYNOBJ_HOLDER_HPP
00007
00009
00010
00011
00012
00013
00014
00015
00016 #include "DoBase.hpp"
00017 #ifndef DOH_SKIP_NEW_ABILITY
00018 #include "DoNew.h"
00019 #endif
00020
00021
00022 #if DO_USE_RUNTIME==1 && defined(DO_MAIN)
00023
00024 #ifndef DO_USE_NOTIFIER
00025 #define DO_USE_NOTIFIER 1
00026 #endif
00027 #endif
00028
00029 #if DO_USE_NOTIFIER==1
00030 #include "DoNotifier.hpp"
00031 #endif
00032
00042 enum HoldMode { hmOwn=1, hmShared, hmStatic, hmWeakRef, hmAutoOwn, hmAutoNoOwn, hmAuto };
00043
00044
00057 template <class T>
00058 struct DynObjHolder {
00059 #if DO_USE_RUNTIME==1 && !defined(DOH_SKIP_NEW_ABILITY)
00060
00063 DynObjHolder( ) : m_pdo(0) {
00064 m_pdo = do_new<T>( );
00065 m_mode = hmAutoOwn;
00066 }
00067
00073 template<class A>
00074 DynObjHolder( A arg ) {
00075 m_pdo = do_new<T>( arg );
00076 m_mode = hmAutoOwn;
00077 }
00078 #endif // DO_USE_RUNTIME==1 && !DOH_SKIP_NEW_ABILITY
00079
00083 DynObjHolder( T *pdo, HoldMode mode ) : m_pdo(NULL), m_mode(mode) {
00084 Assign( pdo, mode );
00085 }
00086
00092 DynObjHolder& Assign( T *pdo, HoldMode mode ){
00093
00094 if( pdo && (m_pdo==pdo
00095 #if DO_USE_NOTIFIER==1
00096 || (m_mode==hmWeakRef && m_pwr && m_pwr->Get()==pdo)
00097 #endif
00098 ))
00099 return *this;
00100
00101 Release( );
00102 if( !pdo ){
00103
00104 if( m_mode!=hmWeakRef ) m_pdo = NULL;
00105 #if DO_USE_NOTIFIER==1
00106 else if(m_pwr) m_pwr->Reset(NULL);
00107 #endif
00108
00109 if( m_mode==hmWeakRef && mode!=hmWeakRef ){
00110 #if DO_USE_NOTIFIER==1
00111 delete m_pwr;
00112 m_pwr = NULL;
00113 #endif
00114 }
00115 m_mode = mode;
00116 return *this;
00117 }
00118
00119
00120 if( mode==hmAuto ){
00121 if( doIsStatic(pdo) )
00122 mode = hmStatic;
00123 else if( pdo->CanBeA(NOTIFIERI_TYPE_ID) )
00124 mode = hmWeakRef;
00125 else
00126 mode = hmAutoOwn;
00127 }
00128
00129 HoldMode old_mode = m_mode;
00130 #if DO_USE_NOTIFIER==1
00131
00132 WeakRef<T> *old_pwr = old_mode==hmWeakRef ? m_pwr : NULL;
00133 #endif
00134
00135 m_mode = mode;
00136 m_pdo = pdo;
00137 if( mode==hmOwn || mode==hmAutoOwn || mode==hmShared ){
00138
00139 if( !pdo->CanBeA(DYNOBJ_TYPE_ID) ){
00140 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, Request to store owning reference, but no DynObj interface available", pdo );
00141 goto Assign_Return_Failed;
00142 }
00143 #if DO_USE_DYNSHARED==1
00144 if( mode==hmShared || (mode==hmAutoOwn && pdo->CanBeA(DYNSHAREDI_TYPE_ID)) ){
00145
00146 m_mode = hmShared;
00147 DynSharedI *psi = do_cast<DynSharedI*>(pdo);
00148 if( psi )
00149 psi->doAddRef();
00150 else{
00151 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, Request to store hold as shared object, no DynSharedI available", pdo );
00152 goto Assign_Return_Failed;
00153 }
00154 }
00155 else
00156 #endif // DO_USE_DYNSHARED==1
00157 {
00158
00159 m_mode = hmOwn;
00160 if( pdo->CanBeA(DYNSHAREDI_TYPE_ID) || doIsStatic(pdo) ){
00161 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, Request for single point ownership, but object is shared (or static), no DynSharedI available", pdo );
00162 goto Assign_Return_Failed;
00163 }
00164 }
00165 }
00166
00167 else if( mode==hmStatic ){
00168 if( !doIsStatic(pdo) ){
00169 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, Request for static holding, but object type is not static", pdo );
00170 goto Assign_Return_Failed;
00171 }
00172 }
00173
00174 else if( mode==hmWeakRef || mode==hmAutoNoOwn ){
00175 if( mode==hmAutoNoOwn && doIsStatic(pdo) ){
00176 m_mode = hmStatic;
00177 }
00178 else {
00179 #if DO_USE_NOTIFIER==1
00180
00181 m_mode = hmWeakRef;
00182 if( !pdo->CanBeA(NOTIFIERI_TYPE_ID) ){
00183 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, hmWeakRef - Object does not support NotifierI", pdo );
00184 goto Assign_Return_Failed;
00185 }
00186
00187 if( old_pwr ){
00188 m_pwr = old_pwr;
00189 m_pwr->Reset(pdo);
00190 }
00191 else
00192 m_pwr = new WeakRef<T>(pdo);
00193 #else
00194 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, hmWeakRef - Weak ref not supported in build", pdo );
00195 goto Assign_Return_Failed;
00196 #endif
00197 }
00198 }
00199 else{
00200 DO_LOG_ERR1( DOERR_CLASS_DYNOBJHOLDER, "DynObjHolder<T>, Unknown holding mode", mode );
00201 goto Assign_Return_Failed;
00202 }
00203
00204
00205 return *this;
00206
00207 Assign_Return_Failed:
00208 #if DO_USE_NOTIFIER==1
00209 if( m_mode!=hmWeakRef ){
00210 m_pdo = NULL;
00211 delete old_pwr;
00212 }
00213 else{
00214 m_pwr = old_pwr;
00215 if(m_pwr) m_pwr->Reset(NULL);
00216 }
00217 #else
00218 m_pdo = NULL;
00219 #endif
00220 return *this;
00221 }
00222
00223 ~DynObjHolder(){
00224 Release( );
00225 #if DO_USE_NOTIFIER==1
00226 if( m_mode==hmWeakRef )
00227 delete m_pwr;
00228 #endif
00229 }
00230
00232 T *Get() const {
00233 if( m_mode!=hmWeakRef )
00234 return m_pdo;
00235 else{
00236 #if DO_USE_NOTIFIER==1
00237 return m_pwr ? m_pwr->Get() : NULL;
00238 #else
00239 assert(0);
00240 return NULL;
00241 #endif
00242 }
00243 }
00244
00246 T &operator()() const { return *Get(); }
00247 T& operator*() const { return *Get(); }
00248
00250 T *operator->() const { return Get(); }
00251
00253 bool operator !() const { return !IsOk(); }
00254
00256 DynObjHolder& operator = (T *pdo){
00257 return Assign( pdo, m_mode );
00258 }
00259
00261 bool IsOk() const {
00262 if( m_mode!=hmWeakRef )
00263 return m_pdo!=NULL;
00264 else{
00265 #if DO_USE_NOTIFIER==1
00266 return m_pwr && m_pwr->Get()!=NULL;
00267 #else
00268 return false;
00269 #endif
00270 }
00271 }
00272
00274 void Release() {
00275 switch(m_mode){
00276 case hmOwn:
00277 case hmShared:
00278 case hmAutoOwn: doReleaseDestroy( (DynObj*)m_pdo ); m_pdo=NULL; break;
00279 case hmStatic: m_pdo=NULL; break;
00280 case hmWeakRef:
00281 #if DO_USE_NOTIFIER==1
00282 m_pwr->Reset( NULL );
00283 #endif
00284 break;
00285 }
00286 }
00287
00288 protected:
00289 union {
00290 T *m_pdo;
00291 #if DO_USE_NOTIFIER==1
00292 WeakRef<T> *m_pwr;
00293 #endif
00294 };
00295 HoldMode m_mode;
00296 };
00297
00298 #define DOH DynObjHolder // Convenience macro
00299
00300 #ifdef TYPEOF_H
00301 #undef TYPE_REG_FILE
00302 #define TYPE_REG_FILE 500
00303 TYPE_REG_T1(DynObjHolder)
00304 #endif
00305
00306 #endif // DYNOBJ_HOLDER_HPP
00307