Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr) 28 // 29 // History: 30 // ----------- 31 // 10 Oct 2011 M.Karamitros created 32 // 33 // ------------------------------------------------------------------- 34 35 //#ifndef G4FASTLIST_ICC_ 36 //#define G4FASTLIST_ICC_ 37 38 //*********************************************************** 39 // TrackList_iterator 40 template<class OBJECT> 41 OBJECT* 42 G4FastList_iterator<OBJECT>::operator*() 43 { 44 if (fpNode == nullptr) return nullptr; 45 return fpNode->GetObject(); 46 } 47 48 template<class OBJECT> 49 OBJECT* 50 G4FastList_iterator<OBJECT>::operator->() 51 { 52 if (fpNode == nullptr) return nullptr; 53 return fpNode->GetObject(); 54 } 55 56 template<class OBJECT> 57 const OBJECT* 58 G4FastList_iterator<OBJECT>::operator*() const 59 { 60 if (fpNode == 0) return 0; 61 return fpNode->GetObject(); 62 } 63 64 template<class OBJECT> 65 const OBJECT* 66 G4FastList_iterator<OBJECT>::operator->() const 67 { 68 if (fpNode == 0) return 0; 69 return fpNode->GetObject(); 70 } 71 72 //*********************************************************** 73 // TrackNodeList 74 75 template<class OBJECT> 76 G4FastListNode<OBJECT>::G4FastListNode(OBJECT* track) : 77 fpObject(track), fpPrevious(nullptr), fpNext(nullptr) 78 { 79 fAttachedToList = false; 80 } 81 82 template<class OBJECT> 83 G4FastListNode<OBJECT>::~G4FastListNode() 84 { 85 if (fListRef && fListRef->fpList) 86 { 87 fListRef->fpList->pop(this); 88 } 89 } 90 91 template<class OBJECT> 92 void G4FastListNode<OBJECT>::DetachYourSelf() 93 { 94 if(fpObject) 95 { 96 fpObject->SetListNode(nullptr); 97 } 98 } 99 100 //*********************************************************** 101 102 template<class OBJECT> 103 G4FastList<OBJECT>::G4FastList() : 104 fBoundary() 105 { 106 fListRef.reset(new _ListRef<G4FastList<OBJECT> >(this)); 107 fNbObjects = 0; 108 fBoundary.SetPrevious(&fBoundary); 109 fBoundary.SetNext(&fBoundary); 110 fBoundary.fAttachedToList = true; 111 fpNodeInManyLists = nullptr; 112 } 113 114 // should not be used 115 template<class OBJECT> 116 G4FastList<OBJECT>::G4FastList(const G4FastList<OBJECT>& /*other*/) : 117 fBoundary() 118 { 119 // One track should not belong to two different trackLists 120 fNbObjects = 0; 121 fpNodeInManyLists = 0; 122 } 123 124 template<class OBJECT> 125 G4FastList<OBJECT>& G4FastList<OBJECT>::operator=(const G4FastList<OBJECT>& other) 126 { 127 // One track should not belong to two different trackList 128 if (this == &other) return *this; // handle self assignment 129 //assignment operator 130 return *this; 131 } 132 133 template<class OBJECT> 134 G4FastList<OBJECT>::~G4FastList() 135 { 136 if (fNbObjects != 0) 137 { 138 G4FastListNode<OBJECT> * __stackedTrack = fBoundary.GetNext(); 139 G4FastListNode<OBJECT> * __nextStackedTrack; 140 141 // delete tracks in the stack 142 while (__stackedTrack && __stackedTrack != &(fBoundary)) 143 { 144 __nextStackedTrack = __stackedTrack->GetNext(); 145 OBJECT* __obj = __stackedTrack->GetObject(); 146 147 delete __stackedTrack; 148 __stackedTrack = nullptr; 149 150 if (__obj) 151 { 152 ////////////// 153 DeleteObject(__obj); 154 __obj = nullptr; 155 ////////////// 156 } 157 __stackedTrack = __nextStackedTrack; 158 } 159 } 160 fNbObjects = 0; 161 162 auto it = fWatchers.begin(); 163 auto _end = fWatchers.end(); 164 165 for (; it != _end; it++) 166 { 167 (*it)->NotifyDeletingList(this); 168 (*it)->StopWatching(this, false); 169 } 170 171 if (fpNodeInManyLists) 172 { 173 delete fpNodeInManyLists; 174 fpNodeInManyLists = nullptr; 175 } 176 } 177 178 template<class OBJECT> 179 bool G4FastList<OBJECT>::empty() const 180 { 181 return (fNbObjects == 0); 182 } 183 184 template<class OBJECT> 185 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::begin() 186 { 187 return iterator(fBoundary.GetNext()); 188 } 189 190 template<class OBJECT> 191 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::begin() const 192 { 193 return const_iterator(fBoundary.GetNext()); 194 } 195 196 template<class OBJECT> 197 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::end() 198 { 199 return iterator(&(fBoundary)); 200 } 201 202 template<class OBJECT> 203 typename G4FastList<OBJECT>::const_iterator G4FastList<OBJECT>::end() const 204 { 205 return const_iterator(&(fBoundary)); 206 } 207 // return an iterator that contains an empty node 208 // use for boundary checking only 209 210 template<class OBJECT> 211 void G4FastList<OBJECT>::push_front(OBJECT* __obj) 212 { 213 insert(begin(), __obj); 214 } 215 216 template<class OBJECT> 217 void G4FastList<OBJECT>::push_back(OBJECT* __obj) 218 { 219 insert(end(), __obj); 220 } 221 222 template<class OBJECT> 223 bool G4FastList<OBJECT>::Holds(const OBJECT* __obj) const 224 { 225 node* __node = GetNode(__obj); 226 if(__node == 0) return false; 227 return (__node->fListRef->fpList == this); 228 } 229 230 // TODO: A revoir 231 template<class OBJECT> 232 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Flag(OBJECT* __obj) 233 { 234 G4FastListNode<OBJECT>* __node = GetNode(__obj); 235 236 if (__node != nullptr) 237 { 238 // Suggestion move the node to this list 239 if (__node->fAttachedToList) 240 { 241 G4ExceptionDescription exceptionDescription; 242 exceptionDescription << "An object"; 243 exceptionDescription << " is already attached to a TrackList "; 244 G4Exception("G4FastList<OBJECT>::Flag", "G4FastList001", 245 FatalErrorInArgument, exceptionDescription); 246 } 247 } 248 else 249 { 250 __node = new G4FastListNode<OBJECT>(__obj); 251 SetNode(__obj,__node); 252 } 253 254 __node->fAttachedToList = true; 255 __node->fListRef = fListRef; 256 return __node; 257 } 258 259 template<class OBJECT> 260 G4FastListNode<OBJECT>* G4FastList<OBJECT>::CreateNode(OBJECT* __obj) 261 { 262 G4FastListNode<OBJECT>* __listNode = Flag(__obj); 263 return __listNode; 264 } 265 266 template<class OBJECT> 267 void G4FastList<OBJECT>::Hook(G4FastListNode<OBJECT>* __position, 268 G4FastListNode<OBJECT>* __toHook) 269 { 270 /* 271 __toHook->SetNext(__position); 272 __toHook->SetPrevious(__position->GetPrevious()); 273 __position->GetPrevious()->SetNext(__toHook); 274 __position->SetPrevious(__toHook); 275 */ 276 G4FastListNode<OBJECT>* __previous = __position->GetPrevious(); 277 __toHook->SetPrevious(__previous); 278 __toHook->SetNext(__position); 279 __position->SetPrevious(__toHook); 280 __previous->SetNext(__toHook); 281 282 /* 283 if (fNbObjects == 0) 284 { 285 // DEBUG 286 // G4cout << "fNbObjects == 0" << G4endl; 287 fpStart = __toHook; 288 fpFinish = __toHook; 289 __toHook->SetNext(&fBoundary); 290 __toHook->SetPrevious(&fBoundary); 291 //fBoundary.SetNext(__toHook); 292 fBoundary.SetPrevious(__toHook); 293 } else if (__position == &fBoundary) 294 { 295 // DEBUG 296 // G4cout << "__position == &fBoundary" << G4endl; 297 fpFinish->SetNext(__toHook); 298 __toHook->SetPrevious(fpFinish); 299 300 __toHook->SetNext(&fBoundary); 301 fBoundary.SetPrevious(__toHook); 302 303 fpFinish = __toHook; 304 } else if (__position == fpStart) 305 { 306 // DEBUG 307 // G4cout << "__position == fStart" << G4endl; 308 __toHook->SetPrevious(&fBoundary); 309 //fBoundary.SetNext(__toHook); 310 __toHook->SetNext(fpStart); 311 fpStart->SetPrevious(__toHook); 312 fpStart = __toHook; 313 } else 314 { 315 // DEBUG 316 // G4cout << "else" << G4endl; 317 G4FastListNode<OBJECT>* __previous = __position->GetPrevious(); 318 __toHook->SetPrevious(__previous); 319 __toHook->SetNext(__position); 320 __position->SetPrevious(__toHook); 321 __previous->SetNext(__toHook); 322 } 323 */ 324 fNbObjects++; 325 326 if(fWatchers.empty() == false) 327 { 328 auto it = fWatchers.begin(); 329 auto _end = fWatchers.end(); 330 331 for (; it != _end; it++) 332 { 333 (*it)->NotifyAddObject(__toHook->GetObject(), this); 334 } 335 } 336 } 337 338 template<class OBJECT> 339 void G4FastListNode<OBJECT>::UnHook() 340 { 341 G4FastListNode<OBJECT>* __next_node = this->fpNext; 342 G4FastListNode<OBJECT>* __prev_node = this->fpPrevious; 343 344 if (__prev_node) 345 { 346 __prev_node->fpNext = __next_node; 347 } 348 349 if (__next_node) 350 { 351 __next_node->fpPrevious = __prev_node; 352 } 353 fpNext = nullptr; 354 fpPrevious = nullptr; 355 } 356 357 template<class OBJECT> 358 void G4FastList<OBJECT>::Unhook(G4FastListNode<OBJECT>* __toUnHook) 359 { 360 __toUnHook->UnHook(); 361 362 fNbObjects--; 363 364 auto it = fWatchers.begin(); 365 auto _end = fWatchers.end(); 366 367 for (; it != _end; it++) 368 { 369 (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this); 370 } 371 } 372 373 template<class OBJECT> 374 typename G4FastList<OBJECT>::iterator 375 G4FastList<OBJECT>::insert(typename G4FastList<OBJECT>::iterator __position, 376 OBJECT* __obj) 377 { 378 G4FastListNode<OBJECT>* __node = CreateNode(__obj); 379 Hook(__position.fpNode, __node); 380 return iterator(__node); 381 } 382 383 //____________________________________________________________________ 384 // 385 // WITHDRAW FROM LIST 386 //____________________________________________________________________ 387 388 template<class OBJECT> 389 void G4FastList<OBJECT>::CheckFlag(G4FastListNode<OBJECT>* __node) 390 { 391 if (__node->fListRef->fpList != this) 392 { 393 G4ExceptionDescription exceptionDescription; 394 exceptionDescription << "The object " 395 << " is not correctly linked to a G4FastList." << G4endl 396 << "You are probably trying to withdraw this object " 397 << "from the list but it probably does not belong to " 398 << "this fast list." << G4endl; 399 G4Exception("G4FastList<OBJECT>::CheckFlag", "G4FastList002", 400 FatalErrorInArgument, exceptionDescription); 401 } 402 } 403 404 template<class OBJECT> 405 G4FastListNode<OBJECT>* G4FastList<OBJECT>::Unflag(OBJECT* __obj) 406 { 407 G4FastListNode<OBJECT>* __node = __GetNode(__obj); 408 CheckFlag(__node); 409 __node->fAttachedToList = false; 410 __node->fListRef.reset(); 411 return __node; 412 } 413 414 template<class OBJECT> 415 void G4FastList<OBJECT>::Unflag(G4FastListNode<OBJECT>* __node) 416 { 417 CheckFlag(__node); 418 __node->fAttachedToList = false; 419 __node->fListRef.reset(); 420 return; 421 } 422 423 template<class OBJECT> 424 OBJECT* G4FastList<OBJECT>::pop_back() 425 { 426 if (fNbObjects == 0) return 0; 427 G4FastListNode<OBJECT> * __aNode = fBoundary.GetPrevious(); 428 Unhook(__aNode); 429 Unflag(__aNode); 430 return __aNode->GetObject(); 431 } 432 433 template<class OBJECT> 434 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(OBJECT* __obj) 435 { 436 G4FastListNode<OBJECT>* __node = Unflag(__obj); 437 iterator __next(__node->GetNext()); 438 Unhook(__node); 439 return __next; 440 } 441 442 template<class OBJECT> 443 typename G4FastList<OBJECT>::iterator 444 G4FastList<OBJECT>::pop(G4FastListNode<OBJECT>* __node) 445 { 446 Unflag(__node); 447 iterator __next(__node->GetNext()); 448 Unhook(__node); 449 return __next; 450 } 451 452 template<class OBJECT> 453 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(OBJECT* __obj) 454 { 455 G4FastListNode<OBJECT>* __next_node = EraseListNode(__obj); 456 ////////////////// 457 DeleteObject(__obj); 458 __obj = nullptr; 459 ////////////////// 460 iterator __next(__next_node); 461 return __next; 462 } 463 464 template<class OBJECT> 465 G4FastListNode<OBJECT>* G4FastList<OBJECT>::EraseListNode(OBJECT* __obj) 466 { 467 G4FastListNode<OBJECT>* __node = Unflag(__obj); 468 __node->DetachYourSelf(); 469 G4FastListNode<OBJECT>* __next = __node->GetNext(); 470 Unhook(__node); 471 delete __node; 472 return __next; 473 } 474 475 template<class OBJECT> 476 void G4FastList<OBJECT>::DeleteObject(OBJECT*) 477 { 478 // delete __obj; 479 } 480 481 template<class OBJECT> 482 void G4FastList<OBJECT>::remove(OBJECT* __obj) 483 { 484 this->erase(__obj); 485 } 486 487 template<class OBJECT> 488 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(iterator __first, 489 iterator __last) 490 { 491 if (fNbObjects == 0) return iterator(&fBoundary); 492 493 while (__first != __last) 494 { 495 if (__first.fpNode) __first = pop(*__first); 496 } 497 return __last; 498 } 499 500 template<class OBJECT> 501 typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(iterator __first, 502 iterator __last) 503 { 504 if (fNbObjects == 0) return iterator(&fBoundary); 505 506 while (__first != __last) 507 { 508 if (__first.fpNode) __first = erase(*__first); 509 } 510 return __last; 511 } 512 513 template<class OBJECT> 514 void G4FastList<OBJECT>::clear() 515 { 516 erase(begin(), end()); 517 } 518 519 template<class OBJECT> 520 void G4FastList<OBJECT>::transferTo(G4FastList<OBJECT>* __destination) 521 { 522 if (fNbObjects == 0) return; 523 524 if (__destination->fNbObjects == 0) 525 { 526 527 if(__destination->fWatchers.empty()==false) 528 { 529 auto it = __destination->fWatchers.begin(); 530 auto _end = __destination->fWatchers.end(); 531 532 // G4cout << "G4FastList<OBJECT>::transferTo --- Watcher size = " 533 // << __destination->fWatchers.size() 534 // << G4endl; 535 536 for (; it != _end; it++) 537 { 538 for(iterator it2 = this->begin() ; 539 it2 != this->end(); ++it2 540 ) 541 { 542 (*it)->NotifyAddObject(*it2, this); 543 } 544 } 545 } 546 547 __destination->fNbObjects = this->fNbObjects; 548 549 __destination->fBoundary.SetNext(fBoundary.GetNext()); 550 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious()); 551 fBoundary.GetNext()->SetPrevious(&__destination->fBoundary); 552 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary); 553 } 554 else 555 { 556 if(__destination->fWatchers.empty()==false) 557 { 558 auto it = __destination->fWatchers.begin(); 559 auto _end = __destination->fWatchers.end(); 560 561 for (; it != _end; it++) 562 { 563 for(iterator it2 = this->begin() ; 564 it2 != this->end(); ++it2) 565 { 566 (*it)->NotifyAddObject(*it2, this); 567 } 568 } 569 } 570 571 node* lastNode = __destination->fBoundary.GetPrevious(); 572 lastNode->SetNext(fBoundary.GetNext()); 573 fBoundary.GetNext()->SetPrevious(lastNode); 574 __destination->fBoundary.SetPrevious(fBoundary.GetPrevious()); 575 fBoundary.GetPrevious()->SetNext(&__destination->fBoundary); 576 577 __destination->fNbObjects += this->fNbObjects; 578 } 579 580 fNbObjects = 0; 581 this->fBoundary.SetPrevious(&this->fBoundary); 582 this->fBoundary.SetNext(&this->fBoundary); 583 584 fListRef->fpList = __destination; 585 } 586 587 //____________________________________________________________ 588 // 589 // G4FastList<OBJECT> Utils 590 //____________________________________________________________ 591 592 template<class OBJECT> 593 G4FastListNode<OBJECT>* G4FastList<OBJECT>::__GetNode(OBJECT* __obj) 594 { 595 G4FastListNode<OBJECT>* __node = GetNode(__obj); 596 // TODO : complete the exception 597 if (__node == nullptr) 598 { 599 G4ExceptionDescription exceptionDescription; 600 exceptionDescription << "The object "; 601 exceptionDescription << " was not connected to any trackList "; 602 G4Exception("G4FastList<OBJECT>::Unflag", "G4FastList003", 603 FatalErrorInArgument, exceptionDescription); 604 return nullptr; 605 } 606 return __node; 607 } 608 609 template<class OBJECT> 610 G4FastListNode<OBJECT>* G4FastList<OBJECT>::GetNode(OBJECT* __obj) 611 { 612 G4FastListNode<OBJECT>* __node = __obj->GetListNode(); 613 return __node; 614 } 615 616 template<class OBJECT> 617 void G4FastList<OBJECT>::SetNode(OBJECT* __obj, 618 G4FastListNode<OBJECT>* __node) 619 { 620 __obj->SetListNode(__node); 621 } 622 623 template<class OBJECT> 624 G4FastList<OBJECT>* G4FastList<OBJECT>::GetList(OBJECT* __obj) 625 { 626 G4FastListNode<OBJECT>* __node = GetNode(__obj); 627 628 if (__node == 0) return 0; 629 if (__node->fListRef == nullptr) return 0; 630 631 return __node->fListRef->fpTrackList; 632 } 633 634 template<class OBJECT> 635 G4FastList<OBJECT>* 636 G4FastList<OBJECT>::GetList(G4FastListNode<OBJECT>* __node) 637 { 638 if (__node == nullptr) return nullptr; 639 if (__node->fListRef == nullptr) return nullptr; 640 641 return __node->fListRef->fpList; 642 } 643 644 template<class OBJECT> 645 void G4FastList<OBJECT>::Pop(OBJECT* __obj) 646 { 647 G4FastListNode<OBJECT>* __node = G4FastList<OBJECT>::GetNode(__obj); 648 G4FastList<OBJECT>* __list = G4FastList<OBJECT>::GetList(__node); 649 if (__list) __list->pop(__node); 650 } 651 652 //#endif /* G4FASTLIST_ICC_*/ 653