• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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