00001
00002 #include "stdafx.h"
00003 #include "mlinknode.h"
00004
00006 M_ImplementDynClass (LinkNode)
00007
00008 LinkNode::LinkNode (IndVect sizeData) : VectLnNdCnncn (sizeData), mChgCnncn (0), mProtected (0), mNotifyConnection (N_false), mLastChanged (NULL) {
00009 }
00010
00011 LinkNode::~LinkNode () {
00012 if (items ())
00013 disconnectAll () ;
00014 }
00015
00016 StsLnNB LinkNode::connect (LinkNode const &other) {
00017 ASSERT (&other != this) ;
00018 addProtect () ;
00019 ((LinkNode &) other).addProtect () ;
00020 StsLnNB ret = stsLnNd (setConnected (other), ((LinkNode &) other).setConnected (*this)) ;
00021 ((LinkNode &) other).removeProtect () ;
00022 removeProtect () ;
00023 return ret ;
00024 }
00025
00026 StsLnNd LinkNode::disconnect (LinkNode const &other, IndLnNd iOther) {
00027 LnNdCnncn const &cnn = (*this) [iOther] ;
00028 if (!(cnn.state & N_LnNdCnncnStt_Connected))
00029 return N_StsLnNd_Warning | N_StsLnNd_AlreadyDone ;
00030 addProtect () ;
00031 ((LinkNode &) other).addProtect () ;
00032 IndLnNd iThis = other.find (*this) ;
00033 if (iOther == N_IndLnNd_Invalid || iThis == N_IndLnNd_Invalid) {
00034 TRACE ("Trying disconnect %p:%s:%d and %p:%s:%d.\n", (CPtr) this, (CStr) getHost (NULL), (int) iOther, (CPtr) &other, (CStr) other.getHost (NULL), (int) iThis) ;
00035 trace (*this, 2, N_LnNdCnncnStt_) ;
00036 trace (other, 2, N_LnNdCnncnStt_) ;
00037 assert (0) ;
00038 }
00039 VERIFY_not_stsLnNdIsError (setDisconnected (iOther)) ;
00040 VERIFY_not_stsLnNdIsError (((LinkNode &) other).setDisconnected (iThis)) ;
00041 ((LinkNode &) other).removeProtect () ;
00042 removeProtect () ;
00043 return N_StsLnNd_OK ;
00044 }
00045
00046 StsLnNd LinkNode::disconnect (LinkNode const &other) {
00047 IndVect iOther = find (other) ;
00048 if (iOther == N_IndVect_Invalid)
00049 return N_StsLnNd_Warning | N_StsLnNd_NoSuchLnNd ;
00050 return disconnect (other, iOther) ;
00051 }
00052
00053 StsLnNd LinkNode::reserve (LinkNode const &other) {
00054 ASSERT (&other != this) ;
00055 addProtect () ;
00056 ((LinkNode &) other).addProtect () ;
00057 StsLnNd ret = setConnectedAnd (other, N_LnNdCnncnStt_Reserve, N_LnNdCnncnStt_ChgReserve) ;
00058 ((LinkNode &) other).setConnectedAnd (*this, N_LnNdCnncnStt_ReservedBy, N_LnNdCnncnStt_ChgReservedBy) ;
00059 ((LinkNode &) other).removeProtect () ;
00060 removeProtect () ;
00061 return ret ;
00062 }
00063
00064 StsLnNd LinkNode::release (LinkNode const &other) {
00065 IndLnNd i = find (other) ;
00066 if (i == N_IndLnNd_Invalid)
00067 return N_StsLnNd_Error | N_StsLnNd_NoSuchLnNd ;
00068 return release (i) ;
00069 }
00070
00071 StsLnNd LinkNode::release (IndLnNd iOther) {
00072 addProtect () ;
00073 LnNdCnncn &cnn = operator[] (iOther) ;
00074 if ((cnn.state & (N_LnNdCnncnStt_Reserve | N_LnNdCnncnStt_Connected)) != (N_LnNdCnncnStt_Reserve | N_LnNdCnncnStt_Connected))
00075 return N_StsLnNd_Warning | N_StsLnNd_AlreadyDone ;
00076 LinkNode *other = (LinkNode *) cnn.node ;
00077 other->addProtect () ;
00078 cnn.state &= ~N_LnNdCnncnStt_Reserve ;
00079 cnn.state |= N_LnNdCnncnStt_ChgRelease ;
00080 connectionChanged (&cnn, N_LnNdCnncnStt_ChgRelease) ;
00081 other->setReleasedBy (*this) ;
00082 other->removeProtect () ;
00083 removeProtect () ;
00084 return N_StsLnNd_OK ;
00085 }
00086
00087 void LinkNode::disconnectAll () {
00088 addProtect () ;
00089 LnNdCnncn const *cnn ;
00090 for (IndLnNd i = 0 ; !!(cnn = iterConnection (i)) ; i++) {
00091 if (cnn->node && (cnn->state & N_LnNdCnncnStt_Connected))
00092 disconnect (*cnn->node, i) ;
00093 }
00094 removeProtect () ;
00095 }
00096
00097 Bool LinkNode::isConnected (LinkNode const &other) const {
00098 IndLnNd i = find (other) ;
00099 if (i == N_IndLnNd_Invalid)
00100 return N_false ;
00101 return isConnected (i) ;
00102 }
00103
00104 Bool LinkNode::isConnected (ClassName clsName) const {
00105 for (IndLnNd i = 0 ; iterConnected (i, clsName) != NULL ; i++)
00106 return N_true ;
00107 return N_false ;
00108 }
00109
00110 Bool LinkNode::isReservedBy (LinkNode const &other) const {
00111 IndLnNd i = find (other) ;
00112 if (i == N_IndLnNd_Invalid)
00113 return N_false ;
00114 return isReservedBy (i) ;
00115 }
00116
00117 Bool LinkNode::isConnected () const {
00118 for (IndLnNd i = 0 ; i < items () ; i++)
00119 if ((*this) [i].state & N_LnNdCnncnStt_Connected)
00120 return N_true ;
00121 return N_false ;
00122 }
00123
00124 Bool LinkNode::isReserved () const {
00125 for (IndLnNd i = 0 ; i < items () ; i++)
00126 if ((*this) [i].state & N_LnNdCnncnStt_ReservedBy) {
00127 ASSERT ((*this) [i].state & N_LnNdCnncnStt_Connected) ;
00128 return N_true ;
00129 }
00130 return N_false ;
00131 }
00132
00133 Bool LinkNode::hasReserved () const {
00134 for (IndLnNd i = 0 ; i < items () ; i++)
00135 if ((*this) [i].state & N_LnNdCnncnStt_Reserve) {
00136 ASSERT ((*this) [i].state & N_LnNdCnncnStt_Connected) ;
00137 return N_true ;
00138 }
00139 return N_false ;
00140 }
00141
00142 LnNdCnncn const *LinkNode::iterChanged (IndLnNd &i) const {
00143 for (LnNdCnncn const *ret ; !!(ret = iterConnection (i)) ; i++)
00144 if (ret->state & N_LnNdCnncnStt_Chg_)
00145 return ret ;
00146 return NULL ;
00147 }
00148
00149 LnNdCnncn const *LinkNode::iterConnected (IndLnNd &i) const {
00150 for (LnNdCnncn const *ret ; !!(ret = iterConnection (i)) ; i++)
00151 if (ret->state & N_LnNdCnncnStt_Connected)
00152 return ret ;
00153 return NULL ;
00154 }
00155
00156 LnNdCnncn const *LinkNode::iterReserved (IndLnNd &i) const {
00157 for (LnNdCnncn const *ret ; !!(ret = iterConnection (i)) ; i++)
00158 if ((ret->state & (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_Reserve)) == (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_Reserve))
00159 return ret ;
00160 return NULL ;
00161 }
00162
00163 LnNdCnncn const *LinkNode::iterReserver (IndLnNd &i) const {
00164 for (LnNdCnncn const *ret ; !!(ret = iterConnection (i)) ; i++)
00165 if ((ret->state & (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ReservedBy)) == (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ReservedBy))
00166 return ret ;
00167 return NULL ;
00168 }
00169
00170 void const *LinkNode::iterConnected (IndLnNd &i, ClassName clsName) const {
00171 CPtr ret ;
00172 for (LnNdCnncn const *cnn ; !!(cnn = iterConnected (i)) ; i++)
00173 if (!!(ret = cnn->node->getHost (clsName)))
00174 return ret ;
00175 return NULL ;
00176 }
00177
00178 StsLnNd LinkNode::setConnected (LinkNode const &other) {
00179 ASSERT (mProtected) ;
00180 IndLnNd i ;
00181 LnNdCnncn *cnn ;
00182 if ((i = find (other)) != N_IndLnNd_Invalid) {
00183 cnn = &((*this) [i]) ;
00184 if (cnn->state & N_LnNdCnncnStt_Connected)
00185 return N_StsLnNd_Warning | N_StsLnNd_AlreadyDone ;
00186 cnn->state |= (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected) ;
00187 } else {
00188 i = allocNewItem () ;
00189 ASSERT (i != N_IndLnNd_Invalid) ;
00190 cnn = &((*this) [i]) ;
00191 cnn->node = &((LinkNode &) other) ;
00192 cnn->state = (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected) ;
00193 }
00194 connectionChanged (cnn, N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected) ;
00195 return N_StsLnNd_OK ;
00196 }
00197
00198 StsLnNd LinkNode::setConnectedAnd (LinkNode const &other, LnNdCnncnType status, LnNdCnncnType change) {
00199 ASSERT (mProtected) ;
00200 IndLnNd i ;
00201 LnNdCnncn *cnn ;
00202 LnNdCnncnType chg ;
00203 if ((i = find (other)) != N_IndLnNd_Invalid) {
00204 cnn = &((*this) [i]) ;
00205 if ((cnn->state & status) == status) {
00206 ASSERT (cnn->state & N_LnNdCnncnStt_Connected) ;
00207 return N_StsLnNd_Warning | N_StsLnNd_AlreadyDone ;
00208 }
00209 if (!(cnn->state & N_LnNdCnncnStt_Connected)) {
00210 cnn->state |= (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected) ;
00211 chg = N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected ;
00212 } else
00213 chg = 0 ;
00214 } else {
00215 i = allocNewItem () ;
00216 ASSERT (i != N_IndLnNd_Invalid) ;
00217 cnn = &((*this) [i]) ;
00218 cnn->node = &((LinkNode &) other) ;
00219 cnn->state = (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected) ;
00220 chg = N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected ;
00221 }
00222 chg |= status | change ;
00223 cnn->state |= chg ;
00224 connectionChanged (cnn, chg) ;
00225 return N_StsLnNd_OK ;
00226 }
00227
00228 StsLnNd LinkNode::setDisconnected (IndLnNd iOther) {
00229 ASSERT (mProtected) ;
00230 if (iOther == N_IndLnNd_Invalid || items () < iOther)
00231 return N_StsLnNd_Error | N_StsLnNd_InvalidRef ;
00232 LnNdCnncn &cnn = operator[] (iOther) ;
00233 if (!(cnn.state & N_LnNdCnncnStt_Connected))
00234 return N_StsLnNd_Warning | N_StsLnNd_AlreadyDone ;
00235 StsLnNd ret = N_StsLnNd_OK ;
00236 LnNdCnncnType chg = 0 ;
00237 if (cnn.state & N_LnNdCnncnStt_ReservedBy) {
00238 chg |= N_LnNdCnncnStt_ChgReleasedBy ;
00239 ret |= N_StsLnNd_ReleasedBy ;
00240 }
00241 if (cnn.state & N_LnNdCnncnStt_Reserve) {
00242 chg |= N_LnNdCnncnStt_ChgRelease ;
00243 ret |= N_StsLnNd_Release ;
00244 }
00245 cnn.state &= ~(N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_Reserve | N_LnNdCnncnStt_ReservedBy | N_LnNdCnncnStt_FlagA | N_LnNdCnncnStt_FlagB | N_LnNdCnncnStt_FlagC | N_LnNdCnncnStt_FlagD) ;
00246 chg |= N_LnNdCnncnStt_ChgDisconnected ;
00247 cnn.state |= chg ;
00248 connectionChanged (&cnn, chg) ;
00249 return ret ;
00250 }
00251
00252 void LinkNode::setReleasedBy (IndLnNd iOther) {
00253 ASSERT (mProtected) ;
00254 ASSERT (iOther != N_IndLnNd_Invalid && iOther < items ()) ;
00255 LnNdCnncn &cnn = operator[] (iOther) ;
00256 ASSERT ((cnn.state & (N_LnNdCnncnStt_ReservedBy | N_LnNdCnncnStt_Connected)) == (N_LnNdCnncnStt_ReservedBy | N_LnNdCnncnStt_Connected)) ;
00257 cnn.state &= ~N_LnNdCnncnStt_ReservedBy ;
00258 cnn.state |= N_LnNdCnncnStt_ChgReleasedBy ;
00259 connectionChanged (&cnn, N_LnNdCnncnStt_ChgReleasedBy) ;
00260 }
00261
00262 void LinkNode::removeProtect () {
00263 ASSERT (mProtected != 0) ;
00264 if (--mProtected == 0 && mChgCnncn) {
00265 notifyBeginNotify (mChgCnncn) ;
00266
00267
00268
00269 LnNdCnncnType changed = 0 ;
00270 while (mChgCnncn) {
00271 ASSERT (mLastChanged) ;
00272 changed |= mChgCnncn ;
00273 mProtected++ ;
00274 mChgCnncn = 0 ;
00275 sendNotifys () ;
00276 VERIFY (--mProtected == 0) ;
00277 }
00278
00279
00280
00281 if (changed & N_LnNdCnncnStt_ChgDisconnected)
00282 purgeDisconnectedConnections () ;
00283
00284
00285 notifyNotifiedAndPurged (changed) ;
00286 }
00287 }
00288
00289 void LinkNode::sendNotifys () {
00290 LnNdCnncn *cnn = (LnNdCnncn *) mLastChanged ;
00291 mLastChanged = NULL ;
00292 if (items ())
00293 if (mNotifyConnection) {
00294
00295 if (cnn != (LnNdCnncn *) -1) {
00296
00297
00298 LnNdCnncnType state = cnn->state ;
00299 cnn->state &= ~N_LnNdCnncnStt_Chg_ ;
00300 notifyConnection (state, cnn) ;
00301 } else {
00302
00303
00304 IndLnNd i = items () - 1 ;
00305 do {
00306 LnNdCnncn &cnn = (*this) [i] ;
00307 if (cnn.node)
00308 if (cnn.state & N_LnNdCnncnStt_Chg_) {
00309 LnNdCnncnType state = cnn.state ;
00310 cnn.state &= ~N_LnNdCnncnStt_Chg_ ;
00311 notifyConnection (state, &cnn) ;
00312 }
00313 } while (i-- != 0) ;
00314 }
00315 } else
00316 for (IndLnNd i = 0 ; i < items () ; i++)
00317 (*this) [i].state &= ~N_LnNdCnncnStt_Chg_ ;
00318 }
00319
00320 inline Bool isConnectionUsed (LnNdCnncnType state) {
00321 return (state & N_LnNdCnncnStt_Connected) ;
00322 }
00323
00324 Bool LinkNode::purgeDisconnectedConnections () {
00325 if (items ()) {
00326 Bool ret = N_false ;
00327 IndVect size = items () ;
00328 Bool purge = N_false ;
00329 for (IndLnNd i = 0 ; i < items () && isConnectionUsed ((*this) [i].state) ; i++) ;
00330 if (i < size) {
00331 IndLnNd iMoveTo = i ;
00332 do {
00333 for (i++ ; i < items () && !isConnectionUsed ((*this) [i].state) ; i++) ;
00334 if (i < items ()) {
00335 IndLnNd iMoveFrom = i ;
00336 for (i++ ; i < items () && isConnectionUsed ((*this) [i].state) ; i++) ;
00337 memmove (itemNT (iMoveTo), itemNT (iMoveFrom), (i - iMoveFrom) * mItemSize) ;
00338 size = iMoveTo = iMoveTo + (i - iMoveFrom) ;
00339 } else
00340 size = iMoveTo ;
00341 } while (i < items ()) ;
00342 setSize (size) ;
00343 return N_true ;
00344 }
00345 }
00346 return N_false ;
00347 }
00348
00349 void trace (LinkNode const &ob, IndVect indent, LnNdCnncnType show1) {
00350 String fill ;
00351 if (indent) {
00352 fill.set (' ', indent) ;
00353 TRACE ((CStr) fill) ;
00354 }
00355 TRACE ("%p: [%d/%d] %d %04lx %s %s ", (CPtr) &ob, (int) ob.connections ().items (), (int) ob.connections ().allocated (), (int) ob.gProtected (), (DWord) ob.gChgCnncn (), ob.clsName (), (CStr) ob.getHost (NULL)) ;
00356 char str [100] ;
00357 TRACE (ob.gLastChanged () ? (ob.gLastChanged () == (LnNdCnncn const *) -1 ? "-1" : type2Str (str, ob.connections ().index (ob.gLastChanged ()))) : "NULL") ;
00358 TRACE ("\n") ;
00359 LnNdCnncn const *cnn ;
00360 for (IndLnNd i = 0 ; (cnn = ob.iterConnection (i)) != NULL ; i++)
00361 if (show1 == N_LnNdCnncnStt_ || (cnn->state & show1)) {
00362 if (indent)
00363 TRACE ((CStr) fill) ;
00364 TRACE (" [%d] (%04lx %p %s %s)\n", (int) i, (DWord) cnn->state, (CPtr) cnn->node, (CStr) cnn->node->clsName (), (CStr) cnn->node->getHost (NULL)) ;
00365 }
00366 }
00367
00368 #ifdef __STRING_H__
00369 String& links2Str (String& ret, LinkNode const &ob) {
00370 char str [100] ;
00371 sprintf (str, "%p: %d [%d/%d] %04lx %s %s ", (CPtr) &ob, (int) ob.gProtected (), (int) ob.connections ().items (), (int) ob.connections ().allocated (), (DWord) ob.gChgCnncn (), ob.clsName (), (CStr) ob.getHost (NULL)) ;
00372 ret = str ;
00373 ret += (ob.gLastChanged () ? (ob.gLastChanged () == (LnNdCnncn const *) -1 ? "-1" : type2Str (str, ob.connections ().index (ob.gLastChanged ()))) : "NULL") ;
00374 LnNdCnncn const *cnn ;
00375 for (IndLnNd i = 0 ; (cnn = ob.iterConnected (i)) != NULL ; i++) {
00376 sprintf (str, " (%4lx %p %s %s)", (DWord) cnn->state, (CPtr) cnn->node, (CStr) cnn->node->clsName (), (CStr) cnn->node->getHost (NULL)) ;
00377 ret += str ;
00378 }
00379 return ret ;
00380 }
00381 #endif // __STRING_H__
00382
00384 IndLnNd VectLnNdCnncn::getGrow (IndLnNd minSize) const {
00385 IndLnNd ret = max ((IndLnNd) minSize, (IndLnNd) (mItems + (mItems ? mItems : 5))) ;
00386 return ret ;
00387 }
00388
00389 IndLnNd VectLnNdCnncn::find (LinkNode const *node) const {
00390 if (items ()) {
00391 IndLnNd i = items () - 1 ;
00392 do
00393 if (operator[] (i).node == node)
00394 return i ;
00395 while (i-- != 0) ;
00396 }
00397 return N_IndLnNd_Invalid ;
00398 }
00399
00400
00401
00403
00404
00405
00406
00407
00408
00409
00411
00412 SuspendLinkNodeNotify::~SuspendLinkNodeNotify () {
00413 releaseAll () ;
00414 }
00415
00416 void SuspendLinkNodeNotify::notifyConnection (LnNdCnncnType chg, LnNdCnncn const *cnncn) {
00417 if ((chg & (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected)) == (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgConnected)) {
00418 LinkNode *node = (LinkNode *) cnncn->node ;
00419 ASSERT (node) ;
00420 node->addProtect () ;
00421 } else if ((chg & (N_LnNdCnncnStt_Connected | N_LnNdCnncnStt_ChgDisconnected)) == N_LnNdCnncnStt_ChgDisconnected) {
00422 LinkNode *node = (LinkNode *) cnncn->node ;
00423 ASSERT (node) ;
00424 node->removeProtect () ;
00425 }
00426 }
00427
00428 void SuspendLinkNodeNotify::notifyNotifiedAndPurged (LnNdCnncnType chg) {
00429 }
00430
00431 SuspendLinkNodeNotify &operator, (SuspendLinkNodeNotify &suspend, LinkNode &connect) {
00432 VERIFY_not_stsLnNdIsError (suspend.connect (connect)) ;
00433 return suspend ;
00434 }
00435
00436
00437
00439
00440
00441
00442
00443
00445
00446
00447
00448 ProcessNodes::ProcessNodes () {
00449 mCurrPrcNodes = &mNodesA ;
00450 mPendingCount = 0 ;
00451 }
00452
00453 ProcessNodes::~ProcessNodes () {
00454 }
00455
00456 void ProcessNodes::removeSuspend () {
00457 if (--mPendingCount == 0)
00458 process () ;
00459 }
00460
00461 void ProcessNodes::process () {
00462 while (pcrNodesCurr ().isConnected ()) {
00463 mPendingCount++ ;
00464 LinkNode &senders = pcrNodesCurr () ;
00465 mCurrPrcNodes = &prcNodesNotCurr () ;
00466
00467 senders.addProtect () ;
00468 LnNdCnncn const *cnn ;
00469 for (IndLnNd i = 0 ; !!(cnn = senders.iterConnected (i)) ; i++)
00470 process (*cnn) ;
00471 senders.disconnectAll () ;
00472 senders.removeProtect () ;
00473 mPendingCount-- ;
00474 }
00475 ASSERT (!mNodesA.isConnected ()) ;
00476 ASSERT (!mNodesB.isConnected ()) ;
00477 }
00478
00479 SuspendProcessNodes::SuspendProcessNodes (ProcessNodes *const *processors) : mProcessors (processors) {
00480 for (char i = 0 ; mProcessors [i] ; i++)
00481 mProcessors [i]->addSuspend () ;
00482 }
00483
00484 SuspendProcessNodes::~SuspendProcessNodes () {
00485 ASSERT (mProcessors [0]) ;
00486 char iPrc ;
00487 ProcessNodes *prc ;
00488 if (mProcessors [0]->gPendingCount () == 1) {
00489 char i ;
00490 for (iPrc = 0 ; !!(prc = mProcessors [iPrc]) ; iPrc++) {
00491 ASSERT (prc->gPendingCount () == 1) ;
00492 prc->process () ;
00493 for (i = 0 ; i < iPrc ; i++)
00494 if (mProcessors [i]->hasWaitingProcesses ())
00495 iPrc = i - i ;
00496 }
00497 }
00498 for (iPrc = 0 ; !!(prc = mProcessors [iPrc]) ; iPrc++)
00499 prc->removeSuspend () ;
00500 }
00501
00503
00504
00505
00506
00507
00508
00510