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