My Project
wxlist.h
1 //------------------------------------------------------------------------------
2 // File: WXList.h
3 //
4 // Desc: DirectShow base classes - defines a non-MFC generic template list
5 // class.
6 //
7 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //------------------------------------------------------------------------------
9 
10 
11 /* A generic list of pointers to objects.
12  No storage management or copying is done on the objects pointed to.
13  Objectives: avoid using MFC libraries in ndm kernel mode and
14  provide a really useful list type.
15 
16  The class is thread safe in that separate threads may add and
17  delete items in the list concurrently although the application
18  must ensure that constructor and destructor access is suitably
19  synchronised. An application can cause deadlock with operations
20  which use two lists by simultaneously calling
21  list1->Operation(list2) and list2->Operation(list1). So don't!
22 
23  The names must not conflict with MFC classes as an application
24  may use both.
25  */
26 #pragma once
27 
28 #ifndef __WXLIST__
29 #define __WXLIST__
30 
31  /* A POSITION represents (in some fashion that's opaque) a cursor
32  on the list that can be set to identify any element. NULL is
33  a valid value and several operations regard NULL as the position
34  "one step off the end of the list". (In an n element list there
35  are n+1 places to insert and NULL is that "n+1-th" value).
36  The POSITION of an element in the list is only invalidated if
37  that element is deleted. Move operations may mean that what
38  was a valid POSITION in one list is now a valid POSITION in
39  a different list.
40 
41  Some operations which at first sight are illegal are allowed as
42  harmless no-ops. For instance RemoveHead is legal on an empty
43  list and it returns NULL. This allows an atomic way to test if
44  there is an element there, and if so, get it. The two operations
45  AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper).
46 
47  Single element operations return POSITIONs, non-NULL means it worked.
48  whole list operations return a BOOL. TRUE means it all worked.
49 
50  This definition is the same as the POSITION type for MFCs, so we must
51  avoid defining it twice.
52  */
53 #ifndef __AFX_H__
54 struct __POSITION { int unused; };
55 typedef __POSITION* POSITION;
56 #endif
57 
58 const int DEFAULTCACHE = 10; /* Default node object cache size */
59 
60 /* A class representing one node in a list.
61  Each node knows a pointer to it's adjacent nodes and also a pointer
62  to the object that it looks after.
63  All of these pointers can be retrieved or set through member functions.
64 */
65 class CBaseList
66 #ifdef DEBUG
67  : public CBaseObject
68 #endif
69 {
70  /* Making these classes inherit from CBaseObject does nothing
71  functionally but it allows us to check there are no memory
72  leaks in debug builds.
73  */
74 
75 public:
76 
77 #ifdef DEBUG
78  class CNode : public CBaseObject {
79 #else
80  class CNode {
81 #endif
82 
83  CNode *m_pPrev; /* Previous node in the list */
84  CNode *m_pNext; /* Next node in the list */
85  void *m_pObject; /* Pointer to the object */
86 
87  public:
88 
89  /* Constructor - initialise the object's pointers */
90  CNode()
91 #ifdef DEBUG
92  : CBaseObject(NAME("List node"))
93 #endif
94  {
95  };
96 
97 
98  /* Return the previous node before this one */
99  CNode *Prev() const { return m_pPrev; };
100 
101 
102  /* Return the next node after this one */
103  CNode *Next() const { return m_pNext; };
104 
105 
106  /* Set the previous node before this one */
107  void SetPrev(CNode *p) { m_pPrev = p; };
108 
109 
110  /* Set the next node after this one */
111  void SetNext(CNode *p) { m_pNext = p; };
112 
113 
114  /* Get the pointer to the object for this node */
115  void *GetData() const { return m_pObject; };
116 
117 
118  /* Set the pointer to the object for this node */
119  void SetData(void *p) { m_pObject = p; };
120  };
121 
123  {
124  public:
125  CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize),
126  m_pHead(NULL),
127  m_iUsed(0)
128  {};
129  ~CNodeCache() {
130  CNode *pNode = m_pHead;
131  while (pNode) {
132  CNode *pCurrent = pNode;
133  pNode = pNode->Next();
134  delete pCurrent;
135  }
136  };
137  void AddToCache(CNode *pNode)
138  {
139  if (m_iUsed < m_iCacheSize) {
140  pNode->SetNext(m_pHead);
141  m_pHead = pNode;
142  m_iUsed++;
143  } else {
144  delete pNode;
145  }
146  };
147  CNode *RemoveFromCache()
148  {
149  CNode *pNode = m_pHead;
150  if (pNode != NULL) {
151  m_pHead = pNode->Next();
152  m_iUsed--;
153  ASSERT(m_iUsed >= 0);
154  } else {
155  ASSERT(m_iUsed == 0);
156  }
157  return pNode;
158  };
159  private:
160  INT m_iCacheSize;
161  INT m_iUsed;
162  CNode *m_pHead;
163  };
164 
165 protected:
166 
167  CNode* m_pFirst; /* Pointer to first node in the list */
168  CNode* m_pLast; /* Pointer to the last node in the list */
169  LONG m_Count; /* Number of nodes currently in the list */
170 
171 private:
172 
173  CNodeCache m_Cache; /* Cache of unused node pointers */
174 
175 private:
176 
177  /* These override the default copy constructor and assignment
178  operator for all list classes. They are in the private class
179  declaration section so that anybody trying to pass a list
180  object by value will generate a compile time error of
181  "cannot access the private member function". If these were
182  not here then the compiler will create default constructors
183  and assignment operators which when executed first take a
184  copy of all member variables and then during destruction
185  delete them all. This must not be done for any heap
186  allocated data.
187  */
188  CBaseList(const CBaseList &refList);
189  CBaseList &operator=(const CBaseList &refList);
190 
191 public:
192 
193  CBaseList(TCHAR *pName,
194  INT iItems);
195 
196  CBaseList(TCHAR *pName);
197 #ifdef UNICODE
198  CBaseList(CHAR *pName,
199  INT iItems);
200 
201  CBaseList(CHAR *pName);
202 #endif
203  ~CBaseList();
204 
205  /* Remove all the nodes from *this i.e. make the list empty */
206  void RemoveAll();
207 
208 
209  /* Return a cursor which identifies the first element of *this */
210  POSITION GetHeadPositionI() const;
211 
212 
213  /* Return a cursor which identifies the last element of *this */
214  POSITION GetTailPositionI() const;
215 
216 
217  /* Return the number of objects in *this */
218  int GetCountI() const;
219 
220 protected:
221  /* Return the pointer to the object at rp,
222  Update rp to the next node in *this
223  but make it NULL if it was at the end of *this.
224  This is a wart retained for backwards compatibility.
225  GetPrev is not implemented.
226  Use Next, Prev and Get separately.
227  */
228  void *GetNextI(POSITION& rp) const;
229 
230 
231  /* Return a pointer to the object at p
232  Asking for the object at NULL will return NULL harmlessly.
233  */
234  void *GetI(POSITION p) const;
235 
236 public:
237  /* return the next / prev position in *this
238  return NULL when going past the end/start.
239  Next(NULL) is same as GetHeadPosition()
240  Prev(NULL) is same as GetTailPosition()
241  An n element list therefore behaves like a n+1 element
242  cycle with NULL at the start/end.
243 
244  !!WARNING!! - This handling of NULL is DIFFERENT from GetNext.
245 
246  Some reasons are:
247  1. For a list of n items there are n+1 positions to insert
248  These are conveniently encoded as the n POSITIONs and NULL.
249  2. If you are keeping a list sorted (fairly common) and you
250  search forward for an element to insert before and don't
251  find it you finish up with NULL as the element before which
252  to insert. You then want that NULL to be a valid POSITION
253  so that you can insert before it and you want that insertion
254  point to mean the (n+1)-th one that doesn't have a POSITION.
255  (symmetrically if you are working backwards through the list).
256  3. It simplifies the algebra which the methods generate.
257  e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x)
258  in ALL cases. All the other arguments probably are reflections
259  of the algebraic point.
260  */
261  POSITION Next(POSITION pos) const
262  {
263  if (pos == NULL) {
264  return (POSITION) m_pFirst;
265  }
266  CNode *pn = (CNode *) pos;
267  return (POSITION) pn->Next();
268  } //Next
269 
270  // See Next
271  POSITION Prev(POSITION pos) const
272  {
273  if (pos == NULL) {
274  return (POSITION) m_pLast;
275  }
276  CNode *pn = (CNode *) pos;
277  return (POSITION) pn->Prev();
278  } //Prev
279 
280 
281  /* Return the first position in *this which holds the given
282  pointer. Return NULL if the pointer was not not found.
283  */
284 protected:
285  POSITION FindI( void * pObj) const;
286 
287  /* Remove the first node in *this (deletes the pointer to its
288  object from the list, does not free the object itself).
289  Return the pointer to its object.
290  If *this was already empty it will harmlessly return NULL.
291  */
292  void *RemoveHeadI();
293 
294 
295  /* Remove the last node in *this (deletes the pointer to its
296  object from the list, does not free the object itself).
297  Return the pointer to its object.
298  If *this was already empty it will harmlessly return NULL.
299  */
300  void *RemoveTailI();
301 
302 
303  /* Remove the node identified by p from the list (deletes the pointer
304  to its object from the list, does not free the object itself).
305  Asking to Remove the object at NULL will harmlessly return NULL.
306  Return the pointer to the object removed.
307  */
308  void *RemoveI(POSITION p);
309 
310  /* Add single object *pObj to become a new last element of the list.
311  Return the new tail position, NULL if it fails.
312  If you are adding a COM objects, you might want AddRef it first.
313  Other existing POSITIONs in *this are still valid
314  */
315  POSITION AddTailI(void * pObj);
316 public:
317 
318 
319  /* Add all the elements in *pList to the tail of *this.
320  This duplicates all the nodes in *pList (i.e. duplicates
321  all its pointers to objects). It does not duplicate the objects.
322  If you are adding a list of pointers to a COM object into the list
323  it's a good idea to AddRef them all it when you AddTail it.
324  Return TRUE if it all worked, FALSE if it didn't.
325  If it fails some elements may have been added.
326  Existing POSITIONs in *this are still valid
327 
328  If you actually want to MOVE the elements, use MoveToTail instead.
329  */
330  BOOL AddTail(CBaseList *pList);
331 
332 
333  /* Mirror images of AddHead: */
334 
335  /* Add single object to become a new first element of the list.
336  Return the new head position, NULL if it fails.
337  Existing POSITIONs in *this are still valid
338  */
339 protected:
340  POSITION AddHeadI(void * pObj);
341 public:
342 
343  /* Add all the elements in *pList to the head of *this.
344  Same warnings apply as for AddTail.
345  Return TRUE if it all worked, FALSE if it didn't.
346  If it fails some of the objects may have been added.
347 
348  If you actually want to MOVE the elements, use MoveToHead instead.
349  */
350  BOOL AddHead(CBaseList *pList);
351 
352 
353  /* Add the object *pObj to *this after position p in *this.
354  AddAfter(NULL,x) adds x to the start - equivalent to AddHead
355  Return the position of the object added, NULL if it failed.
356  Existing POSITIONs in *this are undisturbed, including p.
357  */
358 protected:
359  POSITION AddAfterI(POSITION p, void * pObj);
360 public:
361 
362  /* Add the list *pList to *this after position p in *this
363  AddAfter(NULL,x) adds x to the start - equivalent to AddHead
364  Return TRUE if it all worked, FALSE if it didn't.
365  If it fails, some of the objects may be added
366  Existing POSITIONs in *this are undisturbed, including p.
367  */
368  BOOL AddAfter(POSITION p, CBaseList *pList);
369 
370 
371  /* Mirror images:
372  Add the object *pObj to this-List after position p in *this.
373  AddBefore(NULL,x) adds x to the end - equivalent to AddTail
374  Return the position of the new object, NULL if it fails
375  Existing POSITIONs in *this are undisturbed, including p.
376  */
377  protected:
378  POSITION AddBeforeI(POSITION p, void * pObj);
379  public:
380 
381  /* Add the list *pList to *this before position p in *this
382  AddAfter(NULL,x) adds x to the start - equivalent to AddHead
383  Return TRUE if it all worked, FALSE if it didn't.
384  If it fails, some of the objects may be added
385  Existing POSITIONs in *this are undisturbed, including p.
386  */
387  BOOL AddBefore(POSITION p, CBaseList *pList);
388 
389 
390  /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x)
391  even in cases where p is NULL or Next(p) is NULL.
392  Similarly for mirror images etc.
393  This may make it easier to argue about programs.
394  */
395 
396 
397 
398  /* The following operations do not copy any elements.
399  They move existing blocks of elements around by switching pointers.
400  They are fairly efficient for long lists as for short lists.
401  (Alas, the Count slows things down).
402 
403  They split the list into two parts.
404  One part remains as the original list, the other part
405  is appended to the second list. There are eight possible
406  variations:
407  Split the list {after/before} a given element
408  keep the {head/tail} portion in the original list
409  append the rest to the {head/tail} of the new list.
410 
411  Since After is strictly equivalent to Before Next
412  we are not in serious need of the Before/After variants.
413  That leaves only four.
414 
415  If you are processing a list left to right and dumping
416  the bits that you have processed into another list as
417  you go, the Tail/Tail variant gives the most natural result.
418  If you are processing in reverse order, Head/Head is best.
419 
420  By using NULL positions and empty lists judiciously either
421  of the other two can be built up in two operations.
422 
423  The definition of NULL (see Next/Prev etc) means that
424  degenerate cases include
425  "move all elements to new list"
426  "Split a list into two lists"
427  "Concatenate two lists"
428  (and quite a few no-ops)
429 
430  !!WARNING!! The type checking won't buy you much if you get list
431  positions muddled up - e.g. use a POSITION that's in a different
432  list and see what a mess you get!
433  */
434 
435  /* Split *this after position p in *this
436  Retain as *this the tail portion of the original *this
437  Add the head portion to the tail end of *pList
438  Return TRUE if it all worked, FALSE if it didn't.
439 
440  e.g.
441  foo->MoveToTail(foo->GetHeadPosition(), bar);
442  moves one element from the head of foo to the tail of bar
443  foo->MoveToTail(NULL, bar);
444  is a no-op, returns NULL
445  foo->MoveToTail(foo->GetTailPosition, bar);
446  concatenates foo onto the end of bar and empties foo.
447 
448  A better, except excessively long name might be
449  MoveElementsFromHeadThroughPositionToOtherTail
450  */
451  BOOL MoveToTail(POSITION pos, CBaseList *pList);
452 
453 
454  /* Mirror image:
455  Split *this before position p in *this.
456  Retain in *this the head portion of the original *this
457  Add the tail portion to the start (i.e. head) of *pList
458 
459  e.g.
460  foo->MoveToHead(foo->GetTailPosition(), bar);
461  moves one element from the tail of foo to the head of bar
462  foo->MoveToHead(NULL, bar);
463  is a no-op, returns NULL
464  foo->MoveToHead(foo->GetHeadPosition, bar);
465  concatenates foo onto the start of bar and empties foo.
466  */
467  BOOL MoveToHead(POSITION pos, CBaseList *pList);
468 
469 
470  /* Reverse the order of the [pointers to] objects in *this
471  */
472  void Reverse();
473 
474 
475  /* set cursor to the position of each element of list in turn */
476  #define TRAVERSELIST(list, cursor) \
477  for ( cursor = (list).GetHeadPosition() \
478  ; cursor!=NULL \
479  ; cursor = (list).Next(cursor) \
480  )
481 
482 
483  /* set cursor to the position of each element of list in turn
484  in reverse order
485  */
486  #define REVERSETRAVERSELIST(list, cursor) \
487  for ( cursor = (list).GetTailPosition() \
488  ; cursor!=NULL \
489  ; cursor = (list).Prev(cursor) \
490  )
491 
492 }; // end of class declaration
493 
494 template<class OBJECT> class CGenericList : public CBaseList
495 {
496 public:
497  CGenericList(TCHAR *pName,
498  INT iItems,
499  BOOL bLock = TRUE,
500  BOOL bAlert = FALSE) :
501  CBaseList(pName, iItems) {
502  UNREFERENCED_PARAMETER(bAlert);
503  UNREFERENCED_PARAMETER(bLock);
504  };
505  CGenericList(TCHAR *pName) :
506  CBaseList(pName) {
507  };
508 
509  POSITION GetHeadPosition() const { return (POSITION)m_pFirst; }
510  POSITION GetTailPosition() const { return (POSITION)m_pLast; }
511  int GetCount() const { return m_Count; }
512 
513  OBJECT *GetNext(POSITION& rp) const { return (OBJECT *) GetNextI(rp); }
514 
515  OBJECT *Get(POSITION p) const { return (OBJECT *) GetI(p); }
516  OBJECT *GetHead() const { return Get(GetHeadPosition()); }
517 
518  OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); }
519 
520  OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); }
521 
522  OBJECT *Remove(POSITION p) { return (OBJECT *) RemoveI(p); }
523  POSITION AddBefore(POSITION p, OBJECT * pObj) { return AddBeforeI(p, pObj); }
524  POSITION AddAfter(POSITION p, OBJECT * pObj) { return AddAfterI(p, pObj); }
525  POSITION AddHead(OBJECT * pObj) { return AddHeadI(pObj); }
526  POSITION AddTail(OBJECT * pObj) { return AddTailI(pObj); }
527  BOOL AddTail(CGenericList<OBJECT> *pList)
528  { return CBaseList::AddTail((CBaseList *) pList); }
529  BOOL AddHead(CGenericList<OBJECT> *pList)
530  { return CBaseList::AddHead((CBaseList *) pList); }
531  BOOL AddAfter(POSITION p, CGenericList<OBJECT> *pList)
532  { return CBaseList::AddAfter(p, (CBaseList *) pList); };
533  BOOL AddBefore(POSITION p, CGenericList<OBJECT> *pList)
534  { return CBaseList::AddBefore(p, (CBaseList *) pList); };
535  POSITION Find( OBJECT * pObj) const { return FindI(pObj); }
536 }; // end of class declaration
537 
538 
539 
540 /* These define the standard list types */
541 
544 
545 #endif /* __WXLIST__ */
546 
Definition: combase.h:159
Definition: wxlist.h:80
Definition: wxlist.h:54
Definition: wxlist.h:122
Definition: wxlist.h:65
Definition: wxlist.h:494