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
00021
00022
00023
00024
00026
00029 class LinkNode {
00030 public:
00031
00034 struct NodeLink {
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:
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 () ;
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:
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
00242
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
00248 #define N_LnNdCnncnStt_Reserve 0x0004
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
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
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