PageRenderTime 45ms CodeModel.GetById 14ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/lllinkedqueue.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 309 lines | 188 code | 61 blank | 60 comment | 15 complexity | e14e272453f7640390fe89e6fc97435f MD5 | raw file
  1/** 
  2 * @file lllinkedqueue.h
  3 * @brief Declaration of linked queue classes.
  4 *
  5 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLLINKEDQUEUE_H
 28#define LL_LLLINKEDQUEUE_H
 29
 30#include "llerror.h"
 31
 32// node that actually contains the data
 33template <class DATA_TYPE> class LLLinkedQueueNode
 34{
 35public:
 36	DATA_TYPE			mData;
 37	LLLinkedQueueNode	*mNextp;
 38	LLLinkedQueueNode	*mPrevp;
 39
 40
 41public:
 42	LLLinkedQueueNode();
 43	LLLinkedQueueNode(const DATA_TYPE data);
 44
 45	// destructor does not, by default, destroy associated data
 46	// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
 47	~LLLinkedQueueNode();
 48};
 49
 50
 51
 52template <class DATA_TYPE> class LLLinkedQueue
 53{
 54
 55public:
 56	LLLinkedQueue();
 57
 58	// destructor destroys list and nodes, but not data in nodes
 59	~LLLinkedQueue();
 60
 61	// Puts at end of FIFO
 62	void push(const DATA_TYPE data);
 63
 64	// Takes off front of FIFO
 65	BOOL pop(DATA_TYPE &data);
 66	BOOL peek(DATA_TYPE &data);
 67
 68	void reset();
 69
 70	S32 getLength() const;
 71
 72	BOOL isEmpty() const;
 73
 74	BOOL remove(const DATA_TYPE data);
 75
 76	BOOL checkData(const DATA_TYPE data) const;
 77
 78private:
 79	// add node to end of list
 80	// set mCurrentp to mQueuep
 81	void addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep);
 82
 83private:
 84	LLLinkedQueueNode<DATA_TYPE> mHead;		// head node
 85	LLLinkedQueueNode<DATA_TYPE> mTail;		// tail node
 86	S32 mLength;
 87};
 88
 89
 90//
 91// Nodes
 92//
 93
 94template <class DATA_TYPE>
 95LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode() : 
 96	mData(), mNextp(NULL), mPrevp(NULL)
 97{ }
 98
 99template <class DATA_TYPE>
100LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode(const DATA_TYPE data) : 
101	mData(data), mNextp(NULL), mPrevp(NULL)
102{ }
103
104template <class DATA_TYPE>
105LLLinkedQueueNode<DATA_TYPE>::~LLLinkedQueueNode()
106{ }
107
108
109//
110// Queue itself
111//
112
113template <class DATA_TYPE>
114LLLinkedQueue<DATA_TYPE>::LLLinkedQueue()
115:	mHead(), 
116	mTail(), 
117	mLength(0)
118{ }
119
120
121// destructor destroys list and nodes, but not data in nodes
122template <class DATA_TYPE>
123LLLinkedQueue<DATA_TYPE>::~LLLinkedQueue()
124{
125	reset();
126}
127
128
129// put data into a node and stick it at the end of the list
130template <class DATA_TYPE>
131void LLLinkedQueue<DATA_TYPE>::push(const DATA_TYPE data)
132{
133	// make the new node
134	LLLinkedQueueNode<DATA_TYPE> *nodep = new LLLinkedQueueNode<DATA_TYPE>(data);
135
136	addNodeAtEnd(nodep);
137}
138
139
140// search the list starting at mHead.mNextp and remove the link with mDatap == data
141// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
142// return TRUE if found, FALSE if not found
143template <class DATA_TYPE>
144BOOL LLLinkedQueue<DATA_TYPE>::remove(const DATA_TYPE data)
145{
146	BOOL b_found = FALSE;
147
148	LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
149
150	while (currentp)
151	{
152		if (currentp->mData == data)
153		{
154			b_found = TRUE;
155
156			// if there is a next one, fix it
157			if (currentp->mNextp)
158			{
159				currentp->mNextp->mPrevp = currentp->mPrevp;
160			}
161			else // we are at end of list
162			{
163				mTail.mPrevp = currentp->mPrevp;
164			}
165
166			// if there is a previous one, fix it
167			if (currentp->mPrevp)
168			{
169				currentp->mPrevp->mNextp = currentp->mNextp;
170			}
171			else // we are at beginning of list
172			{
173				mHead.mNextp = currentp->mNextp;
174			}
175
176			// remove the node
177			delete currentp;
178			mLength--;
179			break;
180		}
181		currentp = currentp->mNextp; 
182	}
183
184	return b_found;
185}
186
187
188// remove all nodes from the list but do not delete associated data
189template <class DATA_TYPE>
190void LLLinkedQueue<DATA_TYPE>::reset()
191{
192	LLLinkedQueueNode<DATA_TYPE> *currentp;
193	LLLinkedQueueNode<DATA_TYPE> *nextp;
194	currentp = mHead.mNextp;
195
196	while (currentp)
197	{
198		nextp = currentp->mNextp;
199		delete currentp;
200		currentp = nextp;
201	}
202
203	// reset mHead and mCurrentp
204	mHead.mNextp = NULL;
205	mTail.mPrevp = NULL;
206	mLength = 0;
207}
208
209template <class DATA_TYPE>
210S32 LLLinkedQueue<DATA_TYPE>::getLength() const
211{
212	return mLength;
213}
214
215template <class DATA_TYPE>
216BOOL LLLinkedQueue<DATA_TYPE>::isEmpty() const
217{
218	return mLength <= 0;
219}
220
221// check to see if data is in list
222// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
223// return TRUE if found, FALSE if not found
224template <class DATA_TYPE>
225BOOL LLLinkedQueue<DATA_TYPE>::checkData(const DATA_TYPE data) const
226{
227	LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
228
229	while (currentp)
230	{
231		if (currentp->mData == data)
232		{
233			return TRUE;
234		}
235		currentp = currentp->mNextp;
236	}
237	return FALSE;
238}
239
240template <class DATA_TYPE>
241BOOL LLLinkedQueue<DATA_TYPE>::pop(DATA_TYPE &data)
242{
243	LLLinkedQueueNode<DATA_TYPE> *currentp;
244
245	currentp = mHead.mNextp;
246	if (!currentp)
247	{
248		return FALSE;
249	}
250
251	mHead.mNextp = currentp->mNextp;
252	if (currentp->mNextp)
253	{
254		currentp->mNextp->mPrevp = currentp->mPrevp;
255	}
256	else
257	{
258		mTail.mPrevp = currentp->mPrevp;
259	}
260
261	data = currentp->mData;
262	delete currentp;
263	mLength--;
264	return TRUE;
265}
266
267template <class DATA_TYPE>
268BOOL LLLinkedQueue<DATA_TYPE>::peek(DATA_TYPE &data)
269{
270	LLLinkedQueueNode<DATA_TYPE> *currentp;
271
272	currentp = mHead.mNextp;
273	if (!currentp)
274	{
275		return FALSE;
276	}
277	data = currentp->mData;
278	return TRUE;
279}
280
281
282//////////////////////////////////////////////////////////////////////////////////////////
283// private members
284//////////////////////////////////////////////////////////////////////////////////////////
285
286
287// add node to end of list
288// set mCurrentp to mQueuep
289template <class DATA_TYPE>
290void LLLinkedQueue<DATA_TYPE>::addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep)
291{
292	// add the node to the end of the list
293	nodep->mNextp = NULL;
294	nodep->mPrevp = mTail.mPrevp;
295	mTail.mPrevp = nodep;
296
297	// if there's something in the list, fix its back pointer
298	if (nodep->mPrevp)
299	{
300		nodep->mPrevp->mNextp = nodep;
301	}
302	else	// otherwise fix the head node
303	{
304		mHead.mNextp = nodep;
305	}
306	mLength++;
307}
308
309#endif