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
00020
00021
00022
00023
00025
00028 class LinkNode {
00029 public:
00030
00033 struct NodeLink {
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:
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 () ;
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:
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
00241
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
00247 #define N_LnNdCnncnStt_Reserve 0x0004
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
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
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