1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 // -*- c++ -*-
19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
20
21 // L I N K E D L I S T C L A S S
22
23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
24
25 #ifndef __LINKED_LIST_H
26 #define __LINKED_LIST_H
27
28 // - - Inclusion - - - - - - - - - - - - - - - - - - - - - - - - - - - -
29
30 #include "oscl_mutex.h"
31
32 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
33 template <class LLClass> class LinkedList;
34
35 template <class LLClass> class LinkedListElement
36 {
37
38 public:
LinkedListElement(LLClass in_data)39 LinkedListElement(LLClass in_data)
40 {
41 data = in_data;
42 next = NULL;
43 };
44 // ~LinkedListElement() {};
45
46 friend class LinkedList<LLClass>;
47
48 private:
49 LinkedListElement<LLClass>* next;
50 LLClass data;
51 };
52
53
54 template <class LLClass> class LinkedList
55 {
56
57 public:
58 LinkedList();
59 ~LinkedList();
60
61 int add_element(LLClass& new_data);
62 int add_to_front(const LLClass& new_data);
63 int add_to_end(const LLClass& new_data);
64 int remove_element(const LLClass& data_to_remove);
65 int remove_element(const int index_to_remove);
66 int move_to_end(const LLClass& data_to_move);
67 int move_to_front(const LLClass& data_to_move);
get_num_elements()68 int get_num_elements()
69 {
70 return num_elements;
71 };
72
73 int get_element(int index, LLClass& element);
74 int get_index(const LLClass& data);
75
dequeue_element(LLClass & element)76 int dequeue_element(LLClass & element)
77 {
78 get_element(0, element);
79 return remove_element(0);
80 }
81 // get_first() and get_next() together provide iterator function
get_first(LLClass & ele)82 int get_first(LLClass & ele)
83 {
84 if (!head) return 0;
85 iterator = head;
86 ele = iterator->data;
87 return 1;
88 };
89
get_next(LLClass & ele)90 int get_next(LLClass & ele)
91 {
92 if (iterator == tail) return 0;
93 if (! iterator)
94 {
95 if (!head) return 0;
96 iterator = head;
97 }
98 else
99 {
100 iterator = iterator->next;
101 }
102 ele = iterator->data;
103
104 return 1;
105 };
106
107
108 protected:
109 LinkedListElement<LLClass> *head;
110 LinkedListElement<LLClass> *tail;
111 LinkedListElement<LLClass> *iterator;
112 int num_elements;
113
114 int check_list();
115 };
116
117
LinkedList()118 template <class LLClass> LinkedList<LLClass>::LinkedList()
119 {
120 num_elements = 0;
121 head = tail = iterator = NULL;
122 }
123
~LinkedList()124 template <class LLClass> LinkedList<LLClass>::~LinkedList()
125 {
126 LinkedListElement<LLClass>* tmp;
127 while (num_elements && head)
128 {
129 tmp = head->next;
130 OSCL_DELETE(head);
131 --num_elements;
132 head = tmp;
133 }
134 head = tail = iterator = NULL;
135 }
136
137
check_list()138 template <class LLClass> int LinkedList<LLClass>::check_list()
139 {
140 LinkedListElement<LLClass> *tmp;
141 int ii;
142
143 for (tmp = head, ii = 0; tmp ; ++ii, tmp = tmp->next);
144
145 return (ii == num_elements);
146 }
147
148
add_element(LLClass & new_element)149 template <class LLClass> int LinkedList<LLClass>::add_element(LLClass& new_element)
150 {
151 if (!tail)
152 {
153 head = tail = OSCL_NEW(LinkedListElement<LLClass>, (new_element));
154 }
155 else
156 {
157 tail->next = OSCL_NEW(LinkedListElement<LLClass>, (new_element));
158 tail = tail->next;
159 }
160
161 ++num_elements;
162 return 1;
163 }
164
add_to_front(const LLClass & new_element)165 template <class LLClass> int LinkedList<LLClass>::add_to_front(const LLClass& new_element)
166 {
167 if (!head)
168 {
169 head = tail = OSCL_NEW(LinkedListElement<LLClass>, (new_element));
170 }
171 else
172 {
173 LinkedListElement<LLClass>* tmp;
174 tmp = OSCL_NEW(LinkedListElement<LLClass>, (new_element));
175 tmp->next = head;
176 head = tmp;
177 }
178
179 ++num_elements;
180 return 1;
181 }
182
get_element(int index,LLClass & element)183 template <class LLClass> int LinkedList<LLClass>::get_element(int index, LLClass& element)
184 {
185
186 LinkedListElement<LLClass> *tmp;
187 int ii;
188
189 if (index < 0 || index >= num_elements)
190 {
191 return 0;
192 }
193
194 for (tmp = head, ii = 0; ii < index; ++ii, tmp = tmp->next);
195
196 element = tmp->data;
197 return 1;
198 }
199
200
remove_element(const LLClass & data_to_remove)201 template <class LLClass> int LinkedList<LLClass>::remove_element(const LLClass& data_to_remove)
202 {
203 LinkedListElement<LLClass> *tmp;
204 LinkedListElement<LLClass> *prev;
205 int found = 0;
206
207 for (tmp = head, prev = NULL; tmp; prev = tmp, tmp = tmp->next)
208 {
209
210 if (tmp->data == data_to_remove)
211 {
212 found = 1;
213 if (prev)
214 {
215 prev->next = tmp->next;
216 if (iterator == tmp) iterator = prev;
217 }
218 else
219 {
220 head = tmp->next;
221 if (iterator == tmp) iterator = NULL;
222
223 }
224 if (tmp == tail)
225 {
226 tail = prev;
227 }
228
229 OSCL_DELETE(tmp);
230 --num_elements;
231 break;
232 }
233
234 }
235 return found;
236 }
237
238
get_index(const LLClass & data)239 template <class LLClass> int LinkedList<LLClass>::get_index(const LLClass& data)
240 {
241 LinkedListElement<LLClass> *tmp;
242 int index = 0;
243 int found = 0;
244
245 for (tmp = head, index = 0; tmp; tmp = tmp->next, ++index)
246 {
247
248 if (tmp->data == data)
249 {
250 found = 1;
251 break;
252 }
253 }
254 if (found)
255 return index;
256
257 return -1;
258 }
259
260
261
remove_element(const int index_to_remove)262 template <class LLClass> int LinkedList<LLClass>::remove_element(const int index_to_remove)
263 {
264 LinkedListElement<LLClass> *tmp;
265 LinkedListElement<LLClass> *prev;
266 int ii;
267
268 if (index_to_remove < 0 || index_to_remove >= num_elements)
269 {
270 return 0;
271 }
272
273 // skip to desired element
274 for (tmp = head, prev = NULL, ii = 0; tmp && ii < index_to_remove;
275 ++ii, prev = tmp, tmp = tmp->next);
276
277 if (ii != index_to_remove)
278 {
279 return 0;
280 }
281
282 if (prev)
283 {
284 prev->next = tmp->next;
285 if (iterator == tmp) iterator = prev;
286 }
287 else
288 {
289 head = tmp->next;
290 if (iterator == tmp) iterator = NULL;
291 }
292 if (tmp == tail)
293 {
294 tail = prev;
295 }
296
297 OSCL_DELETE(tmp);
298 --num_elements;
299
300 return 1;
301 }
302
303
move_to_end(const LLClass & data_to_move)304 template <class LLClass> int LinkedList<LLClass>::move_to_end(const LLClass& data_to_move)
305 {
306 LinkedListElement<LLClass> *tmp;
307 LinkedListElement<LLClass> *prev;
308 int found = 0;
309
310 for (tmp = head, prev = NULL; tmp; prev = tmp, tmp = tmp->next)
311 {
312
313 if (tmp->data == data_to_move)
314 {
315 found = 1;
316 if (tmp == tail)
317 {
318 return 1; // nothing to do
319 }
320 if (prev)
321 {
322 prev->next = tmp->next;
323 if (iterator == tmp) iterator = prev;
324 }
325 if (tmp == head)
326 {
327 head = tmp->next;
328 if (iterator == tmp) iterator = NULL;
329 }
330 tail->next = tmp;
331 tmp->next = NULL;
332 tail = tmp;
333
334 return 1;
335 }
336 }
337
338 return 0;
339 }
340
341
move_to_front(const LLClass & data_to_move)342 template <class LLClass> int LinkedList<LLClass>::move_to_front(const LLClass& data_to_move)
343 {
344 LinkedListElement<LLClass> *tmp;
345 LinkedListElement<LLClass> *prev;
346 int found = 0;
347
348 for (tmp = head, prev = NULL; tmp; prev = tmp, tmp = tmp->next)
349 {
350
351 if (tmp->data == data_to_move)
352 {
353 found = 1;
354 if (tmp == head)
355 {
356 return 1; // nothing to do
357 }
358
359 if (prev)
360 {
361 prev->next = tmp->next;
362
363 if (iterator == tmp)
364 {
365 iterator = prev;
366 }
367 }
368
369 if (tmp == tail)
370 {
371 tail = prev;
372 }
373 tmp->next = head;
374 head = tmp;
375
376
377 return 1;
378 }
379 }
380
381 return 0;
382 }
383
384
385 // MTLinkedList is a multi-threaded version of
386 // the LinkedList. It has mutex protection to
387 // allow access by different threads.
388
389 template <class LLClass> class MTLinkedList
390 {
391
392 public:
MTLinkedList()393 MTLinkedList() {};
~MTLinkedList()394 ~MTLinkedList() {};
395
396
397 int add_element(LLClass& new_data);
398 int add_to_front(LLClass& new_data);
399 int remove_element(const LLClass& data_to_remove);
400 int remove_element(const int index_to_remove);
401 int move_to_end(const LLClass& data_to_move);
402 int move_to_front(const LLClass& data_to_move);
get_num_elements()403 int get_num_elements()
404 {
405 return the_list.get_num_elements();
406 };
407
408 int get_element(int index, LLClass& element);
409 int get_index(const LLClass& data);
410
dequeue_element(LLClass & element)411 int dequeue_element(LLClass & element)
412 {
413 int status;
414 mutex.Lock();
415 status = the_list.dequeue_element(element);
416 mutex.Unlock();
417 return status;
418 }
419
420
421 protected:
422 LinkedList<LLClass> the_list;
423 PVMutex mutex;
424
425
426 };
427
428
429
add_element(LLClass & new_element)430 template <class LLClass> int MTLinkedList<LLClass>::add_element(LLClass& new_element)
431 {
432 int status;
433 mutex.Lock();
434 status = the_list.add_element(new_element);
435 mutex.Unlock();
436 return status;
437 }
438
add_to_front(LLClass & new_element)439 template <class LLClass> int MTLinkedList<LLClass>::add_to_front(LLClass& new_element)
440 {
441 int status;
442 mutex.Lock();
443 status = the_list.add_to_front(new_element);
444 mutex.Unlock();
445 return status;
446 }
447
448
get_element(int index,LLClass & element)449 template <class LLClass> int MTLinkedList<LLClass>::get_element(int index, LLClass& element)
450 {
451
452 int status;
453 mutex.Lock();
454 status = the_list.get_element(index, element);
455 mutex.Unlock();
456 return status;
457 }
458
459
remove_element(const LLClass & data_to_remove)460 template <class LLClass> int MTLinkedList<LLClass>::remove_element(const LLClass& data_to_remove)
461 {
462 int status;
463
464 mutex.Lock();
465 status = the_list.remove_element(data_to_remove);
466 mutex.Unlock();
467 return status;
468 }
469
470
get_index(const LLClass & data)471 template <class LLClass> int MTLinkedList<LLClass>::get_index(const LLClass& data)
472 {
473 int status;
474 mutex.Lock();
475 status = the_list.get_index(data);
476 mutex.Unlock();
477 return status;
478 }
479
480
481
remove_element(const int index_to_remove)482 template <class LLClass> int MTLinkedList<LLClass>::remove_element(const int index_to_remove)
483 {
484 int status;
485 mutex.Lock();
486 status = the_list.remove_element(index_to_remove);
487 mutex.Unlock();
488 return status;
489 }
490
491
move_to_end(const LLClass & data_to_move)492 template <class LLClass> int MTLinkedList<LLClass>::move_to_end(const LLClass& data_to_move)
493 {
494 int status;
495 mutex.Lock();
496 status = the_list.move_to_end(data_to_move);
497 mutex.Unlock();
498 return status;
499 }
500
move_to_front(const LLClass & data_to_move)501 template <class LLClass> int MTLinkedList<LLClass>::move_to_front(const LLClass& data_to_move)
502 {
503 int status;
504 mutex.Lock();
505 status = the_list.move_to_front(data_to_move);
506 mutex.Unlock();
507 return status;
508 }
509
510
511
512 #endif // __LINKED_LIST_H
513
514