Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
OVR_List.h
Go to the documentation of this file.
1 /************************************************************************************
2 
3 PublicHeader: OVR
4 Filename : OVR_List.h
5 Content : Template implementation for doubly-connected linked List
6 Created : September 19, 2012
7 Notes :
8 
9 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
10 
11 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
12 you may not use the Oculus VR Rift SDK except in compliance with the License,
13 which is provided at the time of installation or download, or which
14 otherwise accompanies this software in either electronic or hard copy form.
15 
16 You may obtain a copy of the License at
17 
18 http://www.oculusvr.com/licenses/LICENSE-3.1
19 
20 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
21 distributed under the License is distributed on an "AS IS" BASIS,
22 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 See the License for the specific language governing permissions and
24 limitations under the License.
25 
26 ************************************************************************************/
27 
28 #ifndef OVR_List_h
29 #define OVR_List_h
30 
31 #include "OVR_Types.h"
32 
33 namespace OVR {
34 
35 //-----------------------------------------------------------------------------------
36 // ***** ListNode
37 //
38 // Base class for the elements of the intrusive linked list.
39 // To store elements in the List do:
40 //
41 // struct MyData : ListNode<MyData>
42 // {
43 // . . .
44 // };
45 
46 template<class T>
47 struct ListNode
48 {
49  union {
50  T* pPrev;
51  void* pVoidPrev;
52  };
53  union {
54  T* pNext;
55  void* pVoidNext;
56  };
57 
58  void RemoveNode()
59  {
60  pPrev->pNext = pNext;
61  pNext->pPrev = pPrev;
62  }
63 
64  // Removes us from the list and inserts pnew there instead.
65  void ReplaceNodeWith(T* pnew)
66  {
67  pPrev->pNext = pnew;
68  pNext->pPrev = pnew;
69  pnew->pPrev = pPrev;
70  pnew->pNext = pNext;
71  }
72 
73  // Inserts the argument linked list node after us in the list.
74  void InsertNodeAfter(T* p)
75  {
76  p->pPrev = pNext->pPrev; // this
77  p->pNext = pNext;
78  pNext->pPrev = p;
79  pNext = p;
80  }
81  // Inserts the argument linked list node before us in the list.
82  void InsertNodeBefore(T* p)
83  {
84  p->pNext = pNext->pPrev; // this
85  p->pPrev = pPrev;
86  pPrev->pNext = p;
87  pPrev = p;
88  }
89 
91  {
92  pdest->pNext = pNext;
93  pdest->pPrev = pPrev;
94  pPrev->pNext = (T*)pdest;
95  pNext->pPrev = (T*)pdest;
96  }
97 };
98 
99 
100 //------------------------------------------------------------------------
101 // ***** List
102 //
103 // Doubly linked intrusive list.
104 // The data type must be derived from ListNode.
105 //
106 // Adding: PushFront(), PushBack().
107 // Removing: Remove() - the element must be in the list!
108 // Moving: BringToFront(), SendToBack() - the element must be in the list!
109 //
110 // Iterating:
111 // MyData* data = MyList.GetFirst();
112 // while (!MyList.IsNull(data))
113 // {
114 // . . .
115 // data = MyList.GetNext(data);
116 // }
117 //
118 // Removing:
119 // MyData* data = MyList.GetFirst();
120 // while (!MyList.IsNull(data))
121 // {
122 // MyData* next = MyList.GetNext(data);
123 // if (ToBeRemoved(data))
124 // MyList.Remove(data);
125 // data = next;
126 // }
127 //
128 
129 // List<> represents a doubly-linked list of T, where each T must derive
130 // from ListNode<B>. B specifies the base class that was directly
131 // derived from ListNode, and is only necessary if there is an intermediate
132 // inheritance chain.
133 
134 template<class T, class B = T> class List
135 {
136 public:
137  typedef T ValueType;
138 
140  {
141  Root.pNext = Root.pPrev = (ValueType*)&Root;
142  }
143 
144  void Clear()
145  {
146  Root.pNext = Root.pPrev = (ValueType*)&Root;
147  }
148 
149  const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; }
150  const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; }
151  ValueType* GetFirst() { return (ValueType*)Root.pNext; }
152  ValueType* GetLast () { return (ValueType*)Root.pPrev; }
153 
154  // Determine if list is empty (i.e.) points to itself.
155  // Go through void* access to avoid issues with strict-aliasing optimizing out the
156  // access after RemoveNode(), etc.
157  bool IsEmpty() const { return Root.pVoidNext == (const T*)(const B*)&Root; }
158  bool IsFirst(const ValueType* p) const { return p == Root.pNext; }
159  bool IsLast (const ValueType* p) const { return p == Root.pPrev; }
160  bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; }
161 
162  inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; }
163  inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; }
164  inline static ValueType* GetPrev( ValueType* p) { return (ValueType*)p->pPrev; }
165  inline static ValueType* GetNext( ValueType* p) { return (ValueType*)p->pNext; }
166 
168  {
169  p->pNext = Root.pNext;
170  p->pPrev = (ValueType*)&Root;
171  Root.pNext->pPrev = p;
172  Root.pNext = p;
173  }
174 
176  {
177  p->pPrev = Root.pPrev;
178  p->pNext = (ValueType*)&Root;
179  Root.pPrev->pNext = p;
180  Root.pPrev = p;
181  }
182 
183  static void Remove(ValueType* p)
184  {
185  p->pPrev->pNext = p->pNext;
186  p->pNext->pPrev = p->pPrev;
187  }
188 
190  {
191  Remove(p);
192  PushFront(p);
193  }
194 
196  {
197  Remove(p);
198  PushBack(p);
199  }
200 
201  // Appends the contents of the argument list to the front of this list;
202  // items are removed from the argument list.
204  {
205  if (!src.IsEmpty())
206  {
207  ValueType* pfirst = src.GetFirst();
208  ValueType* plast = src.GetLast();
209  src.Clear();
210  plast->pNext = Root.pNext;
211  pfirst->pPrev = (ValueType*)&Root;
212  Root.pNext->pPrev = plast;
213  Root.pNext = pfirst;
214  }
215  }
216 
218  {
219  if (!src.IsEmpty())
220  {
221  ValueType* pfirst = src.GetFirst();
222  ValueType* plast = src.GetLast();
223  src.Clear();
224  plast->pNext = (ValueType*)&Root;
225  pfirst->pPrev = Root.pPrev;
226  Root.pPrev->pNext = pfirst;
227  Root.pPrev = plast;
228  }
229  }
230 
231  // Removes all source list items after (and including) the 'pfirst' node from the
232  // source list and adds them to out list.
234  {
235  if (pfirst != &src.Root)
236  {
237  ValueType *plast = src.Root.pPrev;
238 
239  // Remove list remainder from source.
240  pfirst->pPrev->pNext = (ValueType*)&src.Root;
241  src.Root.pPrev = pfirst->pPrev;
242  // Add the rest of the items to list.
243  plast->pNext = Root.pNext;
244  pfirst->pPrev = (ValueType*)&Root;
245  Root.pNext->pPrev = plast;
246  Root.pNext = pfirst;
247  }
248  }
249 
250  // Removes all source list items up to but NOT including the 'pend' node from the
251  // source list and adds them to out list.
253  {
254  if (src.GetFirst() != ptail)
255  {
256  ValueType *pfirst = src.Root.pNext;
257  ValueType *plast = ptail->pPrev;
258 
259  // Remove list remainder from source.
260  ptail->pPrev = (ValueType*)&src.Root;
261  src.Root.pNext = ptail;
262 
263  // Add the rest of the items to list.
264  plast->pNext = Root.pNext;
265  pfirst->pPrev = (ValueType*)&Root;
266  Root.pNext->pPrev = plast;
267  Root.pNext = pfirst;
268  }
269  }
270 
271 
272  // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend',
273  // and adds them to out list. Note that source items MUST already be in the list.
275  {
276  if (pfirst != pend)
277  {
278  ValueType *plast = pend->pPrev;
279 
280  // Remove list remainder from source.
281  pfirst->pPrev->pNext = pend;
282  pend->pPrev = pfirst->pPrev;
283  // Add the rest of the items to list.
284  plast->pNext = Root.pNext;
285  pfirst->pPrev = (ValueType*)&Root;
286  Root.pNext->pPrev = plast;
287  Root.pNext = pfirst;
288  }
289  }
290 
291 
292  void Alloc_MoveTo(List<T>* pdest)
293  {
294  if (IsEmpty())
295  pdest->Clear();
296  else
297  {
298  pdest->Root.pNext = Root.pNext;
299  pdest->Root.pPrev = Root.pPrev;
300 
301  Root.pNext->pPrev = (ValueType*)&pdest->Root;
302  Root.pPrev->pNext = (ValueType*)&pdest->Root;
303  }
304  }
305 
306 
307 private:
308  // Copying is prohibited
309  List(const List<T>&);
310  const List<T>& operator = (const List<T>&);
311 
313 };
314 
315 
316 //------------------------------------------------------------------------
317 // ***** FreeListElements
318 //
319 // Remove all elements in the list and free them in the allocator
320 
321 template<class List, class Allocator>
322 void FreeListElements(List& list, Allocator& allocator)
323 {
324  typename List::ValueType* self = list.GetFirst();
325  while(!list.IsNull(self))
326  {
327  typename List::ValueType* next = list.GetNext(self);
328  allocator.Free(self);
329  self = next;
330  }
331  list.Clear();
332 }
333 
334 } // OVR
335 
336 #endif
void ReplaceNodeWith(T *pnew)
Definition: OVR_List.h:65
T ValueType
Definition: OVR_List.h:137
bool IsEmpty() const
Definition: OVR_List.h:157
bool IsLast(const ValueType *p) const
Definition: OVR_List.h:159
bool IsFirst(const ValueType *p) const
Definition: OVR_List.h:158
void PushListToFront(List< T > &src)
Definition: OVR_List.h:203
ListNode< B > Root
Definition: OVR_List.h:312
void RemoveNode()
Definition: OVR_List.h:58
void BringToFront(ValueType *p)
Definition: OVR_List.h:189
void PushListItemsToFront(ValueType *pfirst, ValueType *pend)
Definition: OVR_List.h:274
void PushFront(ValueType *p)
Definition: OVR_List.h:167
void PushPrecedingListItemsToFront(List< T > &src, ValueType *ptail)
Definition: OVR_List.h:252
void SendToBack(ValueType *p)
Definition: OVR_List.h:195
static void Remove(ValueType *p)
Definition: OVR_List.h:183
const ValueType * GetLast() const
Definition: OVR_List.h:150
static ValueType * GetNext(ValueType *p)
Definition: OVR_List.h:165
const ValueType * GetFirst() const
Definition: OVR_List.h:149
bool IsNull(const ValueType *p) const
Definition: OVR_List.h:160
void InsertNodeBefore(T *p)
Definition: OVR_List.h:82
void PushFollowingListItemsToFront(List< T > &src, ValueType *pfirst)
Definition: OVR_List.h:233
void Alloc_MoveTo(List< T > *pdest)
Definition: OVR_List.h:292
void PushBack(ValueType *p)
Definition: OVR_List.h:175
void FreeListElements(List &list, Allocator &allocator)
Definition: OVR_List.h:322
void InsertNodeAfter(T *p)
Definition: OVR_List.h:74
ValueType * GetLast()
Definition: OVR_List.h:152
static const ValueType * GetPrev(const ValueType *p)
Definition: OVR_List.h:162
void PushListToBack(List< T > &src)
Definition: OVR_List.h:217
ValueType * GetFirst()
Definition: OVR_List.h:151
static const ValueType * GetNext(const ValueType *p)
Definition: OVR_List.h:163
static ValueType * GetPrev(ValueType *p)
Definition: OVR_List.h:164
virtual void Free(void *p)=0
void Clear()
Definition: OVR_List.h:144
void Alloc_MoveTo(ListNode< T > *pdest)
Definition: OVR_List.h:90
const List< T > & operator=(const List< T > &)