wxlist.h
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:19k
源码类别:
P2P编程
开发平台:
Visual C++
- //------------------------------------------------------------------------------
- // File: WXList.h
- //
- // Desc: DirectShow base classes - defines a non-MFC generic template list
- // class.
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
- /* A generic list of pointers to objects.
- No storage management or copying is done on the objects pointed to.
- Objectives: avoid using MFC libraries in ndm kernel mode and
- provide a really useful list type.
- The class is thread safe in that separate threads may add and
- delete items in the list concurrently although the application
- must ensure that constructor and destructor access is suitably
- synchronised. An application can cause deadlock with operations
- which use two lists by simultaneously calling
- list1->Operation(list2) and list2->Operation(list1). So don't!
- The names must not conflict with MFC classes as an application
- may use both.
- */
- #ifndef __WXLIST__
- #define __WXLIST__
- /* A POSITION represents (in some fashion that's opaque) a cursor
- on the list that can be set to identify any element. NULL is
- a valid value and several operations regard NULL as the position
- "one step off the end of the list". (In an n element list there
- are n+1 places to insert and NULL is that "n+1-th" value).
- The POSITION of an element in the list is only invalidated if
- that element is deleted. Move operations may mean that what
- was a valid POSITION in one list is now a valid POSITION in
- a different list.
- Some operations which at first sight are illegal are allowed as
- harmless no-ops. For instance RemoveHead is legal on an empty
- list and it returns NULL. This allows an atomic way to test if
- there is an element there, and if so, get it. The two operations
- AddTail and RemoveHead thus implement a MONITOR (See Hoare's paper).
- Single element operations return POSITIONs, non-NULL means it worked.
- whole list operations return a BOOL. TRUE means it all worked.
- This definition is the same as the POSITION type for MFCs, so we must
- avoid defining it twice.
- */
- #ifndef __AFX_H__
- struct __POSITION { int unused; };
- typedef __POSITION* POSITION;
- #endif
- const int DEFAULTCACHE = 10; /* Default node object cache size */
- /* A class representing one node in a list.
- Each node knows a pointer to it's adjacent nodes and also a pointer
- to the object that it looks after.
- All of these pointers can be retrieved or set through member functions.
- */
- class CBaseList
- #ifdef DEBUG
- : public CBaseObject
- #endif
- {
- /* Making these classes inherit from CBaseObject does nothing
- functionally but it allows us to check there are no memory
- leaks in debug builds.
- */
- public:
- #ifdef DEBUG
- class CNode : public CBaseObject {
- #else
- class CNode {
- #endif
- CNode *m_pPrev; /* Previous node in the list */
- CNode *m_pNext; /* Next node in the list */
- void *m_pObject; /* Pointer to the object */
- public:
- /* Constructor - initialise the object's pointers */
- CNode()
- #ifdef DEBUG
- : CBaseObject(NAME("List node"))
- #endif
- {
- };
- /* Return the previous node before this one */
- CNode *Prev() const { return m_pPrev; };
- /* Return the next node after this one */
- CNode *Next() const { return m_pNext; };
- /* Set the previous node before this one */
- void SetPrev(CNode *p) { m_pPrev = p; };
- /* Set the next node after this one */
- void SetNext(CNode *p) { m_pNext = p; };
- /* Get the pointer to the object for this node */
- void *GetData() const { return m_pObject; };
- /* Set the pointer to the object for this node */
- void SetData(void *p) { m_pObject = p; };
- };
- class CNodeCache
- {
- public:
- CNodeCache(INT iCacheSize) : m_iCacheSize(iCacheSize),
- m_pHead(NULL),
- m_iUsed(0)
- {};
- ~CNodeCache() {
- CNode *pNode = m_pHead;
- while (pNode) {
- CNode *pCurrent = pNode;
- pNode = pNode->Next();
- delete pCurrent;
- }
- };
- void AddToCache(CNode *pNode)
- {
- if (m_iUsed < m_iCacheSize) {
- pNode->SetNext(m_pHead);
- m_pHead = pNode;
- m_iUsed++;
- } else {
- delete pNode;
- }
- };
- CNode *RemoveFromCache()
- {
- CNode *pNode = m_pHead;
- if (pNode != NULL) {
- m_pHead = pNode->Next();
- m_iUsed--;
- ASSERT(m_iUsed >= 0);
- } else {
- ASSERT(m_iUsed == 0);
- }
- return pNode;
- };
- private:
- INT m_iCacheSize;
- INT m_iUsed;
- CNode *m_pHead;
- };
- protected:
- CNode* m_pFirst; /* Pointer to first node in the list */
- CNode* m_pLast; /* Pointer to the last node in the list */
- LONG m_Count; /* Number of nodes currently in the list */
- private:
- CNodeCache m_Cache; /* Cache of unused node pointers */
- private:
- /* These override the default copy constructor and assignment
- operator for all list classes. They are in the private class
- declaration section so that anybody trying to pass a list
- object by value will generate a compile time error of
- "cannot access the private member function". If these were
- not here then the compiler will create default constructors
- and assignment operators which when executed first take a
- copy of all member variables and then during destruction
- delete them all. This must not be done for any heap
- allocated data.
- */
- CBaseList(const CBaseList &refList);
- CBaseList &operator=(const CBaseList &refList);
- public:
- CBaseList(TCHAR *pName,
- INT iItems);
- CBaseList(TCHAR *pName);
- #ifdef UNICODE
- CBaseList(CHAR *pName,
- INT iItems);
- CBaseList(CHAR *pName);
- #endif
- ~CBaseList();
- /* Remove all the nodes from *this i.e. make the list empty */
- void RemoveAll();
- /* Return a cursor which identifies the first element of *this */
- POSITION GetHeadPositionI() const;
- /* Return a cursor which identifies the last element of *this */
- POSITION GetTailPositionI() const;
- /* Return the number of objects in *this */
- int GetCountI() const;
- protected:
- /* Return the pointer to the object at rp,
- Update rp to the next node in *this
- but make it NULL if it was at the end of *this.
- This is a wart retained for backwards compatibility.
- GetPrev is not implemented.
- Use Next, Prev and Get separately.
- */
- void *GetNextI(POSITION& rp) const;
- /* Return a pointer to the object at p
- Asking for the object at NULL will return NULL harmlessly.
- */
- void *GetI(POSITION p) const;
- public:
- /* return the next / prev position in *this
- return NULL when going past the end/start.
- Next(NULL) is same as GetHeadPosition()
- Prev(NULL) is same as GetTailPosition()
- An n element list therefore behaves like a n+1 element
- cycle with NULL at the start/end.
- !!WARNING!! - This handling of NULL is DIFFERENT from GetNext.
- Some reasons are:
- 1. For a list of n items there are n+1 positions to insert
- These are conveniently encoded as the n POSITIONs and NULL.
- 2. If you are keeping a list sorted (fairly common) and you
- search forward for an element to insert before and don't
- find it you finish up with NULL as the element before which
- to insert. You then want that NULL to be a valid POSITION
- so that you can insert before it and you want that insertion
- point to mean the (n+1)-th one that doesn't have a POSITION.
- (symmetrically if you are working backwards through the list).
- 3. It simplifies the algebra which the methods generate.
- e.g. AddBefore(p,x) is identical to AddAfter(Prev(p),x)
- in ALL cases. All the other arguments probably are reflections
- of the algebraic point.
- */
- POSITION Next(POSITION pos) const
- {
- if (pos == NULL) {
- return (POSITION) m_pFirst;
- }
- CNode *pn = (CNode *) pos;
- return (POSITION) pn->Next();
- } //Next
- // See Next
- POSITION Prev(POSITION pos) const
- {
- if (pos == NULL) {
- return (POSITION) m_pLast;
- }
- CNode *pn = (CNode *) pos;
- return (POSITION) pn->Prev();
- } //Prev
- /* Return the first position in *this which holds the given
- pointer. Return NULL if the pointer was not not found.
- */
- protected:
- POSITION FindI( void * pObj) const;
- /* Remove the first node in *this (deletes the pointer to its
- object from the list, does not free the object itself).
- Return the pointer to its object.
- If *this was already empty it will harmlessly return NULL.
- */
- void *RemoveHeadI();
- /* Remove the last node in *this (deletes the pointer to its
- object from the list, does not free the object itself).
- Return the pointer to its object.
- If *this was already empty it will harmlessly return NULL.
- */
- void *RemoveTailI();
- /* Remove the node identified by p from the list (deletes the pointer
- to its object from the list, does not free the object itself).
- Asking to Remove the object at NULL will harmlessly return NULL.
- Return the pointer to the object removed.
- */
- void *RemoveI(POSITION p);
- /* Add single object *pObj to become a new last element of the list.
- Return the new tail position, NULL if it fails.
- If you are adding a COM objects, you might want AddRef it first.
- Other existing POSITIONs in *this are still valid
- */
- POSITION AddTailI(void * pObj);
- public:
- /* Add all the elements in *pList to the tail of *this.
- This duplicates all the nodes in *pList (i.e. duplicates
- all its pointers to objects). It does not duplicate the objects.
- If you are adding a list of pointers to a COM object into the list
- it's a good idea to AddRef them all it when you AddTail it.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some elements may have been added.
- Existing POSITIONs in *this are still valid
- If you actually want to MOVE the elements, use MoveToTail instead.
- */
- BOOL AddTail(CBaseList *pList);
- /* Mirror images of AddHead: */
- /* Add single object to become a new first element of the list.
- Return the new head position, NULL if it fails.
- Existing POSITIONs in *this are still valid
- */
- protected:
- POSITION AddHeadI(void * pObj);
- public:
- /* Add all the elements in *pList to the head of *this.
- Same warnings apply as for AddTail.
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails some of the objects may have been added.
- If you actually want to MOVE the elements, use MoveToHead instead.
- */
- BOOL AddHead(CBaseList *pList);
- /* Add the object *pObj to *this after position p in *this.
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return the position of the object added, NULL if it failed.
- Existing POSITIONs in *this are undisturbed, including p.
- */
- protected:
- POSITION AddAfterI(POSITION p, void * pObj);
- public:
- /* Add the list *pList to *this after position p in *this
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails, some of the objects may be added
- Existing POSITIONs in *this are undisturbed, including p.
- */
- BOOL AddAfter(POSITION p, CBaseList *pList);
- /* Mirror images:
- Add the object *pObj to this-List after position p in *this.
- AddBefore(NULL,x) adds x to the end - equivalent to AddTail
- Return the position of the new object, NULL if it fails
- Existing POSITIONs in *this are undisturbed, including p.
- */
- protected:
- POSITION AddBeforeI(POSITION p, void * pObj);
- public:
- /* Add the list *pList to *this before position p in *this
- AddAfter(NULL,x) adds x to the start - equivalent to AddHead
- Return TRUE if it all worked, FALSE if it didn't.
- If it fails, some of the objects may be added
- Existing POSITIONs in *this are undisturbed, including p.
- */
- BOOL AddBefore(POSITION p, CBaseList *pList);
- /* Note that AddAfter(p,x) is equivalent to AddBefore(Next(p),x)
- even in cases where p is NULL or Next(p) is NULL.
- Similarly for mirror images etc.
- This may make it easier to argue about programs.
- */
- /* The following operations do not copy any elements.
- They move existing blocks of elements around by switching pointers.
- They are fairly efficient for long lists as for short lists.
- (Alas, the Count slows things down).
- They split the list into two parts.
- One part remains as the original list, the other part
- is appended to the second list. There are eight possible
- variations:
- Split the list {after/before} a given element
- keep the {head/tail} portion in the original list
- append the rest to the {head/tail} of the new list.
- Since After is strictly equivalent to Before Next
- we are not in serious need of the Before/After variants.
- That leaves only four.
- If you are processing a list left to right and dumping
- the bits that you have processed into another list as
- you go, the Tail/Tail variant gives the most natural result.
- If you are processing in reverse order, Head/Head is best.
- By using NULL positions and empty lists judiciously either
- of the other two can be built up in two operations.
- The definition of NULL (see Next/Prev etc) means that
- degenerate cases include
- "move all elements to new list"
- "Split a list into two lists"
- "Concatenate two lists"
- (and quite a few no-ops)
- !!WARNING!! The type checking won't buy you much if you get list
- positions muddled up - e.g. use a POSITION that's in a different
- list and see what a mess you get!
- */
- /* Split *this after position p in *this
- Retain as *this the tail portion of the original *this
- Add the head portion to the tail end of *pList
- Return TRUE if it all worked, FALSE if it didn't.
- e.g.
- foo->MoveToTail(foo->GetHeadPosition(), bar);
- moves one element from the head of foo to the tail of bar
- foo->MoveToTail(NULL, bar);
- is a no-op, returns NULL
- foo->MoveToTail(foo->GetTailPosition, bar);
- concatenates foo onto the end of bar and empties foo.
- A better, except excessively long name might be
- MoveElementsFromHeadThroughPositionToOtherTail
- */
- BOOL MoveToTail(POSITION pos, CBaseList *pList);
- /* Mirror image:
- Split *this before position p in *this.
- Retain in *this the head portion of the original *this
- Add the tail portion to the start (i.e. head) of *pList
- e.g.
- foo->MoveToHead(foo->GetTailPosition(), bar);
- moves one element from the tail of foo to the head of bar
- foo->MoveToHead(NULL, bar);
- is a no-op, returns NULL
- foo->MoveToHead(foo->GetHeadPosition, bar);
- concatenates foo onto the start of bar and empties foo.
- */
- BOOL MoveToHead(POSITION pos, CBaseList *pList);
- /* Reverse the order of the [pointers to] objects in *this
- */
- void Reverse();
- /* set cursor to the position of each element of list in turn */
- #define TRAVERSELIST(list, cursor)
- for ( cursor = (list).GetHeadPosition()
- ; cursor!=NULL
- ; cursor = (list).Next(cursor)
- )
- /* set cursor to the position of each element of list in turn
- in reverse order
- */
- #define REVERSETRAVERSELIST(list, cursor)
- for ( cursor = (list).GetTailPosition()
- ; cursor!=NULL
- ; cursor = (list).Prev(cursor)
- )
- }; // end of class declaration
- template<class OBJECT> class CGenericList : public CBaseList
- {
- public:
- CGenericList(TCHAR *pName,
- INT iItems,
- BOOL bLock = TRUE,
- BOOL bAlert = FALSE) :
- CBaseList(pName, iItems) {
- UNREFERENCED_PARAMETER(bAlert);
- UNREFERENCED_PARAMETER(bLock);
- };
- CGenericList(TCHAR *pName) :
- CBaseList(pName) {
- };
- POSITION GetHeadPosition() const { return (POSITION)m_pFirst; }
- POSITION GetTailPosition() const { return (POSITION)m_pLast; }
- int GetCount() const { return m_Count; }
- OBJECT *GetNext(POSITION& rp) const { return (OBJECT *) GetNextI(rp); }
- OBJECT *Get(POSITION p) const { return (OBJECT *) GetI(p); }
- OBJECT *GetHead() const { return Get(GetHeadPosition()); }
- OBJECT *RemoveHead() { return (OBJECT *) RemoveHeadI(); }
- OBJECT *RemoveTail() { return (OBJECT *) RemoveTailI(); }
- OBJECT *Remove(POSITION p) { return (OBJECT *) RemoveI(p); }
- POSITION AddBefore(POSITION p, OBJECT * pObj) { return AddBeforeI(p, pObj); }
- POSITION AddAfter(POSITION p, OBJECT * pObj) { return AddAfterI(p, pObj); }
- POSITION AddHead(OBJECT * pObj) { return AddHeadI(pObj); }
- POSITION AddTail(OBJECT * pObj) { return AddTailI(pObj); }
- BOOL AddTail(CGenericList<OBJECT> *pList)
- { return CBaseList::AddTail((CBaseList *) pList); }
- BOOL AddHead(CGenericList<OBJECT> *pList)
- { return CBaseList::AddHead((CBaseList *) pList); }
- BOOL AddAfter(POSITION p, CGenericList<OBJECT> *pList)
- { return CBaseList::AddAfter(p, (CBaseList *) pList); };
- BOOL AddBefore(POSITION p, CGenericList<OBJECT> *pList)
- { return CBaseList::AddBefore(p, (CBaseList *) pList); };
- POSITION Find( OBJECT * pObj) const { return FindI(pObj); }
- }; // end of class declaration
- /* These define the standard list types */
- typedef CGenericList<CBaseObject> CBaseObjectList;
- typedef CGenericList<IUnknown> CBaseInterfaceList;
- #endif /* __WXLIST__ */