Simple Application Framework
1
|
00001 /* 00002 This file is part of Simple Application Framework (Saf) library. 00003 Copyright (C) 2010 - 2012 Ondrej Danek <ondrej.danek@gmail.com> 00004 00005 This library is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published 00007 by the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 Saf is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Simple Application Framework library. If not, 00017 see <http://www.gnu.org/licenses/>. 00018 */ 00019 00028 #ifndef SAF_COLLECTION_DEQUEUE_H 00029 #define SAF_COLLECTION_DEQUEUE_H 00030 00031 #include "../Mem/Alloc.h" 00032 #include "../Algo/Swap.h" 00033 #include "../Algo/Selection/MinMax.h" 00034 #include "../Math/Calculus/Powers.h" 00035 #include "../Type/IteratorCategory.h" 00036 #include "Array.h" 00037 00038 namespace Saf 00039 { 00040 namespace Collection 00041 { 00064 template <class T> 00065 class Deque 00066 { 00067 protected: 00068 typedef Deque<T> MyType; 00069 00070 public: 00072 class ConstIterator 00073 { 00074 public: 00075 typedef T ValType; 00076 typedef Type::IteratorCategory::RandomAccessCategory CategoryType; 00077 00078 protected: 00080 Size m_ofs; 00082 T *m_ptr; 00084 MyType *m_deque; 00085 00086 // Deque needs to access the protected properties 00087 friend class Deque<T>; 00088 00089 public: 00091 ConstIterator() 00092 {} 00093 00095 explicit ConstIterator(Size ofs, MyType &deque) 00096 : m_ofs(ofs), m_ptr(deque.ElementAt(ofs)), m_deque(&deque) 00097 {} 00098 00100 ConstIterator(const ConstIterator& it) 00101 : m_ofs(it.m_ofs), m_ptr(it.m_ptr), m_deque(it.m_deque) 00102 {} 00103 00105 ConstIterator& operator=(const ConstIterator& it) 00106 { 00107 m_ofs = it.m_ofs; 00108 m_ptr = it.m_ptr; 00109 m_deque = it.m_deque; 00110 return *this; 00111 } 00112 00114 const T& operator*() const 00115 { 00116 return *m_ptr; 00117 } 00118 00120 const T* operator->() const 00121 { 00122 return m_ptr; 00123 } 00124 00126 ConstIterator& operator++() 00127 { 00128 if (!m_deque->BlockOffset(++m_ofs)) 00129 { 00130 m_ptr = m_deque->ElementAt(m_ofs); 00131 } 00132 else 00133 { 00134 ++m_ptr; 00135 } 00136 00137 return *this; 00138 } 00139 00141 ConstIterator operator++(int) 00142 { 00143 ConstIterator ci(*this); 00144 ++(*this); 00145 return ci; 00146 } 00147 00149 ConstIterator& operator+=(Diff offset) 00150 { 00151 m_ofs += offset; 00152 m_ptr = m_deque->ElementAt(m_ofs); 00153 return *this; 00154 } 00155 00157 ConstIterator operator+(Diff offset) const 00158 { 00159 ConstIterator ci(*this); 00160 ci += offset; 00161 return ci; 00162 } 00163 00165 ConstIterator& operator--() 00166 { 00167 if (!m_deque->BlockOffset(m_ofs--)) 00168 { 00169 m_ptr = m_deque->ElementAt(m_ofs); 00170 } 00171 else 00172 { 00173 --m_ptr; 00174 } 00175 00176 return *this; 00177 } 00178 00180 ConstIterator operator--(int) 00181 { 00182 ConstIterator ci(*this); 00183 --(*this); 00184 return ci; 00185 } 00186 00188 ConstIterator& operator-=(Diff offset) 00189 { 00190 m_ofs -= offset; 00191 m_ptr = m_deque->ElementAt(m_ofs); 00192 return *this; 00193 } 00194 00196 ConstIterator operator-(Diff offset) const 00197 { 00198 ConstIterator ci(*this); 00199 ci -= offset; 00200 return ci; 00201 } 00202 00204 bool operator==(const ConstIterator& it) const 00205 { 00206 return (m_ofs == it.m_ofs); 00207 } 00208 00210 bool operator!=(const ConstIterator& it) const 00211 { 00212 return (m_ofs != it.m_ofs); 00213 } 00214 00216 bool operator<(const ConstIterator& it) const 00217 { 00218 return (m_ofs < it.m_ofs); 00219 } 00220 00222 bool operator>(const ConstIterator& it) const 00223 { 00224 return (m_ofs > it.m_ofs); 00225 } 00226 00228 bool operator<=(const ConstIterator& it) const 00229 { 00230 return (m_ofs <= it.m_ofs); 00231 } 00232 00234 bool operator>=(const ConstIterator& it) const 00235 { 00236 return (m_ofs >= it.m_ofs); 00237 } 00238 00240 const T& operator[](Diff ofs) const 00241 { 00242 return *m_deque->ElementAt(m_ofs + ofs); 00243 } 00244 00246 Diff operator-(const ConstIterator& it) const 00247 { 00248 return (m_ofs < it.m_ofs) ? -Diff(it.m_ofs - m_ofs) 00249 : Diff(m_ofs - it.m_ofs); 00250 } 00251 }; 00252 00254 class Iterator 00255 : public ConstIterator 00256 { 00257 public: 00259 Iterator() 00260 : ConstIterator() 00261 {} 00262 00264 explicit Iterator(Size ofs, MyType &deque) 00265 : ConstIterator(ofs, deque) 00266 {} 00267 00269 Iterator(const Iterator& iter) 00270 : ConstIterator(iter) 00271 {} 00272 00274 Iterator& operator=(const Iterator& iter) 00275 { 00276 ConstIterator::operator=(iter); 00277 return *this; 00278 } 00279 00281 T& operator*() const 00282 { 00283 return *this->m_ptr; 00284 } 00285 00287 T* operator->() const 00288 { 00289 return this->m_ptr; 00290 } 00291 00293 Iterator& operator++() 00294 { 00295 ++(*((ConstIterator *)this)); 00296 return *this; 00297 } 00298 00300 Iterator operator++(int) 00301 { 00302 Iterator it(*this); 00303 ++(*this); 00304 return it; 00305 } 00306 00308 Iterator& operator+=(Diff offset) 00309 { 00310 *((ConstIterator *)this) += offset; 00311 return *this; 00312 } 00313 00315 Iterator operator+(Diff offset) const 00316 { 00317 Iterator it(*this); 00318 it += offset; 00319 return it; 00320 } 00321 00323 Iterator& operator--() 00324 { 00325 --(*((ConstIterator *)this)); 00326 return *this; 00327 } 00328 00330 Iterator operator--(int) 00331 { 00332 Iterator it(*this); 00333 --(*this); 00334 return it; 00335 } 00336 00338 Iterator& operator-=(Diff offset) 00339 { 00340 *((ConstIterator *)this) -= offset; 00341 return *this; 00342 } 00343 00345 Iterator operator-(Diff offset) const 00346 { 00347 Iterator it(*this); 00348 it -= offset; 00349 return it; 00350 } 00351 00353 T& operator[](Diff ofs) const 00354 { 00355 return *this->m_deque->ElementAt(this->m_ofs + ofs); 00356 } 00357 00359 Diff operator-(const Iterator& it) const 00360 { 00361 return (this->m_ofs < it.m_ofs) ? -Diff(it.m_ofs - this->m_ofs) 00362 : Diff(this->m_ofs - it.m_ofs); 00363 } 00364 }; 00365 00366 protected: 00373 static const Size MinBlockSize = 4096; 00378 static const Size MinMapSize = 8; 00379 00380 private: 00386 Array<1,T *> m_map; 00388 Size m_mapMask; 00390 Size m_blockBits; 00392 Size m_blockMask; 00394 Iterator m_begin; 00396 Iterator m_end; 00397 00398 protected: 00400 T *ElementAt(Size ofs) 00401 { 00402 return m_map[BlockIndex(ofs)] + BlockOffset(ofs); 00403 } 00404 00406 const T *ElementAt(Size ofs) const 00407 { 00408 return m_map[BlockIndex(ofs)] + BlockOffset(ofs); 00409 } 00410 00412 Size BlockSize() const 00413 { 00414 return (Size(1) << m_blockBits); 00415 } 00416 00418 Size BlockIndex(Size ofs) const 00419 { 00420 return (ofs >> m_blockBits) & m_mapMask; 00421 } 00422 00424 Size BlockOffset(Size ofs) const 00425 { 00426 return ofs & m_blockMask; 00427 } 00428 00430 void ComputeBlockSize() 00431 { 00432 Size blockElemCount = Math::IntegerDivCeil(MinBlockSize, sizeof(T)); 00433 Size blockSize = Math::Calculus::RoundUpToPowerOf2(blockElemCount); 00434 m_blockBits = Math::Calculus::BinaryLogarithm(blockSize); 00435 m_blockMask = blockSize - 1; 00436 } 00437 00439 void AllocateBlock(T *&block) 00440 { 00441 if (block == nullptr) 00442 { 00443 Mem::OperatorNew(block, BlockSize(), SAF_SOURCE_LOCATION); 00444 } 00445 } 00446 00448 void InitIterators() 00449 { 00450 m_begin.m_ofs = 0; 00451 m_begin.m_ptr = nullptr; 00452 m_begin.m_deque = this; 00453 00454 m_end.m_ofs = 0; 00455 m_end.m_ptr = nullptr; 00456 m_end.m_deque = this; 00457 } 00458 00460 void GrowMap() 00461 { 00462 if (m_map.IsEmpty()) 00463 { 00464 m_map.Resize(MinMapSize, nullptr); 00465 m_mapMask = m_map.Elements() - 1; 00466 00467 // Allocate room for the sentinel element and setup iterators 00468 AllocateBlock(m_map[0]); 00469 00470 m_begin.m_ofs = 0; 00471 m_begin.m_ptr = m_map[0]; 00472 m_end.m_ofs = 0; 00473 m_end.m_ptr = m_map[0]; 00474 } 00475 else 00476 { 00477 // Double the size of the map 00478 Array<1,T *> newMap(2 * m_map.Elements()); 00479 00480 // Copy old block pointers (unroll map) 00481 Size firstBlock = BlockIndex(m_begin.m_ofs); 00482 typename Array<1,T *>::Iterator iter = newMap.Begin(); 00483 00484 for (Size i = 0; i < m_map.Elements(); ++i, ++iter) 00485 { 00486 *iter = m_map[firstBlock]; 00487 firstBlock = (firstBlock + 1) & m_mapMask; 00488 } 00489 00490 // Initialize new block pointers 00491 Algo::Range::Fill(iter, newMap.End(), (T *)nullptr); 00492 00493 // Replace old map with the new one 00494 Algo::Swap(m_map, newMap); 00495 m_mapMask = m_map.Elements() - 1; 00496 00497 // Update iterators -> shift to beginning of the new map 00498 Size elems = Elements(); 00499 m_begin.m_ofs = BlockOffset(m_begin.m_ofs); 00500 m_end.m_ofs = m_begin.m_ofs + elems; 00501 } 00502 } 00503 00510 Size NormElemCount() const 00511 { 00512 return BlockOffset(m_begin.m_ofs) + Elements() + 1; 00513 } 00514 00515 public: 00521 explicit Deque(Size elems = 0, const T& val = T()) 00522 : m_mapMask(0) 00523 { 00524 ComputeBlockSize(); 00525 InitIterators(); 00526 00527 while (elems-- > 0) 00528 { 00529 PushBack(val); 00530 } 00531 } 00532 00534 Deque(const MyType& d) 00535 : m_mapMask(0) 00536 { 00537 ComputeBlockSize(); 00538 InitIterators(); 00539 *this = d; 00540 } 00541 00543 ~Deque() 00544 { 00545 Free(); 00546 } 00547 00549 MyType& operator=(const MyType& d) 00550 { 00551 if (this != &d) 00552 { 00553 Free(); 00554 00555 m_blockBits = d.m_blockBits; 00556 m_blockMask = d.m_blockMask; 00557 00558 // Copy elements 00559 for (ConstIterator ci = d.Begin(); ci != d.End(); ++ci) 00560 { 00561 PushBack(*ci); 00562 } 00563 } 00564 00565 return *this; 00566 } 00567 00569 void Free() 00570 { 00571 while (!IsEmpty()) 00572 { 00573 PopBack(); 00574 } 00575 00576 for (Size i = 0; i < m_map.Elements(); i++) 00577 { 00578 if (m_map[i] != nullptr) 00579 { 00580 Mem::OperatorDelete(m_map[i], BlockSize()); 00581 } 00582 } 00583 00584 InitIterators(); 00585 m_map.Free(); 00586 m_mapMask = 0; 00587 } 00588 00594 MyType& Swap(MyType& d) 00595 { 00596 if (this != &d) 00597 { 00598 m_map.Swap(d.m_map); 00599 Algo::Swap(m_mapMask, d.m_mapMask); 00600 Algo::Swap(m_blockBits, d.m_blockBits); 00601 Algo::Swap(m_blockMask, d.m_blockMask); 00602 Algo::Swap(m_begin, d.m_begin); 00603 Algo::Swap(m_end, d.m_end); 00604 } 00605 00606 return *this; 00607 } 00608 00614 Size Elements() const 00615 { 00616 return (m_end - m_begin); 00617 } 00618 00624 bool IsEmpty() const 00625 { 00626 return (m_begin == m_end); 00627 } 00628 00636 MyType& PushBack(const T& val) 00637 { 00638 // Check if we need to enlarge the block map 00639 if ((NormElemCount() >> m_blockBits) >= m_map.Elements()) 00640 { 00641 GrowMap(); 00642 } 00643 00644 // Insert position 00645 T *insPtr = m_end.m_ptr; 00646 00647 // Increment end iterator 00648 AllocateBlock(m_map[BlockIndex(m_end.m_ofs + 1)]); 00649 ++m_end; 00650 00651 // Insert new element 00652 new (insPtr) T(val); 00653 00654 // Make sure that the start offset doesn't go to infinity after a series 00655 // of PushBack() + PopFront() operations. We cannot do this in PopFront() 00656 // because that would invalidate iterators. 00657 if ((m_begin.m_ofs >> m_blockBits) > m_mapMask) 00658 { 00659 Size elems = m_end.m_ofs - m_begin.m_ofs; 00660 m_begin.m_ofs &= (m_map.Elements() << m_blockBits) - 1; 00661 m_end.m_ofs = m_begin.m_ofs + elems; 00662 } 00663 00664 return *this; 00665 } 00666 00674 MyType& PushFront(const T& val) 00675 { 00676 // Check if we need to enlarge the block map 00677 if ((NormElemCount() >> m_blockBits) >= m_map.Elements()) 00678 { 00679 GrowMap(); 00680 } 00681 00682 // Shift offsets if necessary 00683 if (!m_begin.m_ofs) 00684 { 00685 Size totalCap = (m_map.Elements() << m_blockBits); 00686 m_begin.m_ofs = totalCap; 00687 m_end.m_ofs += totalCap; 00688 } 00689 00690 // Decrement begin iterator and insert element 00691 AllocateBlock(m_map[BlockIndex(m_begin.m_ofs - 1)]); 00692 --m_begin; 00693 new (m_begin.m_ptr) T(val); 00694 00695 return *this; 00696 } 00697 00707 MyType& PopBack() 00708 { 00709 if (!IsEmpty()) 00710 { 00711 --m_end; 00712 m_end.m_ptr->~T(); 00713 } 00714 00715 return *this; 00716 } 00717 00726 MyType& PopFront() 00727 { 00728 if (!IsEmpty()) 00729 { 00730 T *ptr = m_begin.m_ptr; 00731 ++m_begin; 00732 ptr->~T(); 00733 } 00734 00735 return *this; 00736 } 00737 00744 void Shrink() 00745 { 00746 if (IsEmpty()) 00747 { 00748 Free(); 00749 } 00750 else 00751 { 00752 // First block with valid elements 00753 Size firstBlock = BlockIndex(m_begin.m_ofs); 00754 // Number of blocks containing valid elements 00755 Size validBlocks = Math::IntegerDivCeil(NormElemCount(), BlockSize()); 00756 00757 // Create new block map 00758 Array<1,T *> newMap(Algo::Selection::Max(MinMapSize, Math::Calculus::RoundUpToPowerOf2(validBlocks))); 00759 typename Array<1,T *>::Iterator iter = newMap.Begin(); 00760 00761 // Unroll the map, copy pointers to valid blocks and free empty blocks 00762 for (Size i = 0; i < m_map.Elements(); ++i) 00763 { 00764 if (i < validBlocks) 00765 { 00766 *iter = m_map[firstBlock]; 00767 ++iter; 00768 } 00769 else if (m_map[firstBlock] != nullptr) 00770 { 00771 Mem::OperatorDelete(m_map[firstBlock], BlockSize()); 00772 } 00773 00774 firstBlock = (firstBlock + 1) & m_mapMask; 00775 } 00776 00777 // Initialize new block pointers 00778 Algo::Range::Fill(iter, newMap.End(), (T *)nullptr); 00779 00780 // Replace old map with the new one 00781 Algo::Swap(m_map, newMap); 00782 m_mapMask = m_map.Elements() - 1; 00783 00784 // Update iterators -> shift to beginning of the new map 00785 Size elems = Elements(); 00786 m_begin.m_ofs = BlockOffset(m_begin.m_ofs); 00787 m_end.m_ofs = m_begin.m_ofs + elems; 00788 } 00789 } 00790 00792 T& operator[](Size i) 00793 { 00794 return m_begin[i]; 00795 } 00796 00798 const T& operator[](Size i) const 00799 { 00800 return m_begin[i]; 00801 } 00802 00804 Iterator Begin() 00805 { 00806 return m_begin; 00807 } 00808 00810 ConstIterator Begin() const 00811 { 00812 return m_begin; 00813 } 00814 00816 Iterator End() 00817 { 00818 return m_end; 00819 } 00820 00822 ConstIterator End() const 00823 { 00824 return m_end; 00825 } 00826 00828 Iterator Front() 00829 { 00830 return Begin(); 00831 } 00832 00834 ConstIterator Front() const 00835 { 00836 return Begin(); 00837 } 00838 00843 Iterator Back() 00844 { 00845 Iterator iEnd(m_end); 00846 return --iEnd; 00847 } 00848 00853 ConstIterator Back() const 00854 { 00855 ConstIterator iEnd(m_end); 00856 return --iEnd; 00857 } 00858 }; 00859 } 00860 00862 namespace Algo 00863 { 00864 // Swap specialization for the double-ended queue container. 00865 template <class T> 00866 struct SwapFunc< Collection::Deque<T> > 00867 { 00868 void operator()(Collection::Deque<T>& x, Collection::Deque<T>& y) 00869 { 00870 x.Swap(y); 00871 } 00872 }; 00873 } 00875 } 00876 00877 #endif