Main Page   Class Hierarchy   Compound List   File List   Compound Members  

mlinknode.h

00001 #ifndef __LINKNODE_H__
00002 #define __LINKNODE_H__
00003 
00004 #include <magic/mobject.h>
00005 #include <magic/mpararr.h>
00006 
00007 
00008 typedef unsigned int Word;
00009 typedef unsigned int DWord;
00010 
00011 typedef Word    LnNdCnncnType ;
00012 
00013 typedef Word    StsLnNd ;
00014 typedef DWord   StsLnNB ;
00015 
00016 
00017 
00019 //                 |     o       |   |   |          |                       //
00020 //                 |         _   |   |\  |          |  ___                  //
00021 //                 |     | |/ \  | / | \ |  __   ---| /   )                 //
00022 //                 |     | |   | |/  |  \| /  \ (   | |---                  //
00023 //                 |____ | |   | | \ |   | \__/  ---|  \__                  //
00025 
00028 class LinkNode {
00029   public:
00030 
00033     struct NodeLink { // Was LnNdCnncnType;
00034         LinkNode        *node ;
00035         LnNdCnncnType   state ;
00036         char            data [0] ;
00037     };
00038 
00041     class NodeLinkArray : public PackArray<NodeLink> {
00042       public:
00043         NodeLinkArray   (IndVect sizeData = 0) : VectGrow (sizeof (NodeLink) + sizeData)    { }
00044         
00046         virtual IndLnNd     getGrow         (IndLnNd minSize = 1) const ;
00047         
00049         IndLnNd             find            (LinkNode const &node) const                { return find (&node) ; }
00050         IndLnNd             find            (LinkNode const *node) const ;
00051     };
00052 
00053   public:
00054 
00055     LinkNode (IndVect sizeData = 0) ;
00056     
00057     virtual     ~LinkNode () ;
00058     
00063     StsLnNB connect (LinkNode const &other) ;
00064     StsLnNB connect (LinkNode const *other)             { return (other ? connect (*other) : M_stsLnNdThis (N_StsLnNd_Error | N_StsLnNd_InvalidRef)) ; }
00065 
00070     StsLnNd reserve (LinkNode const &other) ;
00071     StsLnNd reserve (LinkNode const *other)             { return (other ? reserve (*other) : N_StsLnNd_Error | N_StsLnNd_InvalidRef) ; }
00072 
00076     StsLnNd release (IndLnNd iOther) ;
00077     StsLnNd release (LinkNode const &other) ;
00078     StsLnNd release (LinkNode const *other)             { return (other ? release (*other) : N_StsLnNd_Error | N_StsLnNd_InvalidRef) ; }
00079 
00081     StsLnNd disconnect (LinkNode const &other, IndLnNd iOther) ;
00082     StsLnNd disconnect (LinkNode const &other) ;
00083     StsLnNd disconnect (LinkNode const *other)          { return (other ? disconnect (*other) : N_StsLnNd_Error | N_StsLnNd_InvalidRef) ; }
00084 
00086     void    disconnectAll () ;
00087 
00089     void    releaseAll () ;
00090 
00092     Bool    isConnected (IndLnNd iOther) const          { return (*this) [iOther].state & N_NodeLinkStt_Connected ; }
00093     Bool    isConnected (LinkNode const &other) const ;
00094 
00096     Bool    isConnected (ClassName clsName) const ;
00097     Bool    isReservedBy (IndLnNd iOther) const         { return (*this) [iOther].state & N_NodeLinkStt_ReservedBy ; }
00098     Bool    isReservedBy (LinkNode const &other) const ;
00099     Bool    isConnected () const ;
00100     Bool    isReserved () const ;
00101     Bool    hasReserved () const ;
00102 
00107     void    addProtect ()                               { VERIFY (++mProtected != 0) ; }
00108 
00112     void    removeProtect () ;
00113 
00115     NodeLink const  *iterConnection (LinkNodeIndex &i) const    { return (i < items () ? itemNT (i) : NULL) ; }
00116     NodeLink const  *iterChanged (IndLnNd &i) const ;
00117     NodeLink const  *iterConnected (IndLnNd &i) const ;
00118     NodeLink const  *iterReserved (IndLnNd &i) const ;
00119     NodeLink const  *iterReserver (IndLnNd &i) const ;
00120 
00124     NodeLink const  *findConnection (LinkNode const &item) const        { IndLnNd i = find (item) ; return (i != N_IndLnNd_Invalid ? &((*this) [i]) : NULL) ; }
00125 
00126     void const  *findConnected (ClassName clsName) const                { IndLnNd i = 0 ; return iterConnected (i, clsName) ; }
00127     void const  *iterConnected (IndLnNd &i, ClassName clsName) const ;
00128     
00129     NodeLinkArray const &connections () const           { return *this ; }
00130     NodeLinkType        gChgCnncn () const              { return mChgCnncn ; }
00131     unsigned int        gProtected () const             { return mProtected ; }
00132     NodeLink const      *gLastChanged () const          { return mLastChanged ; }
00133 
00138     virtual CPtr    getHost (ClassName className) const { return (className ? castClsF (className) : clsName ()) ; }
00139     
00140     Bool    mNotifyConnection ;
00141 
00142   protected:
00143     StsLnNd removeProtect (StsLnNd ret)                 { removeProtect () ; return ret ; }
00144     StsLnNB removeProtect (StsLnNB ret)                 { removeProtect () ; return ret ; }
00145     
00146   private: // Methods
00147     StsLnNd setConnected (LinkNode const &other) ;
00148     StsLnNd setDisconnected (IndLnNd other) ;
00149     StsLnNd setDisconnected (LinkNode const &other)     { return setDisconnected (find (other)) ; }
00150     StsLnNd setConnectedAnd (LinkNode const &other, NodeLinkType status, NodeLinkType chg) ;
00151     void    setReleasedBy (IndLnNd other) ;
00152     void    setReleasedBy (LinkNode const &other)       { setReleasedBy (find (other)) ; }
00153 
00154     void    sendNotifys () ;
00155     Bool    purgeDisconnectedConnections () ;           // N_true if purged
00156     
00157     void    connectionChanged (NodeLink const *cnn, NodeLinkType chg)   { mChgCnncn |= chg ; mLastChanged = (mLastChanged ? (NodeLink *) -1 : cnn) ; }
00158 
00160     virtual void    notifyBeginNotify (NodeLinkType changed)    { }
00161     
00170     virtual void    notifyConnection (NodeLinkType chg, NodeLink const *cnncn)  { }
00171 
00173     virtual void    notifyNotifiedAndPurged (NodeLinkType chg)  { }
00174 
00175   private: // Attributes
00176     
00177     NodeLinkArray mNodeLinks;
00178     
00179     NodeLinkType    mChgCnncn ;
00180 
00184     unsigned int    mProtected ;
00185 
00189     NodeLink const  *mLastChanged ;
00190 };
00191 
00192 inline VERIFY_stsLnNdIsOK (StsLnNd sts) {
00193     ASSERT (stsLnNdIsOK (sts)) ;
00194     return sts ;
00195 }
00196 
00197 inline VERIFY_not_stsLnNdIsError (StsLnNd sts) {
00198     ASSERT (!stsLnNdIsError (sts)) ;
00199     return sts ;
00200 }
00201 
00202 inline VERIFY_stsLnNdIsOK (StsLnNB sts) {
00203     ASSERT (stsLnNdIsOK (sts)) ;
00204     return sts ;
00205 }
00206 
00207 inline VERIFY_not_stsLnNdIsError (StsLnNB sts) {
00208     ASSERT (!stsLnNdIsError (sts)) ;
00209     return sts ;
00210 }
00211 
00212 #if defined (_DEBUG)
00213     void trace (LinkNode const &ob, IndVect indent = 0, NodeLinkType show1 = N_NodeLinkStt_Connected) ;
00214 #endif  // defined (_DEBUG)
00215 
00216 #ifdef __STRING_H__
00217     String& links2Str (String& ret, LinkNode const &ob) ;
00218 #endif  // __STRING_H__
00219 
00220 
00221 inline Bool stsLnNdIsOK (StsLnNd sts)       { return !(sts & (N_StsLnNd_Warning | N_StsLnNd_Error)) ; }
00222 inline Bool stsLnNdIsError (StsLnNd sts)    { return !!(sts & N_StsLnNd_Error) ; }
00223 inline Bool stsLnNdIsWarning (StsLnNd sts)  { return !!(sts & N_StsLnNd_Warning) ; }
00224 
00225 #define M_stsLnNdThis(sts)                  ((StsLnNB) (StsLnNd) sts)
00226 #define M_stsLnNdOther(sts)                 (((StsLnNB) sts) << 16)
00227 
00228 inline Bool stsLnNdIsOK (StsLnNB sts)       { return !(sts & (M_stsLnNdThis (N_StsLnNd_Error | N_StsLnNd_Warning) | M_stsLnNdOther (N_StsLnNd_Error | N_StsLnNd_Warning))) ; }
00229 inline Bool stsLnNdIsError (StsLnNB sts)    { return !!(sts & (M_stsLnNdThis (N_StsLnNd_Error) | M_stsLnNdOther (N_StsLnNd_Error))); }
00230 inline Bool stsLnNdIsWarning (StsLnNB sts)  { return !!(sts & (M_stsLnNdThis (N_StsLnNd_Warning) | M_stsLnNdOther (N_StsLnNd_Warning))) ; }
00231 
00232 inline StsLnNd  stsLnNdThis (StsLnNB sts)                   { return (StsLnNd) sts ; }
00233 inline StsLnNd  stsLnNdOther (StsLnNB sts)                  { return (StsLnNd) (sts >> 16) ; }
00234 inline StsLnNB  stsLnNdThis (StsLnNd sts)                   { return M_stsLnNdThis(sts) ; }
00235 inline StsLnNB  stsLnNdOther (StsLnNd sts)                  { return M_stsLnNdOther(sts) ; }
00236 inline StsLnNB  stsLnNd (StsLnNd stsThis, StsLnNd stsOther) { return stsLnNdThis (stsThis) | stsLnNdOther (stsOther) ; }
00237 inline StsLnNB  stsLnNdSwapThisAndOther (StsLnNB sts)       { return stsLnNd (stsLnNdOther (sts), stsLnNdThis (sts)) ; }
00238 
00239 
00240 // typedef IndVect              IndLnNd ;
00241 // #define N_IndLnNd_Invalid    N_IndVect_Invalid
00242 
00243 inline LinkNode *node (NodeLink const *cnn) { return (cnn ? cnn->node : NULL) ; }
00244 
00245 #define N_LnNdCnncnStt_Connected        0x0001
00246 #define N_LnNdCnncnStt_ReservedBy       0x0002  /* This node is reserved by LnNdCnncn::node. */
00247 #define N_LnNdCnncnStt_Reserve          0x0004  /* This node reserves LnNdCnncn::node. */
00248 #define N_LnNdCnncnStt_FlagA            0x0010
00249 #define N_LnNdCnncnStt_FlagB            0x0020
00250 #define N_LnNdCnncnStt_FlagC            0x0040
00251 #define N_LnNdCnncnStt_FlagD            0x0080
00252 #define N_LnNdCnncnStt_ChgReserve       0x0100
00253 #define N_LnNdCnncnStt_ChgRelease       0x0200
00254 #define N_LnNdCnncnStt_ChgReservedBy    0x0400
00255 #define N_LnNdCnncnStt_ChgReleasedBy    0x0800
00256 #define N_LnNdCnncnStt_ChgInvalidRef    0x2000
00257 #define N_LnNdCnncnStt_ChgConnected     0x4000
00258 #define N_LnNdCnncnStt_ChgDisconnected  0x8000
00259 #define N_LnNdCnncnStt_Chg_             0xef00
00260 #define N_LnNdCnncnStt_                 0xeff7
00261 
00262 #define N_StsLnNd_OK                0x0000
00263 #define N_StsLnNd_Warning           0x1000
00264 #define N_StsLnNd_Error             0x2000
00265 #define N_StsLnNd_AlreadyDone       0x0001
00266 #define N_StsLnNd_NoSuchLnNd        0x0002
00267 #define N_StsLnNd_InvalidRef        0x0004
00268 #define N_StsLnNd_Linked            0x0008
00269 #define N_StsLnNd_ReleasedBy        0x0010
00270 #define N_StsLnNd_Release           0x0020
00271 #define N_StsLnNd_                 (0x0007 | N_StsLnNd_OK | N_StsLnNd_Warning | N_StsLnNd_Error)
00272 
00273 
00275 //      ---           | o     |     o       |   |   |          |            //
00276 //       |    _       |       |         _   |   |\  |          |  ___       //
00277 //       |  |/ \   ---| | |/\ |     | |/ \  | / | \ |  __   ---| /   )      //
00278 //       |  |   | (   | | |   |     | |   | |/  |  \| /  \ (   | |---       //
00279 //      _|_ |   |  ---| | |   |____ | |   | | \ |   | \__/  ---|  \__       //
00281 
00286 template <class T>
00287 class IndirLinkNode : public LinkNode {
00288   public:
00289     typedef CPtr    (T::*FGetHost) (ClassName) const ; 
00290     typedef void    (T::*FNfyBegN) (NodeLinkType) ;
00291     typedef void    (T::*FNfyNfPg) (NodeLinkType) ;
00292     typedef void    (T::*FNfyCnn) (NodeLinkType chg, NodeLink const *) ;
00293     
00294                     IndirLinkNode () : mFunc_notifyConnection (NULL), mFunc_notifyBeginNotify (NULL), mFunc_notifyNotifiedAndPurged (NULL), mFunc_getHost (NULL)    { }
00295 
00297     void            setOwner                        (T &owner)          { mOwner = &owner ; }
00298 
00300     T*              gOwner () const                                     { return mOwner ; }
00301 
00306     virtual CPtr    getHost (ClassName clsName) const           { return (clsName ? (mFunc_getHost ? (mOwner->*mFunc_getHost) (clsName) : mOwner->castClsF (clsName)) : mOwner->clsName ()) ; }
00307 
00308     FGetHost        setFunc_getOwner                (FGetHost func)     { FGetHost ret = mFunc_getHost ; mFunc_getHost = func ; return ret ; }
00309     FNfyBegN        setFunc_notifyBeginNotify       (FNfyBegN func)     { FNfyBegN ret = mFunc_notifyBeginNotify ; mFunc_notifyBeginNotify = func ; return ret ; }
00310     FNfyNfPg        setFunc_notifyNotifiedAndPurged (FNfyNfPg func)     { FNfyNfPg ret = mFunc_notifyNotifiedAndPurged ; mFunc_notifyNotifiedAndPurged = func ; return ret ; }
00311     FNfyCnn         setFunc_notifyConnection        (FNfyCnn func)      { FNfyCnn ret = mFunc_notifyConnection ; mFunc_notifyConnection = func ; if (mFunc_notifyConnection) mNotifyConnection = N_true ; return ret ; }
00312 
00314     void            set (T &client, FGetHost func1, FNfyNfPg func2, FNfyBegN func4, FNfyCnn func3) ;
00315 
00316   private:
00317     virtual void    notifyBeginNotify (NodeLinkType changed)                        { if (mFunc_notifyBeginNotify) (mClient->*mFunc_notifyBeginNotify) (changed) ; }
00318     virtual void    notifyConnection (NodeLinkType chg, NodeLink const *cnncn)  { if (mFunc_notifyConnection) (mClient->*mFunc_notifyConnection) (chg, cnncn) ; }
00319     virtual void    notifyNotifiedAndPurged (NodeLinkType chg)                      { if (mFunc_notifyNotifiedAndPurged) (mClient->*mFunc_notifyNotifiedAndPurged) (chg) ; }
00320 
00322     T   *mOwner ;
00323     
00324     FNfyCnn     mFunc_notifyConnection ;
00325     FNfyBegN    mFunc_notifyBeginNotify ;
00326     FNfyNfPg    mFunc_notifyNotifiedAndPurged ;
00327     FGetHost    mFunc_getHost ;
00328 };
00329 
00330 template <class T>
00331 void    IndirLinkNode<T>::set (T &client, FGetHost func1, FNfyNfPg func2, FNfyBegN func4, FNfyCnn func3) {
00332     mClient = &client ;
00333     mFunc_getHost = func1 ;
00334     mFunc_notifyNotifiedAndPurged = func2 ;
00335     mFunc_notifyBeginNotify = func4 ;
00336     mFunc_notifyConnection = func3 ;
00337     if (mFunc_notifyConnection)
00338         mNotifyConnection = N_true ;
00339 }
00340 
00341 
00342 
00344 //  ----                                  | |     o       |   |   |          |       |   |          o           //
00345 // (            ____  --   ___    _       | |         _   |   |\  |          |  ___  |\  |       |     __       //
00346 //  ---  |   | (     |  ) /   ) |/ \   ---| |     | |/ \  | / | \ |  __   ---| /   ) | \ |  __  -+- | /   \   | //
00347 //     ) |   |  \__  |--  |---  |   | (   | |     | |   | |/  |  \| /  \ (   | |---  |  \| /  \  |  | +--  \  | //
00348 // ___/   \__! ____) |     \__  |   |  ---| |____ | |   | | \ |   | \__/  ---|  \__  |   | \__/   \ | |     \_/ //
00349 //                                                                                                    |    \_/  //
00351 
00357 class SuspendLinkNodeNotify : public LinkNode {
00358   public:
00359     SuspendLinkNodeNotify ()                    { mNotifyConnection = N_true ; }
00360     virtual ~SuspendLinkNodeNotify () ;
00361     
00362     void    suspend (LinkNode const &other)     { VERIFY_not_stsLnNdIsError (connect (other)) ; }
00363     void    release (LinkNode const &other)     { VERIFY_not_stsLnNdIsError (disconnect (other)) ; }
00364     void    releaseAll ()                       { disconnectAll () ; }
00365     
00366   protected:
00368     virtual void    notifyConnection (NodeLinkType chg, NodeLink const *cnncn) ;
00370     virtual void    notifyNotifiedAndPurged (NodeLinkType chg) ;
00371 };
00372 
00373 SuspendLinkNodeNotify &operator, (SuspendLinkNodeNotify &suspend, LinkNode &connect) ;
00374 
00376 class ClcnNodesPrc : public LinkNode {
00377         M_DeclareDynClass
00378     public:
00379         virtual CPtr    getHost (ClassName className) const { return (className ? NULL : _mClsName) ; }
00380 };
00381 
00382 
00383 
00385 //  |   |          |       ----                                             //
00386 //  |\  |          |  ___  |   )           ___   ___   ____  ____           //
00387 //  | \ |  __   ---| /   ) |---  |/\  __  |   \ /   ) (     (      __  |/\  //
00388 //  |  \| /  \ (   | |---  |     |   /  \ |     |---   \__   \__  /  \ |    //
00389 //  |   | \__/  ---|  \__  |     |   \__/  \__/  \__  ____) ____) \__/ |    //
00391 
00394 class LinkNodeProcessor {
00395   public:
00396     LinkNodeProcessor () ;
00397     
00398     virtual         ~LinkNodeProcessor      () ;
00399 
00400     void            process             () ;
00401     
00402     UInt            gPendingCount       () const                { return mPendingCount ; }
00403     void            addSuspend          ()                      { mPendingCount++ ; }
00404     void            removeSuspend       () ;
00405     Bool            hasWaitingProcesses () const                { return mCurrPrcNodes->isConnected () ; }
00406     
00407     void            addNode             (LinkNode const &node)  { VERIFY_not_stsLnNdIsError (pcrNodesCurr ().connect (node)) ; }
00408     
00409     ClcnNodesPrc    &prcNodesNotCurr    ()                      { return *(mCurrPrcNodes == &mNodesA ? &mNodesB : (mCurrPrcNodes == &mNodesB ? &mNodesA : NULL)) ; }
00410     ClcnNodesPrc    &pcrNodesCurr       () const                { return *mCurrPrcNodes ; }
00411     
00412   protected:
00413     UInt            mPendingCount ;
00414     ClcnNodesPrc    mNodesA ;
00415     ClcnNodesPrc    mNodesB ;
00416     ClcnNodesPrc    *mCurrPrcNodes ;
00417 
00419     virtual void    process (const NodeLink& cnn)   {MUST_OVERLOAD}
00420 };
00421 
00422 class SuspendLinkNodeProcessor {
00423     public:
00424         SuspendLinkNodeProcessor (LinkNodeProcessor *const *processors) ;
00425         virtual ~SuspendLinkNodeProcessor () ;
00426     
00427     protected:
00428         LinkNodeProcessor *const *mProcessors ;
00429 };
00430 
00432 template<class T, T *prcNodes>
00433     class SuspendPrcNodes {
00434         public:
00435             SuspendPrcNodes ()                                          { prcNodes->addSuspend () ; }
00436             SuspendPrcNodes (LinkNode const &sender)                    { prcNodes->addSuspend () ; _addNode (sender) ; }
00437 
00438             virtual ~SuspendPrcNodes ()                                 { prcNodes->removeSuspend () ; }
00439 
00440             virtual UInt    gPendingCount () const                      { return _gPendingCount () ; }
00441 
00442             static T    *_gNotifySender ()                              { return prcNodes ; }
00443             static UInt _gPendingCount ()                               { return prcNodes->gPendingCount () ; }
00444             static void _addNode (LinkNode const &sender)               { prcNodes->addNode (sender) ; }
00445     };
00446 
00448 #endif // I_mlinknode.h

Generated at Tue Dec 4 19:53:25 2001 for MagiC++ by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001