Simple Application Framework  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Saf/Collection/Deque.h
Go to the documentation of this file.
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