last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 1998 - 2004 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * 00006 * This file is part of the Computer Vision and Robotics Library (CVR-Lib) 00007 * 00008 * The CVR-Lib is free software; you can redistribute it and/or 00009 * modify it under the terms of the BSD License. 00010 * 00011 * All rights reserved. 00012 * 00013 * Redistribution and use in source and binary forms, with or without 00014 * modification, are permitted provided that the following conditions are met: 00015 * 00016 * 1. Redistributions of source code must retain the above copyright notice, 00017 * this list of conditions and the following disclaimer. 00018 * 00019 * 2. Redistributions in binary form must reproduce the above copyright notice, 00020 * this list of conditions and the following disclaimer in the documentation 00021 * and/or other materials provided with the distribution. 00022 * 00023 * 3. Neither the name of the authors nor the names of its contributors may be 00024 * used to endorse or promote products derived from this software without 00025 * specific prior written permission. 00026 * 00027 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00028 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00029 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00030 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00031 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00032 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00033 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00034 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00035 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00036 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00037 * POSSIBILITY OF SUCH DAMAGE. 00038 */ 00039 00040 00041 /** 00042 * \file cvrSmallObjectList.h 00043 * Defines a list similar to the std::list but specialized for 00044 * an efficient access of small objects. 00045 * \author Gustavo Quiros 00046 * \date 12.12.03 00047 * 00048 * $Id: cvrSmallObjectList.h,v 1.14 2007/12/25 19:58:24 alvarado Exp $ 00049 */ 00050 00051 #ifndef _CVR_SMALL_OBJECT_LIST_H_ 00052 #define _CVR_SMALL_OBJECT_LIST_H_ 00053 00054 #include "cvrObject.h" 00055 #include "cvrIoObject.h" 00056 #include "cvrTypes.h" 00057 #include "cvrException.h" 00058 #include "cvrAssert.h" 00059 #include "cvrPerformanceConfig.h" 00060 00061 namespace cvr { 00062 00063 /** 00064 * List of objects of small size. 00065 * 00066 * The %cvr::smallObjectList is an efficient implementation 00067 * of a (double) linked list for small data types. 00068 * 00069 * Each instance maintains its own heap, which may be expensive in memory 00070 * consumption, but they are intended as very fast data structures with 00071 * respect to memory reservation issues. It should serve, in many cases, as 00072 * a drop-in replacement for std::list. 00073 * 00074 * @see cvr::list 00075 */ 00076 template <typename T> 00077 class smallObjectList { 00078 00079 private: 00080 00081 struct node; 00082 class heap; 00083 00084 public: 00085 00086 class iterator; 00087 class const_iterator; 00088 friend class iterator; 00089 friend class const_iterator; 00090 00091 /** 00092 * The type used to store the size of this list. 00093 */ 00094 typedef unsigned int size_type; 00095 00096 /** 00097 * Reference type (allows read and write operations) 00098 * The use of the reference classes is similar to the 00099 * references of the STL (Standard Template Library). 00100 */ 00101 typedef T& reference; 00102 00103 /** 00104 * Const_reference type (allows read-only operations) 00105 * The use of the reference classes is similar to the 00106 * references of the STL (Standard Template Library). 00107 */ 00108 typedef const T& const_reference; 00109 00110 /** 00111 * Pointer type (allows read and write operations) 00112 * The use of the pointer classes is similar to the 00113 * references of the STL (Standard Template Library). 00114 */ 00115 typedef T* pointer; 00116 00117 /** 00118 * Const_pointer type (allows read-only operations) 00119 * The use of the pointer classes is similar to the 00120 * references of the STL (Standard Template Library). 00121 */ 00122 typedef const T* const_pointer; 00123 00124 /** 00125 * The type of the values stored in the list. 00126 */ 00127 typedef T value_type; 00128 00129 /** 00130 * Default constructor. Creates an empty smallObjectList. 00131 */ 00132 smallObjectList(); 00133 00134 /** 00135 * Copy constructor. Creates a smallObjectList with the same 00136 * contents as the given list. 00137 */ 00138 smallObjectList(const smallObjectList& l); 00139 00140 /** 00141 * Destructor 00142 */ 00143 ~smallObjectList(); 00144 00145 /** 00146 * Returns the number of elements in the list. 00147 */ 00148 size_type size() const; 00149 00150 /** 00151 * Returns true if the list has no elements, false otherwise. 00152 */ 00153 bool empty() const; 00154 00155 /** 00156 * Empties the list. 00157 */ 00158 void clear(); 00159 00160 /** 00161 * Returns an iterator pointing to the first element of the list. 00162 * The use of the interators is similar to the iterators of the 00163 * Standard Template Library (STL). 00164 */ 00165 iterator begin(); 00166 00167 /** 00168 * Returns an iterator pointing after the last element of the list. 00169 * The use of the interators is similar to the iterators of the 00170 * Standard Template Library (STL). 00171 */ 00172 iterator end(); 00173 00174 /** 00175 * Returns a const_iterator pointing to the first element of the list. 00176 * The use of the interators is similar to the iterators of the 00177 * Standard Template Library (STL). 00178 */ 00179 const_iterator begin() const; 00180 00181 /** 00182 * Returns a const_iterator pointing after the last element of the list. 00183 * The use of the interators is similar to the iterators of the 00184 * Standard Template Library (STL). 00185 */ 00186 const_iterator end() const; 00187 00188 /** 00189 * Erases the element at position pos, and returns an iterator pointing 00190 * to the next element after pos. 00191 */ 00192 iterator erase(iterator pos); 00193 00194 /** 00195 * Erases the elements between first and last, and returns an iterator 00196 * pointing to the next element after last. 00197 */ 00198 iterator erase(iterator first, iterator last); 00199 00200 /** 00201 * Inserts the range [first, last) before pos, and returns an iterator 00202 * pointing after the last inserted element. 00203 */ 00204 iterator insert(iterator pos, const_iterator first, const_iterator last); 00205 00206 /** 00207 * Inserts n copies of x before pos, and returns an iterator pointing 00208 * after the last inserted element. 00209 */ 00210 iterator insert(iterator pos, size_type n, const T& x); 00211 00212 /** 00213 * Inserts x before pos, and returns an iterator pointing after the 00214 * inserted element. 00215 */ 00216 iterator insert(iterator pos, const T& x); 00217 00218 /** 00219 * Removes all ocurrences of x found in the list. If the value 00220 * \a x is not in the list, the list remains unchanged. 00221 * @param x value to be removed from the list 00222 */ 00223 void remove(const T& x); 00224 00225 /** 00226 * Inserts x at the beginning of the list. 00227 */ 00228 void push_front(const T& x); 00229 00230 /** 00231 * Inserts x at the end of the list. 00232 */ 00233 void push_back(const T& x); 00234 00235 /** 00236 * Removes the first element from the list. 00237 */ 00238 void pop_front(); 00239 00240 /** 00241 * Removes the last element from the list. 00242 */ 00243 void pop_back(); 00244 00245 /** 00246 * Returns a reference to the first element of the list. 00247 */ 00248 reference front(); 00249 00250 /** 00251 * Returns a const_reference to the first element of the list. 00252 */ 00253 const_reference front() const; 00254 00255 /** 00256 * Returns a reference to the last element of the list. 00257 */ 00258 reference back(); 00259 00260 /** 00261 * Returns a const_reference to the last element of the list. 00262 */ 00263 const_reference back() const; 00264 00265 /** 00266 * Sorts this list according to the < operator. 00267 */ 00268 void sort(); 00269 00270 /** 00271 * Sorts this list according to the comparison function \a comp 00272 * which must return a bool and take two arguments of type T. 00273 */ 00274 template <class Compare> 00275 void sort(Compare comp); 00276 00277 /** 00278 * Swaps the contents of this list with the given list. 00279 */ 00280 void swap(smallObjectList<T>& l); 00281 00282 /** 00283 * Inserts all elements from the given list \a other before the 00284 * given \a position, and removes them from the given list. 00285 * 00286 * This is a constant time operation. 00287 */ 00288 void splice(iterator position, smallObjectList<T>& other); 00289 00290 /** 00291 * Removes the element at \a it from list \a other and inserts it 00292 * in this list before \a position. 00293 * 00294 * This is NOT a constant time operation. The computational cost is 00295 * equivalent to use insert and erase. The method is just provided for 00296 * interface compatibility with the std::list. 00297 */ 00298 void splice(iterator position, smallObjectList<T>& other, iterator it); 00299 00300 /** 00301 * Removes the elements in the interval [\a begin, \a end] from 00302 * list \a other and inserts them before \a position in this 00303 * list. 00304 * 00305 * This is NOT a constant time operation. The computational cost is 00306 * equivalent to use several insert and erase calls sequentially. The 00307 * method is just provided for interface compatibility with the std::list. 00308 */ 00309 void splice(iterator position, smallObjectList<T>& other, 00310 iterator begin, iterator end); 00311 00312 /** 00313 * Assignment operator. Clears this list, and copies the contents 00314 * of the given list. 00315 */ 00316 smallObjectList<T>& operator = (const smallObjectList<T>& l); 00317 00318 /** 00319 * Iterator class (allows read and write operations) 00320 * The use of the iterator classes is similar to the iterators of 00321 * the STL (Standard Template Library). 00322 */ 00323 class iterator { 00324 00325 public: 00326 00327 /** 00328 * Iterator traits. These are required by the algorithms 00329 * of the STL. 00330 */ 00331 typedef std::bidirectional_iterator_tag iterator_category; 00332 typedef T value_type; 00333 typedef T difference_type; 00334 typedef T* pointer; 00335 typedef T& reference; 00336 00337 private: 00338 00339 friend class smallObjectList<T>; 00340 friend class const_iterator; 00341 00342 /** 00343 * Pointer to the current node. 00344 */ 00345 node *node_; 00346 00347 protected: 00348 00349 /** 00350 * Creates an iterator for the given list, at the given position. 00351 */ 00352 iterator(node *n) : node_(n) { 00353 } 00354 00355 public: 00356 00357 /** 00358 * Creates an uninitialized iterator. 00359 */ 00360 iterator() : node_(0) { 00361 } 00362 00363 /** 00364 * Copy constructor. Creates a copy of the given iterator. 00365 */ 00366 iterator(const iterator& i) : node_(i.node_) { 00367 } 00368 00369 /** 00370 * Returns true if both iterators are at the same position on the 00371 * same list, false otherwise. 00372 */ 00373 bool operator == (const iterator& i) const { 00374 return node_ == i.node_; 00375 } 00376 00377 /** 00378 * Returns false if both iterators are at the same position on the 00379 * same list, true otherwise. 00380 */ 00381 bool operator != (const iterator& i) const { 00382 return node_ != i.node_; 00383 } 00384 00385 /** 00386 * Returns a reference to the current element. 00387 */ 00388 reference operator * () const { 00389 return node_->obj; 00390 } 00391 00392 // /** 00393 // * Overwrites the current element with the given element. 00394 // */ 00395 // reference operator * (T obj) const { 00396 // return node_->obj = obj; 00397 // } 00398 00399 /** 00400 * Returns a pointer to the current element. 00401 */ 00402 pointer operator->() const { 00403 return &((*node_).obj); 00404 } 00405 00406 /** 00407 * Moves forward one element in the list, and returns itself. 00408 */ 00409 iterator& operator ++ () { 00410 node_ = node_->next; 00411 return *this; 00412 } 00413 00414 /** 00415 * Moves forward one element in the list, and returns a copy of itself 00416 * before the move. 00417 */ 00418 iterator operator ++ (int) { 00419 iterator tmp(*this); 00420 ++*this; 00421 return tmp; 00422 } 00423 00424 /** 00425 * Moves backward one element in the list, and returns itself. 00426 */ 00427 iterator& operator -- () { 00428 node_ = node_->prev; 00429 return *this; 00430 } 00431 00432 /** 00433 * Moves backward one element in the list, and returns a copy of itself 00434 * before the move. 00435 */ 00436 iterator operator -- (int) { 00437 iterator tmp(*this); 00438 --*this; 00439 return tmp; 00440 } 00441 00442 }; 00443 00444 /** 00445 * Const_iterator class (allows read-only operations). 00446 * 00447 * The use of the iterator classes is similar to the iterators of 00448 * the STL (Standard Template Library). 00449 */ 00450 class const_iterator { 00451 00452 public: 00453 00454 /** 00455 * Iterator traits. These are required by the algorithms 00456 * of the STL. 00457 */ 00458 typedef std::bidirectional_iterator_tag iterator_category; 00459 typedef T value_type; 00460 typedef T difference_type; 00461 typedef T* pointer; 00462 typedef T& reference; 00463 00464 private: 00465 00466 friend class smallObjectList<T>; 00467 00468 /** 00469 * Pointer to the current position. 00470 */ 00471 const node *node_; 00472 00473 protected: 00474 00475 /** 00476 * Creates an const_iterator for the given list, at the given position. 00477 */ 00478 const_iterator(const node *p) : node_(p) { 00479 } 00480 00481 public: 00482 00483 /** 00484 * Creates an uninitialized const_iterator. 00485 */ 00486 const_iterator() : node_(0) { 00487 } 00488 00489 /** 00490 * Copy constructor. Creates a copy of the given const_iterator. 00491 */ 00492 const_iterator(const const_iterator& i) 00493 : node_(i.node_) { 00494 } 00495 00496 /** 00497 * Copy constructor. Creates a copy of the given iterator. 00498 */ 00499 const_iterator(const iterator& i) 00500 : node_(i.node_) { 00501 } 00502 00503 /** 00504 * Returns true if both iterators are at the same position on the 00505 * same list, false otherwise. 00506 */ 00507 bool operator == (const const_iterator& i) const { 00508 return node_ == i.node_; 00509 } 00510 00511 /** 00512 * Returns false if both iterators are at the same position on the 00513 * same list, true otherwise. 00514 */ 00515 bool operator != (const const_iterator& i) const { 00516 return node_ != i.node_; 00517 } 00518 00519 /** 00520 * Returns a const_reference to the current element. 00521 */ 00522 const_reference operator * () const { 00523 return node_->obj; 00524 } 00525 00526 /** 00527 * Returns a const_pointer to the current element. 00528 */ 00529 const_pointer operator -> () const { 00530 return &(node_->obj); 00531 } 00532 00533 /** 00534 * Moves forward one element in the list, and returns itself. 00535 */ 00536 const_iterator& operator ++ () { 00537 node_ = node_->next; 00538 return *this; 00539 } 00540 00541 /** 00542 * Moves forward one element in the list, and returns a copy of itself 00543 * before the move. 00544 */ 00545 const_iterator operator ++ (int) { 00546 const_iterator tmp(*this); 00547 ++*this; 00548 return tmp; 00549 } 00550 00551 /** 00552 * Moves backward one element in the list, and returns itself. 00553 */ 00554 const_iterator& operator -- () { 00555 node_ = node_->prev; 00556 return *this; 00557 } 00558 00559 /** 00560 * Moves backward one element in the list, and returns a copy of itself 00561 * before the move. 00562 */ 00563 const_iterator operator -- (int) { 00564 const_iterator tmp(*this); 00565 --*this; 00566 return tmp; 00567 } 00568 00569 }; 00570 00571 private: 00572 00573 /** 00574 * Node structure. 00575 * 00576 * Represents a node of the linked list. 00577 */ 00578 struct node { 00579 00580 /** 00581 * default constructor 00582 */ 00583 node() : obj(), prev(0), next(0) {}; 00584 00585 /** 00586 * copy constructor 00587 */ 00588 node(const node& other) 00589 : obj(other.obj), prev(other.prev), next(other.next) {}; 00590 00591 /** 00592 * copy the other node 00593 */ 00594 node& operator=(const node& other) { 00595 obj = other.obj; 00596 prev = other.prev; 00597 next = other.next; 00598 return *this; 00599 } 00600 00601 /** 00602 * The stored element. 00603 */ 00604 T obj; 00605 00606 /** 00607 * Pointer to the previous node. 00608 */ 00609 node *prev; 00610 00611 /** 00612 * Pointer to the next node. 00613 */ 00614 node *next; 00615 00616 }; 00617 00618 /** 00619 * A segment of the heap, used to allocate memory for nodes. Since 00620 * these nodes are used for a linked list, the unused nodes are 00621 * kept in a (singly) linked list of free nodes. 00622 */ 00623 class segment { 00624 00625 friend class heap; 00626 00627 private: 00628 00629 /** 00630 * The array of nodes contained in this segment 00631 */ 00632 node nodes_[_CVR_PERFORMANCE_SMALLOBJECTLIST_HEAP_SEGMENT_SIZE]; 00633 00634 /** 00635 * A pointer to the first free node of the segment 00636 */ 00637 node *firstFree; 00638 00639 /** 00640 * A pointer to the next segment in the heap 00641 */ 00642 segment* next; 00643 00644 /** 00645 * A pointer to the previous segment in the heap 00646 */ 00647 segment* prev; 00648 00649 /** 00650 * The number of nodes currently allocated in this segment 00651 */ 00652 short int nodeCount; 00653 00654 /** 00655 * don't copy it 00656 */ 00657 segment& operator=(const segment& o) {} 00658 00659 segment(const segment& o) {} 00660 00661 public: 00662 00663 /** 00664 * Constructor. Initializes the list of free nodes. 00665 */ 00666 segment(); 00667 00668 /** 00669 * Destructor 00670 */ 00671 ~segment(); 00672 00673 /** 00674 * Determines if the given node is contained in this segment, that is, 00675 * if the pointer points within the inner node array. 00676 */ 00677 inline bool contains(node *node); 00678 00679 /** 00680 * 'Grabs' (allocates) a node in this segment. 00681 */ 00682 inline node* grab(); 00683 00684 /** 00685 * Releases the given node in this segment 00686 */ 00687 inline void release(node *n); 00688 00689 }; 00690 00691 /** 00692 * A heap of nodes. 00693 * 00694 * Stores nodes in dynamically allocated segments. 00695 */ 00696 class heap { 00697 00698 private: 00699 00700 /** 00701 * A pointer to the first segment in the list of segments 00702 */ 00703 segment *first_; 00704 00705 /** 00706 * A pointer to the segment most recently used for allocation 00707 */ 00708 segment *recentAlloc_; 00709 00710 /** 00711 * A pointer to the segment most recently used for deallocation 00712 */ 00713 segment *recentDealloc_; 00714 00715 /** 00716 * The total object count contained in this heap 00717 */ 00718 unsigned long int objectCount_; 00719 00720 /** 00721 * The number of segments in this heap 00722 */ 00723 unsigned long int segmentCount_; 00724 00725 public: 00726 00727 /** 00728 * Constructor 00729 */ 00730 heap(); 00731 00732 /** 00733 * Destructor 00734 */ 00735 ~heap(); 00736 00737 /** 00738 * Disable the copy constructor 00739 */ 00740 heap(const heap&); 00741 00742 /** 00743 * Disable the assignment operator 00744 */ 00745 heap& operator= (const heap&); 00746 00747 /* 00748 * The singleton instance accessor 00749 */ 00750 //static heap& instance(); 00751 00752 /** 00753 * Allocates a new node in the heap 00754 */ 00755 node *allocate(); 00756 00757 /** 00758 * Frees the given node from the heap 00759 */ 00760 void deallocate(node *n); 00761 00762 /** 00763 * Transfer all data to the other heap 00764 */ 00765 void detach(heap& other); 00766 00767 /** 00768 * Assign all data of the other heap to this one 00769 */ 00770 void attach(heap& other); 00771 00772 /** 00773 * Swap the contents of two heaps 00774 */ 00775 void swap(heap& other); 00776 }; 00777 00778 /** 00779 * The heap of nodes, used for memory allocation and management. 00780 */ 00781 heap heap_; 00782 00783 /** 00784 * The 'end' node. This node marks the end of the list, and contains no 00785 * user data. Its 'next' is the first element of the list, and its 'prev' 00786 * is the last. Therefore, for an empty list, both of these pointers point 00787 * at end_; 00788 */ 00789 node end_; 00790 00791 /** 00792 * Quicksort implementation used by sort(). 00793 */ 00794 void quicksort(iterator front, iterator back); 00795 00796 /** 00797 * Quicksort implementation used by sort(comp). See sort(Compare 00798 * comp) for details. 00799 */ 00800 template <class Compare> 00801 void quicksort(iterator front, iterator back, Compare comp); 00802 00803 /** 00804 * Moves the elements from [\a first,\a last) before \a position 00805 * 00806 * This is a helper function for splice(). 00807 */ 00808 /* 00809 void spliceHelper(iterator position, 00810 smallObjectList<T>& other, 00811 iterator first, 00812 iterator last); 00813 */ 00814 00815 }; 00816 00817 } 00818 00819 #include "cvrSmallObjectList_template.h" 00820 #include "cvrSmallObjectList_inline.h" 00821 00822 #endif