Geant4  10.01.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 std::set<Watcher*>::iterator it = fWatchers.begin();
164  typename std::set<Watcher*>::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  typename std::set<Watcher*>::iterator it = fWatchers.begin();
328  typename std::set<Watcher*>::iterator _end = fWatchers.end();
329 
330  for (; it != _end; it++)
331  {
332  (*it)->NotifyNewObject(__toHook->GetObject(), this);
333  }
334  }
335 
336 template<class OBJECT>
337  void G4FastListNode<OBJECT>::UnHook()
338  {
339  G4FastListNode<OBJECT>* __next_node = this->fpNext;
340  G4FastListNode<OBJECT>* __prev_node = this->fpPrevious;
341 
342  if (__prev_node)
343  {
344  __prev_node->fpNext = __next_node;
345  }
346 
347  if (__next_node)
348  {
349  __next_node->fpPrevious = __prev_node;
350  }
351  fpNext = 0;
352  fpPrevious = 0;
353  }
354 
355 template<class OBJECT>
356  void G4FastList<OBJECT>::Unhook(G4FastListNode<OBJECT>* __toUnHook)
357  {
358  __toUnHook->UnHook();
359 
360  fNbObjects--;
361 
362  typename std::set<Watcher*>::iterator it = fWatchers.begin();
363  typename std::set<Watcher*>::iterator _end = fWatchers.end();
364 
365  for (; it != _end; it++)
366  {
367  (*it)->NotifyRemoveObject(__toUnHook->GetObject(), this);
368  }
369  }
370 
371 template<class OBJECT>
372  typename G4FastList<OBJECT>::iterator
373  G4FastList<OBJECT>::insert(typename G4FastList<OBJECT>::iterator __position,
374  OBJECT* __obj)
375  {
376  G4FastListNode<OBJECT>* __node = CreateNode(__obj);
377  Hook(__position.fpNode, __node);
378  return iterator(__node);
379  }
380 
381 //____________________________________________________________________
382 //
383 // WITHDRAW FROM LIST
384 //____________________________________________________________________
385 
386 template<class OBJECT>
387  void G4FastList<OBJECT>::CheckFlag(G4FastListNode<OBJECT>* __node)
388  {
389  if (__node->fListRef->fpList != this)
390  {
391  G4ExceptionDescription exceptionDescription;
392  exceptionDescription << "The object "
393  << " is not correctly linked to a G4FastList." << G4endl
394  << "You are probably trying to withdraw this object "
395  << "from the list but it probably does not belong to "
396  << "this fast list." << G4endl;
397  G4Exception("G4FastList<OBJECT>::CheckFlag", "G4FastList002",
398  FatalErrorInArgument, exceptionDescription);
399  }
400  }
401 
402 template<class OBJECT>
403  G4FastListNode<OBJECT>* G4FastList<OBJECT>::Unflag(OBJECT* __obj)
404  {
405  G4FastListNode<OBJECT>* __node = __GetNode(__obj);
406  CheckFlag(__node);
407  __node->fAttachedToList = false;
408  __node->fListRef.reset();
409  return __node;
410  }
411 
412 template<class OBJECT>
413  void G4FastList<OBJECT>::Unflag(G4FastListNode<OBJECT>* __node)
414  {
415  CheckFlag(__node);
416  __node->fAttachedToList = false;
417  __node->fListRef.reset();
418  return;
419  }
420 
421 template<class OBJECT>
422  OBJECT* G4FastList<OBJECT>::pop_back()
423  {
424  if (fNbObjects == 0) return 0;
425  G4FastListNode<OBJECT> * __aNode = fBoundary.GetPrevious();
426  Unhook(__aNode);
427  Unflag(__aNode);
428  return __aNode->GetObject();
429  }
430 
431 template<class OBJECT>
432  typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(OBJECT* __obj)
433  {
434  G4FastListNode<OBJECT>* __node = Unflag(__obj);
435  iterator __next(__node->GetNext());
436  Unhook(__node);
437  return __next;
438  }
439 
440 template<class OBJECT>
441  typename G4FastList<OBJECT>::iterator
442  G4FastList<OBJECT>::pop(G4FastListNode<OBJECT>* __node)
443  {
444  Unflag(__node);
445  iterator __next(__node->GetNext());
446  Unhook(__node);
447  return __next;
448  }
449 
450 template<class OBJECT>
451  typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(OBJECT* __obj)
452  {
453  G4FastListNode<OBJECT>* __next_node = EraseListNode(__obj);
454  //////////////////
455  DeleteObject(__obj);
456  __obj = 0;
457  //////////////////
458  iterator __next(__next_node);
459  return __next;
460  }
461 
462 template<class OBJECT>
463  G4FastListNode<OBJECT>* G4FastList<OBJECT>::EraseListNode(OBJECT* __obj)
464  {
465  G4FastListNode<OBJECT>* __node = Unflag(__obj);
466  __node->DetachYourSelf();
467  G4FastListNode<OBJECT>* __next = __node->GetNext();
468  Unhook(__node);
469  delete __node;
470  return __next;
471  }
472 
473 template<class OBJECT>
474  void G4FastList<OBJECT>::DeleteObject(OBJECT*)
475  {
476 // delete __obj;
477  }
478 
479 template<class OBJECT>
480  void G4FastList<OBJECT>::remove(OBJECT* __obj)
481  {
482  this->erase(__obj);
483  }
484 
485 template<class OBJECT>
486  typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::pop(iterator __first,
487  iterator __last)
488  {
489  if (fNbObjects == 0) return iterator(&fBoundary);
490 
491  while (__first != __last)
492  {
493  if (__first.fpNode) __first = pop(*__first);
494  }
495  return __last;
496  }
497 
498 template<class OBJECT>
499  typename G4FastList<OBJECT>::iterator G4FastList<OBJECT>::erase(iterator __first,
500  iterator __last)
501  {
502  if (fNbObjects == 0) return iterator(&fBoundary);
503 
504  while (__first != __last)
505  {
506  if (__first.fpNode) __first = erase(*__first);
507  }
508  return __last;
509  }
510 
511 template<class OBJECT>
512  void G4FastList<OBJECT>::clear()
513  {
514  erase(begin(), end());
515  }
516 
517 template<class OBJECT>
518  void G4FastList<OBJECT>::transferTo(G4FastList<OBJECT>* __destination)
519  {
520  if (fNbObjects == 0) return;
521 
522  if (__destination->fNbObjects == 0)
523  {
524  __destination->fNbObjects = this->fNbObjects;
525 
526  __destination->fBoundary.SetNext(fBoundary.GetNext());
527  __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
528  fBoundary.GetNext()->SetPrevious(&__destination->fBoundary);
529  fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
530  }
531  else
532  {
533  node* lastNode = __destination->fBoundary.GetPrevious();
534  lastNode->SetNext(fBoundary.GetNext());
535  fBoundary.GetNext()->SetPrevious(lastNode);
536  __destination->fBoundary.SetPrevious(fBoundary.GetPrevious());
537  fBoundary.GetPrevious()->SetNext(&__destination->fBoundary);
538 
539  __destination->fNbObjects += this->fNbObjects;
540  }
541 
542  fNbObjects = 0;
543  this->fBoundary.SetPrevious(&this->fBoundary);
544  this->fBoundary.SetNext(&this->fBoundary);
545 
546  fListRef->fpList = __destination;
547  }
548 
549 //____________________________________________________________
550 //
551 // G4FastList<OBJECT> Utils
552 //____________________________________________________________
553 
554 template<class OBJECT>
555  G4FastListNode<OBJECT>* G4FastList<OBJECT>::__GetNode(OBJECT* __obj)
556  {
557  G4FastListNode<OBJECT>* __node = GetNode(__obj);
558  // TODO : complete the exception
559  if (__node == 0)
560  {
561  G4ExceptionDescription exceptionDescription;
562  exceptionDescription << "The object ";
563  exceptionDescription << " was not connected to any trackList ";
564  G4Exception("G4FastList<OBJECT>::Unflag", "G4FastList003",
565  FatalErrorInArgument, exceptionDescription);
566  return 0;
567  }
568  return __node;
569  }
570 
571 template<class OBJECT>
572  G4FastListNode<OBJECT>* G4FastList<OBJECT>::GetNode(OBJECT* __obj)
573  {
574  G4FastListNode<OBJECT>* __node = __obj->GetListNode();
575  return __node;
576  }
577 
578 template<class OBJECT>
579  void G4FastList<OBJECT>::SetNode(OBJECT* __obj,
580  G4FastListNode<OBJECT>* __node)
581  {
582  __obj->SetListNode(__node);
583  }
584 
585 template<class OBJECT>
586  G4FastList<OBJECT>* G4FastList<OBJECT>::GetList(OBJECT* __obj)
587  {
588  G4FastListNode<OBJECT>* __node = GetNode(__obj);
589 
590  if (__node == 0) return 0;
591  if (__node->fListRef == 0) return 0;
592 
593  return __node->fListRef->fpTrackList;
594  }
595 
596 template<class OBJECT>
597  G4FastList<OBJECT>*
598  G4FastList<OBJECT>::GetList(G4FastListNode<OBJECT>* __node)
599  {
600  if (__node == 0) return 0;
601  if (__node->fListRef == 0) return 0;
602 
603  return __node->fListRef->fpList;
604  }
605 
606 template<class OBJECT>
607  void G4FastList<OBJECT>::Pop(OBJECT* __obj)
608  {
609  G4FastListNode<OBJECT>* __node = G4FastList<OBJECT>::GetNode(__obj);
610  G4FastList<OBJECT>* __list = G4FastList<OBJECT>::GetList(__node);
611  if (__list) __list->pop(__node);
612  }
613 
614 //#endif /* G4FASTLIST_ICC_*/