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 // O S C L _ L I N K E D _ L I S T 22 23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 24 25 /*! \addtogroup osclbase OSCL Base 26 * 27 * @{ 28 */ 29 30 31 /*! \file oscl_linked_list.h 32 \brief The file oscl_linked_list.h defines the template class Oscl_Linked_List which has a very similar API as the STL Vector class (it basically provides a subset of the STL functionality). Memory allocation is abstracted through the use of an allocator template parameter. 33 */ 34 35 #ifndef OSCL_LINKED_LIST_H_INCLUDED 36 #define OSCL_LINKED_LIST_H_INCLUDED 37 38 #ifndef OSCL_BASE_H_INCLUDED 39 #include "oscl_base.h" 40 #endif 41 #ifndef OSCL_DEFALLOC_H_INCLUDED 42 #include "oscl_defalloc.h" 43 #endif 44 #ifndef OSCL_OPAQUE_TYPE_H_INCLUDED 45 #include "oscl_opaque_type.h" 46 #endif 47 #ifndef OSCL_ASSERT_H_INCLUDED 48 #include "oscl_assert.h" 49 #endif 50 51 52 /** 53 * oscl_linked_list supports random access to elements, constant time insertion 54 * and removal of elements from the list, and linear time 55 * insertion and removal of elements at the beginning or middle of the 56 * list. The number of elements in a list can vary dynamically, and 57 * memory management is performed using new and delete operators. 58 */ 59 60 template <class LLClass, class Alloc> class Oscl_Linked_List; 61 /** 62 * Linked List Element Class 63 */ 64 template <class LLClass> class LinkedListElement 65 { 66 67 public: LinkedListElement(LLClass in_data)68 LinkedListElement(LLClass in_data) 69 { 70 data = in_data; 71 next = NULL; 72 }; 73 // ~LinkedListElement() {}; 74 75 // friend class Oscl_Linked_List<LLClass>; 76 LinkedListElement<LLClass>* next; 77 LLClass data; 78 79 private: 80 }; 81 82 /** 83 * Oscl Linked List Base Class. A non-templated base class is used to avoid 84 * large inline functions in the Oscl_Linked_List implementation. 85 */ 86 class Oscl_Linked_List_Base 87 { 88 protected: ~Oscl_Linked_List_Base()89 virtual ~Oscl_Linked_List_Base() 90 {} 91 92 OSCL_IMPORT_REF void construct(Oscl_Opaque_Type_Alloc_LL* op); 93 94 OSCL_IMPORT_REF void destroy(); 95 96 /** 97 * Return the first element of list in passed parameter, 98 * @param ele return the value of first element of list in this parameter 99 * @return 32-bit interger,If first element found, it returns 1 100 * otherwise it returns 0 101 */ 102 OSCL_IMPORT_REF int32 get_first(OsclAny* ele); 103 104 /** 105 * Return the next element of list in passed parameter, 106 * @param ele return the value of next element of list in this parameter 107 * @return 32-bit interger ,if next element is found in list,it returns 1 108 * otherwise it returns 0 109 */ 110 OSCL_IMPORT_REF int32 get_next(OsclAny* ele); 111 112 /** 113 * Debug routine: Checks the list for elements. 114 * @return 32-bit integer, if node count is equal to number of node added 115 * to the list then returns 1 otherwise returns 0. 116 */ 117 OSCL_IMPORT_REF int32 check_list(); 118 119 /** 120 * Adds new element to the list.if list is already there then it adds element at end of list otherwise 121 * it create the list and add the element as first element of list. 122 * @param new_element the element to be add in the list. 123 * @return 32-bit integer on the success returns 1. 124 */ 125 OSCL_IMPORT_REF int32 add_element(OsclAny* new_element); 126 127 /** 128 * Adds new element at the start of the list.if list is already 129 * exist then it adds element at start of list otherwise 130 * it create the list and add the element as first element of list. 131 * @param new_element the element to be add in the list. 132 * @return 32-bit integer on the success returns 1. 133 */ 134 OSCL_IMPORT_REF int32 add_to_front(const OsclAny* new_element); 135 136 /** 137 * Search and returs the element in the list for passed index. 138 * @param index, element The index is the count for the node. 139 * @return 32-bit integer on success returns 1 otherwise returns 0. 140 */ 141 OSCL_IMPORT_REF int32 get_element(int32 index, OsclAny* element); 142 143 /** 144 * Removes the element from the list. 145 * @param data_to_remove 146 * @return 32-bit integer on if element fount in the list returns 1 otherwise returns 0. 147 */ 148 OSCL_IMPORT_REF int32 remove_element(const OsclAny* data_to_remove); 149 150 /** 151 * Returns the index for requested element. 152 * @param data the element for which index to be return. 153 * @return 32-bit integer if data is found in the list it returns index 154 * otherwise it returns -1. 155 */ 156 OSCL_IMPORT_REF int32 get_index(const OsclAny* data); 157 158 /** 159 * Removes the element for requested index. 160 * @param index_to_remove 161 * @return on success return 1 otherwise return 0. 162 */ 163 OSCL_IMPORT_REF int32 remove_element(const int32 index_to_remove); 164 165 /** 166 * Moves the element to end of the list 167 * @param data_to_move 168 * @return On success returns 1 otherwise returns 0. 169 */ 170 OSCL_IMPORT_REF int32 move_to_end(const OsclAny* data_to_move); 171 172 /** 173 * Moves the element to front of the list 174 * @param data_to_move 175 * @return On success returns 1 otherwise returns 0. 176 */ 177 OSCL_IMPORT_REF int32 move_to_front(const OsclAny* data_to_move); 178 179 OsclAny *head; 180 OsclAny *tail; 181 OsclAny *iterator; 182 int32 num_elements; 183 uint32 sizeof_T; 184 185 private: 186 Oscl_Opaque_Type_Alloc_LL* pOpaqueType; 187 }; 188 189 /** 190 * Oscl Linked List Class 191 */ 192 template <class LLClass, class Alloc> class Oscl_Linked_List 193 : public Oscl_Linked_List_Base 194 , public Oscl_Opaque_Type_Alloc_LL 195 { 196 197 public: 198 /** 199 * Initialized the protected variables of list. 200 */ Oscl_Linked_List()201 Oscl_Linked_List(): Oscl_Linked_List_Base(), Oscl_Opaque_Type_Alloc_LL() 202 { 203 sizeof_T = sizeof(LinkedListElement<LLClass>); 204 Oscl_Linked_List_Base::construct(this); 205 } 206 207 /** 208 * The destructor. 209 */ ~Oscl_Linked_List()210 ~Oscl_Linked_List() 211 { 212 Oscl_Linked_List_Base::destroy(); 213 } 214 dequeue_element(LLClass & element)215 int32 dequeue_element(LLClass & element) 216 { 217 get_element(0, element); 218 return remove_element((int32) 0); 219 } 220 // get_first() and get_next() together provide iterator function 221 222 /** 223 * Return the first element of list in passed parameter, 224 * @param ele return the value of first element of list in this parameter 225 * @return 32-bit interger,If first element found, it returns 1 226 * otherwise it returns 0 227 */ get_first(LLClass & ele)228 int32 get_first(LLClass & ele) 229 { 230 return Oscl_Linked_List_Base::get_first(&ele); 231 } 232 233 /** 234 * Return the next element of list in passed parameter, 235 * @param ele return the value of next element of list in this parameter 236 * @return 32-bit interger ,if next element is found in list,it returns 1 237 * otherwise it returns 0 238 */ get_next(LLClass & ele)239 int32 get_next(LLClass & ele) 240 { 241 return Oscl_Linked_List_Base::get_next(&ele); 242 } 243 244 /** 245 * Debug routine: Checks the list for elements. 246 * @return 32-bit integer, if node count is equal to number of node added 247 * to the list then returns 1 otherwise returns 0. 248 */ check_list()249 int32 check_list() 250 { 251 return Oscl_Linked_List_Base::check_list(); 252 } 253 254 /** 255 * Get number of elements in the list. 256 * @return 32-bit integer, number of elements in list. 257 */ get_num_elements()258 int32 get_num_elements() 259 { 260 return num_elements; 261 } 262 263 /** 264 * Adds new element to the list.if list is already there then it adds element at end of list otherwise 265 * it create the list and add the element as first element of list. 266 * @param new_element the element to be add in the list. 267 * @return 32-bit integer on the success returns 1. 268 */ add_element(LLClass & new_element)269 int32 add_element(LLClass& new_element) 270 { 271 return Oscl_Linked_List_Base::add_element(&new_element); 272 } 273 274 /** 275 * Adds new element at the start of the list.if list is already 276 * exist then it adds element at start of list otherwise 277 * it create the list and add the element as first element of list. 278 * @param new_element the element to be add in the list. 279 * @return 32-bit integer on the success returns 1. 280 */ add_to_front(const LLClass & new_element)281 int32 add_to_front(const LLClass& new_element) 282 { 283 return Oscl_Linked_List_Base::add_to_front(&new_element); 284 } 285 286 /** 287 * Search and returs the element in the list for passed index. 288 * @param index, element The index is the count for the node. 289 * @return 32-bit integer on success returns 1 otherwise returns 0. 290 */ get_element(int32 index,LLClass & element)291 int32 get_element(int32 index, LLClass& element) 292 { 293 return Oscl_Linked_List_Base::get_element(index, &element); 294 } 295 296 /** 297 * Removes the element from the list. 298 * @param data_to_remove 299 * @return 32-bit integer on if element fount in the list returns 1 otherwise returns 0. 300 */ remove_element(const LLClass & data_to_remove)301 int32 remove_element(const LLClass& data_to_remove) 302 { 303 return Oscl_Linked_List_Base::remove_element(&data_to_remove); 304 } 305 306 /** 307 * Returns the index for requested element. 308 * @param data the element for which index to be return. 309 * @return 32-bit integer if data is found in the list it returns index 310 * otherwise it returns -1. 311 */ get_index(const LLClass & data)312 int32 get_index(const LLClass& data) 313 { 314 return Oscl_Linked_List_Base::get_index(&data); 315 } 316 317 /** 318 * Removes the element for requested index. 319 * @param index_to_remove 320 * @return on success return 1 otherwise return 0. 321 */ remove_element(const int32 index_to_remove)322 int32 remove_element(const int32 index_to_remove) 323 { 324 return Oscl_Linked_List_Base::remove_element(index_to_remove); 325 } 326 327 /** 328 * Moves the element to end of the list 329 * @param data_to_move 330 * @return On success returns 1 otherwise returns 0. 331 */ move_to_end(const LLClass & data_to_move)332 int32 move_to_end(const LLClass& data_to_move) 333 { 334 return Oscl_Linked_List_Base::move_to_end(&data_to_move); 335 } 336 337 /** 338 * Moves the element to front of the list 339 * @param data_to_move 340 * @return On success returns 1 otherwise returns 0. 341 */ move_to_front(const LLClass & data_to_move)342 int32 move_to_front(const LLClass& data_to_move) 343 { 344 return Oscl_Linked_List_Base::move_to_front(&data_to_move); 345 } 346 347 348 private: 349 350 //from Oscl_Opaque_Type_Alloc_LL construct(OsclAny * p,const OsclAny * init_val)351 void construct(OsclAny* p, const OsclAny* init_val) 352 { 353 OSCL_ASSERT(init_val); 354 OSCL_ASSERT(p); 355 new(p) LinkedListElement<LLClass>(*(LLClass*)init_val); 356 } 357 358 //this typedef is needed to avoid compile errors ADS 1.2 compiler. 359 typedef LinkedListElement<LLClass>* p_elem_type; 360 361 //from Oscl_Opaque_Type_Alloc_LL destroy(OsclAny * p)362 void destroy(OsclAny* p) 363 { 364 OSCL_ASSERT(p); 365 ((p_elem_type)p)->~LinkedListElement<LLClass>(); 366 } 367 368 //from Oscl_Opaque_Type_Alloc_LL allocate(const uint32 size)369 OsclAny* allocate(const uint32 size) 370 { 371 return alloc.ALLOCATE(size); 372 } 373 374 //from Oscl_Opaque_Type_Alloc_LL deallocate(OsclAny * p)375 void deallocate(OsclAny* p) 376 { 377 alloc.deallocate(p); 378 } 379 380 //from Oscl_Opaque_Type_Alloc_LL get_next(const OsclAny * elem)381 OsclAny* get_next(const OsclAny* elem)const 382 { 383 return ((LinkedListElement<LLClass>*)elem)->next; 384 } 385 386 //from Oscl_Opaque_Type_Alloc_LL set_next(OsclAny * elem,const OsclAny * nextelem)387 void set_next(OsclAny* elem, const OsclAny* nextelem) 388 { 389 OSCL_ASSERT(elem); 390 ((LinkedListElement<LLClass>*)elem)->next = (LinkedListElement<LLClass>*)nextelem; 391 } 392 393 //from Oscl_Opaque_Type_Alloc_LL get_data(OsclAny * elem,OsclAny * data_val)394 void get_data(OsclAny*elem, OsclAny*data_val) 395 { 396 OSCL_ASSERT(elem); 397 OSCL_ASSERT(data_val); 398 *((LLClass*)data_val) = ((LinkedListElement<LLClass>*)elem)->data ; 399 } 400 401 //from Oscl_Opaque_Type_Alloc_LL compare_data(const OsclAny * elem,const OsclAny * data_val)402 bool compare_data(const OsclAny*elem, const OsclAny*data_val)const 403 { 404 OSCL_ASSERT(elem); 405 OSCL_ASSERT(data_val); 406 return ((LinkedListElement<LLClass>*)elem)->data == *((LLClass*)data_val); 407 } 408 409 Alloc alloc; 410 411 }; 412 413 /** 414 * Oscl_MTLinked_List is a multi-threaded version of 415 * the LinkedList. It has mutex protection to 416 * allow access by different threads. 417 */ 418 template <class LLClass, class Alloc, class TheLock> class Oscl_MTLinked_List 419 { 420 421 public: 422 /** 423 * Constructor for Oscl_MTLinked_List 424 */ Oscl_MTLinked_List()425 Oscl_MTLinked_List() {}; 426 427 /** 428 * Destructor for Oscl_MTLinked_List 429 */ ~Oscl_MTLinked_List()430 ~Oscl_MTLinked_List() {}; 431 dequeue_element(LLClass & element)432 int32 dequeue_element(LLClass & element) 433 { 434 int32 status; 435 TheLock Mylock; 436 Mylock.Lock(); 437 status = the_list.dequeue_element(element); 438 Mylock.Unlock(); 439 return status; 440 } 441 442 /** 443 * Adds new element to the Multi Threaded Linked list.if list 444 * is already there then it adds element at end of list otherwise 445 * it create the list and add the element as first element of list. 446 * @param new_element the element to be add in the list. 447 * @return 32-bit integer on the success returns 1. 448 */ add_element(LLClass & new_element)449 int32 add_element(LLClass& new_element) 450 { 451 int32 status; 452 TheLock Mylock; 453 Mylock.Lock(); 454 status = the_list.add_element(new_element); 455 Mylock.Unlock(); 456 return status; 457 } 458 459 /** 460 * Adds new element at the start of the Multi Threaded Linked list. 461 * if list is already exist then it adds element at start of list otherwise 462 * it create the list and add the element as first element of list. 463 * @param new_element the element to be add in the list. 464 * @return 32-bit integer on the success returns 1. 465 */ add_to_front(LLClass & new_element)466 int32 add_to_front(LLClass& new_element) 467 { 468 int32 status; 469 TheLock Mylock; 470 Mylock.Lock(); 471 status = the_list.add_to_front(new_element); 472 Mylock.Unlock(); 473 return status; 474 } 475 476 /** 477 * Search and returs the element in the Multi Treaded Linked List 478 * for passed index. 479 * @param index, element The index is the count for the node. 480 * @return 32-bit integer on success returns 1 otherwise returns 0. 481 */ get_element(int32 index,LLClass & element)482 uint32 get_element(int32 index, LLClass& element) 483 { 484 485 int32 status; 486 TheLock Mylock; 487 Mylock.Lock(); 488 status = the_list.get_element(index, element); 489 Mylock.Unlock(); 490 return status; 491 } 492 493 /** 494 * Removes the element from the list. 495 * @param data_to_remove 496 * @return 32-bit integer on if element fount in the list returns 1 otherwise returns 0. 497 */ remove_element(const LLClass & data_to_remove)498 int32 remove_element(const LLClass& data_to_remove) 499 { 500 int32 status; 501 TheLock Mylock; 502 Mylock.Lock(); 503 status = the_list.remove_element(data_to_remove); 504 Mylock.Unlock(); 505 return status; 506 } 507 508 /** 509 * Returns the index for requested element. 510 * @param data the element for which index to be return. 511 * @return 32-bit integer if data is found in the list it returns index 512 * otherwise it returns -1. 513 */ get_index(const LLClass & data)514 int32 get_index(const LLClass& data) 515 { 516 int32 status; 517 TheLock Mylock; 518 Mylock.Lock(); 519 status = the_list.get_index(data); 520 Mylock.Unlock(); 521 return status; 522 } 523 524 /** 525 * Removes the element for requested index. 526 * @param index_to_remove 527 * @return on success return 1 otherwise return 0. 528 */ remove_element(const int32 index_to_remove)529 int32 remove_element(const int32 index_to_remove) 530 { 531 int32 status; 532 TheLock Mylock; 533 Mylock.Lock(); 534 status = the_list.remove_element(index_to_remove); 535 Mylock.Unlock(); 536 return status; 537 } 538 539 /** 540 * Moves the element to end of the list 541 * @param data_to_move 542 * @return On success returns 1 otherwise returns 0. 543 */ move_to_end(const LLClass & data_to_move)544 int32 move_to_end(const LLClass& data_to_move) 545 { 546 int32 status; 547 TheLock Mylock; 548 Mylock.Lock(); 549 status = the_list.move_to_end(data_to_move); 550 Mylock.Unlock(); 551 return status; 552 } 553 554 /** 555 * Moves the element to front of the list 556 * @param data_to_move 557 * @return On success returns 1 otherwise returns 0. 558 */ move_to_front(const LLClass & data_to_move)559 int32 move_to_front(const LLClass& data_to_move) 560 { 561 int32 status; 562 TheLock Mylock; 563 Mylock.Lock(); 564 status = the_list.move_to_front(data_to_move); 565 Mylock.Unlock(); 566 return status; 567 } 568 569 protected: 570 Oscl_Linked_List<LLClass, Alloc> the_list; 571 // PVMutex mutex; 572 573 }; 574 575 576 /*! @} */ 577 578 579 #endif // __LINKED_LIST_H 580 581