gwnavruntime/kernel/SF_List.h Source File

SF_List.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: None
10 Filename : KY_List.h
11 Content : Template implementation for doubly-connected linked List
12 Created : 2008
13 Authors : MaximShemanarev
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_List_H
18 #define INC_KY_Kernel_List_H
19 
21 
22 namespace Kaim {
23 
24 // ***** ListNode
25 //
26 // Base class for the elements of the intrusive linked list.
27 // To store elements in the List do:
28 //
29 // struct MyData : ListNode<MyData>
30 // {
31 // . . .
32 // };
33 //------------------------------------------------------------------------
34 template<class T>
35 struct ListNode
36 {
37  union {
38  T* pPrev;
39  void* pVoidPrev;
40  };
41  union {
42  T* pNext;
43  void* pVoidNext;
44  };
45 
46  void RemoveNode()
47  {
48  pPrev->pNext = pNext;
49  pNext->pPrev = pPrev;
50  }
51 
52  // Removes us from the list and inserts pnew there instead.
53  void ReplaceNodeWith(T* pnew)
54  {
55  pPrev->pNext = pnew;
56  pNext->pPrev = pnew;
57  pnew->pPrev = pPrev;
58  pnew->pNext = pNext;
59  }
60 
61  // Inserts the argument linked list node after us in the list.
62  void InsertNodeAfter(T* p)
63  {
64  p->pPrev = pNext->pPrev; // this
65  p->pNext = pNext;
66  pNext->pPrev = p;
67  pNext = p;
68  }
69  // Inserts the argument linked list node before us in the list.
70  void InsertNodeBefore(T* p)
71  {
72  p->pNext = pNext->pPrev; // this
73  p->pPrev = pPrev;
74  pPrev->pNext = p;
75  pPrev = p;
76  }
77 
78  void Alloc_MoveTo(ListNode<T>* pdest)
79  {
80  pdest->pNext = pNext;
81  pdest->pPrev = pPrev;
82  pPrev->pNext = (T*)pdest;
83  pNext->pPrev = (T*)pdest;
84  }
85 };
86 
87 
88 
89 // ***** List
90 //
91 // Doubly linked intrusive list.
92 // The data type must be derived from ListNode.
93 //
94 // Adding: PushFront(), PushBack().
95 // Removing: Remove() - the element must be in the list!
96 // Moving: BringToFront(), SendToBack() - the element must be in the list!
97 //
98 // Iterating:
99 // MyData* data = MyList.GetFirst();
100 // while (!MyList.IsNull(data))
101 // {
102 // . . .
103 // data = MyList.GetNext(data);
104 // }
105 //
106 // Removing:
107 // MyData* data = MyList.GetFirst();
108 // while (!MyList.IsNull(data))
109 // {
110 // MyData* next = MyList.GetNext(data);
111 // if (ToBeRemoved(data))
112 // MyList.Remove(data);
113 // data = next;
114 // }
115 //
116 //------------------------------------------------------------------------
117 // List<> represents a boudly-linked list if T, where each T must detive
118 // from ListNode<B>. B specifies the base class that was directly
119 // derived from ListNode, and is only necessary if there is an intermediate
120 // inheritance chain.
121 
122 template<class T, class B = T> class List
123 {
124 public:
125  typedef T ValueType;
126 
127  List()
128  {
129  Root.pNext = Root.pPrev = (ValueType*)&Root;
130  }
131 
132  void Clear()
133  {
134  Root.pNext = Root.pPrev = (ValueType*)&Root;
135  }
136 
137  const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; }
138  const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; }
139  ValueType* GetFirst() { return (ValueType*)Root.pNext; }
140  ValueType* GetLast () { return (ValueType*)Root.pPrev; }
141 
142  // Determine if list is empty (i.e.) points to itself.
143  // Go through void* access to avoid issues with strict-aliasing optimizing out the
144  // access after RemoveNode(), etc.
145  bool IsEmpty() const { return Root.pVoidNext == (const T*)(const B*)&Root; }
146  bool IsFirst(const ValueType* p) const { return p == Root.pNext; }
147  bool IsLast (const ValueType* p) const { return p == Root.pPrev; }
148  bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; }
149 
150  inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; }
151  inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; }
152  inline static ValueType* GetPrev( ValueType* p) { return (ValueType*)p->pPrev; }
153  inline static ValueType* GetNext( ValueType* p) { return (ValueType*)p->pNext; }
154 
155  void PushFront(ValueType* p)
156  {
157  p->pNext = Root.pNext;
158  p->pPrev = (ValueType*)&Root;
159  Root.pNext->pPrev = p;
160  Root.pNext = p;
161  }
162 
163  void PushBack(ValueType* p)
164  {
165  p->pPrev = Root.pPrev;
166  p->pNext = (ValueType*)&Root;
167  Root.pPrev->pNext = p;
168  Root.pPrev = p;
169  }
170 
171  static void Remove(ValueType* p)
172  {
173  p->pPrev->pNext = p->pNext;
174  p->pNext->pPrev = p->pPrev;
175  }
176 
177  void BringToFront(ValueType* p)
178  {
179  Remove(p);
180  PushFront(p);
181  }
182 
183  void SendToBack(ValueType* p)
184  {
185  Remove(p);
186  PushBack(p);
187  }
188 
189  // Appends the contents of the argument list to the front of this list;
190  // items are removed from the argument list.
191  void PushListToFront(List<T>& src)
192  {
193  if (!src.IsEmpty())
194  {
195  ValueType* pfirst = src.GetFirst();
196  ValueType* plast = src.GetLast();
197  src.Clear();
198  plast->pNext = Root.pNext;
199  pfirst->pPrev = (ValueType*)&Root;
200  Root.pNext->pPrev = plast;
201  Root.pNext = pfirst;
202  }
203  }
204 
205  void PushListToBack(List<T>& src)
206  {
207  if (!src.IsEmpty())
208  {
209  ValueType* pfirst = src.GetFirst();
210  ValueType* plast = src.GetLast();
211  src.Clear();
212  plast->pNext = (ValueType*)&Root;
213  pfirst->pPrev = Root.pPrev;
214  Root.pPrev->pNext = pfirst;
215  Root.pPrev = plast;
216  }
217  }
218 
219  // Removes all source list items after (and including) the 'pfirst' node from the
220  // source list and adds them to out list.
221  void PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst)
222  {
223  if (pfirst != &src.Root)
224  {
225  ValueType *plast = src.Root.pPrev;
226 
227  // Remove list remainder from source.
228  pfirst->pPrev->pNext = (ValueType*)&src.Root;
229  src.Root.pPrev = pfirst->pPrev;
230  // Add the rest of the items to list.
231  plast->pNext = Root.pNext;
232  pfirst->pPrev = (ValueType*)&Root;
233  Root.pNext->pPrev = plast;
234  Root.pNext = pfirst;
235  }
236  }
237 
238  // Removes all source list items up to but NOT including the 'pend' node from the
239  // source list and adds them to out list.
240  void PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail)
241  {
242  if (src.GetFirst() != ptail)
243  {
244  ValueType *pfirst = src.Root.pNext;
245  ValueType *plast = ptail->pPrev;
246 
247  // Remove list remainder from source.
248  ptail->pPrev = (ValueType*)&src.Root;
249  src.Root.pNext = ptail;
250 
251  // Add the rest of the items to list.
252  plast->pNext = Root.pNext;
253  pfirst->pPrev = (ValueType*)&Root;
254  Root.pNext->pPrev = plast;
255  Root.pNext = pfirst;
256  }
257  }
258 
259 
260  // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend',
261  // and adds them to out list. Note that source items MUST already be in the list.
262  void PushListItemsToFront(ValueType *pfirst, ValueType *pend)
263  {
264  if (pfirst != pend)
265  {
266  ValueType *plast = pend->pPrev;
267 
268  // Remove list remainder from source.
269  pfirst->pPrev->pNext = pend;
270  pend->pPrev = pfirst->pPrev;
271  // Add the rest of the items to list.
272  plast->pNext = Root.pNext;
273  pfirst->pPrev = (ValueType*)&Root;
274  Root.pNext->pPrev = plast;
275  Root.pNext = pfirst;
276  }
277  }
278 
279 
280  void Alloc_MoveTo(List<T>* pdest)
281  {
282  if (IsEmpty())
283  pdest->Clear();
284  else
285  {
286  pdest->Root.pNext = Root.pNext;
287  pdest->Root.pPrev = Root.pPrev;
288 
289  Root.pNext->pPrev = (ValueType*)&pdest->Root;
290  Root.pPrev->pNext = (ValueType*)&pdest->Root;
291  }
292  }
293 
294 
295 private:
296  // Copying is prohibited
297  List(const List<T>&);
298  const List<T>& operator = (const List<T>&);
299 
300  ListNode<B> Root;
301 };
302 
303 
304 // ***** List2
305 //
306 // Doubly linked intrusive list with data accessor.
307 // Used when the same data must be in two or more different linked lists.
308 // List2, unlike List keeps the whole ValueType as the root element
309 // (while List keeps only ListNode<T>).
310 //
311 // struct MyData
312 // {
313 // MyData* pPrev1;
314 // MyData* pNext1;
315 // MyData* pPrev2;
316 // MyData* pNext2;
317 // . . .
318 // };
319 //
320 // struct MyData_Accessor1
321 // {
322 // static void SetPrev(MyData* self, MyData* what) { self->pPrev1 = what; }
323 // static void SetNext(MyData* self, MyData* what) { self->pNext1 = what; }
324 // static const MyData* GetPrev(const MyData* self) { return self->pPrev1; }
325 // static const MyData* GetNext(const MyData* self) { return self->pNext1; }
326 // static MyData* GetPrev(MyData* self) { return self->pPrev1; }
327 // static MyData* GetNext(MyData* self) { return self->pNext1; }
328 // };
329 //
330 // struct MyData_Accessor2
331 // {
332 // static void SetPrev(MyData* self, MyData* what) { self->pPrev2 = what; }
333 // static void SetNext(MyData* self, MyData* what) { self->pNext2 = what; }
334 // static const MyData* GetPrev(const MyData* self) { return self->pPrev2; }
335 // static const MyData* GetNext(const MyData* self) { return self->pNext2; }
336 // static MyData* GetPrev(MyData* self) { return self->pPrev2; }
337 // static MyData* GetNext(MyData* self) { return self->pNext2; }
338 // };
339 //
340 // List2<MyData, MyData_Accessor1> list1;
341 // List2<MyData, MyData_Accessor2> list2;
342 //
343 //------------------------------------------------------------------------
344 template<class T, class Accessor> class List2
345 {
346 public:
347  typedef T ValueType;
348 
349  inline static void SetPrev(ValueType* self, ValueType* what) { Accessor::SetPrev(self, what); }
350  inline static void SetNext(ValueType* self, ValueType* what) { Accessor::SetNext(self, what); }
351  inline static const ValueType* GetPrev(const ValueType* self) { return Accessor::GetPrev(self); }
352  inline static const ValueType* GetNext(const ValueType* self) { return Accessor::GetNext(self); }
353  inline static ValueType* GetPrev(ValueType* self) { return Accessor::GetPrev(self); }
354  inline static ValueType* GetNext(ValueType* self) { return Accessor::GetNext(self); }
355 
356  List2()
357  {
358  SetPrev(&Root, &Root);
359  SetNext(&Root, &Root);
360  }
361 
362  void Clear()
363  {
364  SetPrev(&Root, &Root);
365  SetNext(&Root, &Root);
366  }
367 
368  const ValueType* GetFirst() const { return GetNext(&Root); }
369  const ValueType* GetLast () const { return GetPrev(&Root); }
370  ValueType* GetFirst() { return GetNext(&Root); }
371  ValueType* GetLast () { return GetPrev(&Root); }
372 
373  bool IsEmpty() const { return GetNext(&Root) == &Root; }
374  bool IsFirst(const ValueType* p) const { return p == GetNext(&Root); }
375  bool IsLast (const ValueType* p) const { return p == GetPrev(&Root); }
376  bool IsNull (const ValueType* p) const { return p == &Root; }
377 
378  void PushFront(ValueType* p)
379  {
380  SetNext(p, GetNext(&Root));
381  SetPrev(p, &Root);
382  SetPrev(GetNext(&Root), p);
383  SetNext(&Root, p);
384  }
385 
386  void PushBack(ValueType* p)
387  {
388  SetPrev(p, GetPrev(&Root));
389  SetNext(p, &Root);
390  SetNext(GetPrev(&Root), p);
391  SetPrev(&Root, p);
392  }
393 
394  void InsertBefore(ValueType* existing, ValueType* newOne)
395  {
396  ValueType* prev = GetPrev(existing);
397  SetNext(newOne, existing);
398  SetPrev(newOne, prev);
399  SetNext(prev, newOne);
400  SetPrev(existing, newOne);
401  }
402 
403  void InsertAfter(ValueType* existing, ValueType* newOne)
404  {
405  ValueType* next = GetNext(existing);
406  SetPrev(newOne, existing);
407  SetNext(newOne, next);
408  SetPrev(next, newOne);
409  SetNext(existing, newOne);
410  }
411 
412  static void Remove(ValueType* p)
413  {
414  SetNext(GetPrev(p), GetNext(p));
415  SetPrev(GetNext(p), GetPrev(p));
416  }
417 
418  void BringToFront(ValueType* p)
419  {
420  Remove(p);
421  PushFront(p);
422  }
423 
424  void SendToBack(ValueType* p)
425  {
426  Remove(p);
427  PushBack(p);
428  }
429 
430  // Appends the contents of the argument list to the front of this list;
431  // items are removed from the argument list.
432  void PushListToFront(List2<T,Accessor>& src)
433  {
434  if (!src.IsEmpty())
435  {
436  ValueType* pfirst = src.GetFirst();
437  ValueType* plast = src.GetLast();
438  src.Clear();
439  SetNext(plast, GetNext(&Root));
440  SetPrev(pfirst, &Root);
441  SetPrev(GetNext(&Root), plast);
442  SetNext(&Root, pfirst);
443  }
444  }
445 
446 private:
447  // Copying is prohibited
448  List2(const List2<T,Accessor>&);
449  const List2<T,Accessor>& operator = (const List2<T,Accessor>&);
450 
451  ValueType Root;
452 };
453 
454 
455 // ***** FreeListElements
456 //
457 // Remove all elements in the list and free them in the allocator
458 //------------------------------------------------------------------------
459 template<class List, class Allocator>
460 void FreeListElements(List& list, Allocator& allocator)
461 {
462  typename List::ValueType* self = list.GetFirst();
463  while(!list.IsNull(self))
464  {
465  typename List::ValueType* next = list.GetNext(self);
466  allocator.Free(self);
467  self = next;
468  }
469  list.Clear();
470 }
471 
472 } // Scaleform
473 
474 #endif
Definition: gamekitcrowddispersion.h:20