Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

mlinknode.h

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

Generated on Thu Feb 10 20:06:42 2005 for LibMagiC by doxygen1.2.18