00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 #ifndef COH_MEMBER_HANDLE_HPP
00017 #define COH_MEMBER_HANDLE_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/Object.hpp"
00022 #include "coherence/lang/SmartMember.hpp"
00023 #include "coherence/lang/SynchronizedMemberReadBlock.hpp"
00024 #include "coherence/lang/SynchronizedMemberWriteBlock.hpp"
00025 #include "coherence/lang/TypedHandle.hpp"
00026 
00027 #include <ostream>
00028 #include <sstream>
00029 
00030 COH_OPEN_NAMESPACE2(coherence,lang)
00031 
00032 template<class> class MemberView;
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 template<class T>
00056 class MemberHandle
00057     : public SmartMember
00058     {
00059     
00060 
00061     public:
00062 
00063 
00064 
00065         typedef T ValueType;
00066 
00067 
00068 
00069 
00070         typedef typename T::Handle ValueHandle;
00071 
00072 
00073 
00074 
00075         typedef typename T::View ValueView;
00076 
00077 
00078 
00079 
00080         typedef ValueHandle GetType;
00081 
00082 
00083 
00084 
00085         typedef ValueView ConstGetType;
00086 
00087 
00088     
00089 
00090     public:
00091 
00092 
00093 
00094 
00095 
00096         MemberHandle(const Object& oGuardian)
00097             : SmartMember(oGuardian), m_po(NULL)
00098             {
00099             }
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108         MemberHandle(const Object& oGuardian, const ValueHandle& that)
00109             : SmartMember(oGuardian),
00110               m_po(NULL)
00111             {
00112             T* po = get_pointer(that);
00113             if (po != NULL)
00114                 {
00115                 po->_attach(oGuardian._isEscaped());
00116                 m_po = po;
00117                 }
00118             }
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129         MemberHandle(const Object& oGuardian, const ValueHandle& that,
00130                 bool fMutable)
00131             : SmartMember(oGuardian, fMutable ? MUTABLE : SAFE_CONST),
00132               m_po(NULL)
00133             {
00134             T* po = get_pointer(that);
00135             if (po != NULL)
00136                 {
00137                 if (fMutable)
00138                     {
00139                     po->_attach(oGuardian._isEscaped());
00140                     }
00141                 else
00142                     {
00143                     ((const T*) po)->_attach(oGuardian._isEscaped());
00144                     }
00145                 m_po = po;
00146                 }
00147             }
00148 
00149 
00150 
00151 
00152         ~MemberHandle()
00153             {
00154             T*         po          = m_po;
00155             Mutability nMutability = m_nMutability;
00156 
00157             if (NULL != po)
00158                 {
00159                 m_po = NULL;
00160                 try
00161                     {
00162                     bool fEscaped = getGuardian()._isEscaped();
00163                     if (nMutability >= CONST)
00164                         {
00165                         ((const T*) po)->_detach(fEscaped);
00166                         }
00167                     else
00168                         {
00169                         po->_detach(fEscaped);
00170                         }
00171                     }
00172                 catch (const std::exception& e)
00173                     {
00174                     
00175                     std::cerr << "Error during ~MemberHandle: " << e.what() << std::endl;
00176                     return; 
00177                     }
00178                 }
00179             }
00180 
00181     private:
00182 
00183 
00184 
00185         MemberHandle(const MemberHandle&);
00186 
00187 
00188     
00189 
00190     public:
00191 
00192 
00193 
00194 
00195 
00196 
00197 
00198         MemberHandle& operator=(const ValueHandle& that)
00199             {
00200             set(that);
00201             return *this;
00202             }
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212         MemberHandle& operator=(MemberHandle& that)
00213             {
00214             operator=((ValueHandle) that); 
00215             return *this;
00216             }
00217 
00218 
00219 
00220 
00221 
00222 
00223         operator ValueView() const
00224             {
00225             return get();
00226             }
00227 
00228 
00229 
00230 
00231 
00232 
00233         operator ValueHandle()
00234             {
00235             return get();
00236             }
00237 
00238 
00239 
00240 
00241 
00242 
00243         template<class PT>
00244         operator TypedHandle<const PT>() const
00245             {
00246             return get();
00247             }
00248 
00249 
00250 
00251 
00252 
00253 
00254         template<class PT>
00255         operator TypedHandle<PT>()
00256             {
00257             return get();
00258             }
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266         template<class PT>
00267         operator TypedHolder<PT>() const
00268             {
00269             return get();
00270             }
00271 
00272 
00273 
00274 
00275 
00276 
00277         template<class PT>
00278         operator TypedHolder<PT>()
00279             {
00280             return get();
00281             }
00282 
00283 
00284 
00285 
00286 
00287 
00288         ValueView operator->() const
00289             {
00290             return get();
00291             }
00292 
00293 
00294 
00295 
00296 
00297 
00298         ValueHandle operator->()
00299             {
00300             return get();
00301             }
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310         const T& operator*() const
00311             {
00312             return *get();
00313             }
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322         T& operator*()
00323             {
00324             return *get();
00325             }
00326 
00327     private:
00328 
00329 
00330 
00331         MemberHandle<T>& operator=(const MemberHandle<T>&);
00332 
00333 
00334     
00335 
00336     protected:
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345         void set(const TypedHandle<T>& that,
00346                 SynchronizedMemberWriteBlock* pSync = NULL)
00347             {
00348             const Object& oGuardian = getGuardian();
00349             T*            po        = get_pointer(that);
00350             T*            pDetach   = NULL;
00351             bool          fEscaped  = oGuardian._isEscaped();
00352             Object*       pAttach   = po == NULL ? NULL : po->_attach(fEscaped);
00353 
00354             if (pSync != NULL)
00355                 {
00356                 
00357                 SynchronizedMemberWriteBlock syncWrite(oGuardian, pSync);
00358                 if (m_nMutability >= CONST)
00359                     {
00360                     coh_throw_illegal_state("attempt to set const MemberHandle");
00361                     }
00362                 pDetach = m_po;
00363                 m_po    = NULL == pAttach ? NULL : po;
00364                 }
00365             else if (fEscaped)
00366                 {
00367                 
00368                 SynchronizedMemberWriteBlock::Guard guard(oGuardian);
00369                 if (m_nMutability >= CONST)
00370                     {
00371                     coh_throw_illegal_state("attempt to set const MemberHandle");
00372                     }
00373                 pDetach = m_po;
00374                 m_po    = NULL == pAttach ? NULL : po;
00375                 }
00376             else
00377                 {
00378                 if (m_nMutability >= CONST)
00379                     {
00380                     coh_throw_illegal_state("attempt to set const MemberHandle");
00381                     }
00382                 pDetach = m_po;
00383                 m_po    = NULL == pAttach ? NULL : po;
00384                 }
00385 
00386             if (pDetach)
00387                 {
00388                 pDetach->_detach(fEscaped);
00389                 }
00390             }
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400         ValueView get(SynchronizedMemberReadBlock* pSync = NULL) const
00401             {
00402             const Object& oGuardian = getGuardian();
00403             if (pSync != NULL)
00404                 {
00405                 SynchronizedMemberReadBlock syncRead(oGuardian, pSync);
00406                 
00407                 return ValueView((const T*) m_po);
00408                 }
00409             else if (m_nMutability == SAFE_CONST || !oGuardian._isEscaped())
00410                 {
00411                 
00412                 return ValueView((const T*) m_po);
00413                 }
00414             else
00415                 {
00416                 SynchronizedMemberReadBlock::Guard guard(oGuardian);
00417                 
00418                 return ValueView((const T*) m_po);
00419                 }
00420             }
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430         ValueHandle get(SynchronizedMemberReadBlock* pSync = NULL)
00431             {
00432             const Object& oGuardian = getGuardian();
00433             if (pSync != NULL)
00434                 {
00435                 SynchronizedMemberReadBlock syncRead(oGuardian, pSync);
00436                 if (m_nMutability >= CONST)
00437                     {
00438                     coh_throw_illegal_state(
00439                         "attempt to access handle from const MemberHandle");
00440                     }
00441                 return m_po; 
00442                 }
00443             else if (oGuardian._isEscaped())
00444                 {
00445                 SynchronizedMemberReadBlock::Guard guard(oGuardian);
00446                 if (m_nMutability >= CONST)
00447                     {
00448                     coh_throw_illegal_state(
00449                         "attempt to access handle from const MemberHandle");
00450                     }
00451                 return m_po; 
00452                 }
00453 
00454             if (m_nMutability >= CONST)
00455                 {
00456                 coh_throw_illegal_state(
00457                     "attempt to access handle from const MemberHandle");
00458                 }
00459             return m_po;
00460             }
00461 
00462 
00463     
00464 
00465     protected:
00466 
00467 
00468 
00469 
00470 
00471 
00472         virtual void onConst()
00473             {
00474             const Object& oGuardian = getGuardian();
00475             bool          fEscaped  = oGuardian._isEscaped();
00476             T*            po        = NULL;
00477 
00478             if (fEscaped)
00479                 {
00480                 SynchronizedMemberWriteBlock::Guard guard(oGuardian);
00481                 po = m_po;
00482                 }
00483             else
00484                 {
00485                 po = m_po;
00486                 }
00487 
00488             if (NULL != po)
00489                 {
00490                 
00491                 ((const T*) po)->_attach(fEscaped);
00492                 po->_detach(fEscaped);
00493                 }
00494 
00495             SmartMember::onConst();
00496             }
00497 
00498 
00499 
00500 
00501         virtual void onEscape(bool fEscaped) const
00502             {
00503             T* po = m_po;
00504             if (po != NULL)
00505                 {
00506                 if (m_nMutability >= CONST)
00507                     {
00508                     const T* cpo = po;
00509                     cpo->_attach(fEscaped);  
00510                     cpo->_detach(!fEscaped); 
00511                     }
00512                 else
00513                     {
00514                     po->_attach(fEscaped);  
00515                     po->_detach(!fEscaped); 
00516                     }
00517                 }
00518 
00519             SmartMember::onEscape(fEscaped);
00520             }
00521 
00522 
00523     
00524 
00525     protected:
00526 
00527 
00528 
00529         T* m_po;
00530 
00531 
00532     
00533 
00534 
00535 
00536 
00537     template<class D, class H> friend D cast(MemberHandle<T>& mh, bool fThrow);
00538 
00539 
00540 
00541 
00542     friend class SynchronizedMemberReadBlock;
00543 
00544 
00545 
00546 
00547     friend class SynchronizedMemberWriteBlock;
00548     };
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 template<class T> std::ostream& operator<<(std::ostream& out, const MemberHandle<T>& mh)
00563     {
00564     out << (typename T::View) mh;
00565     return out;
00566     }
00567 
00568 
00569 
00570 
00571 
00572 
00573 template<class T> void clear_handle(MemberHandle<T>& mh)
00574     {
00575     mh = NULL;
00576     }
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 template<class T>
00586 bool is_null(const MemberHandle<T>& mh)
00587     {
00588     return mh == NULL;
00589     }
00590 
00591 
00592 
00593 
00594 
00595 
00596 
00597 
00598 
00599 
00600 
00601 
00602 template<class D, class T>
00603 D cast(MemberHandle<T>& mh, bool fThrow = true)
00604     {
00605     return cast<D>((typename MemberHandle<T>::ValueHandle) mh, fThrow);
00606     }
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 template<class D, class T>
00620 D cast(const MemberHandle<T>& mh, bool fThrow = true)
00621     {
00622     return cast<D>((typename MemberHandle<T>::ValueView) mh, fThrow);
00623     }
00624 
00625 
00626 
00627 
00628 
00629 
00630 
00631 
00632 template<class D, class T>
00633 bool instanceof(MemberHandle<T>& mh)
00634     {
00635     return NULL != cast<D>(mh, false);
00636     }
00637 
00638 
00639 
00640 
00641 
00642 
00643 
00644 
00645 template<class D, class T>
00646 bool instanceof(const MemberHandle<T>& mh)
00647     {
00648     return NULL != cast<D>(mh, false);
00649     }
00650 
00651 COH_CLOSE_NAMESPACE2
00652 
00653 #endif // COH_MEMBER_HANDLE_HPP