src/corelib/tools/qcontiguouscache.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcontiguouscache.h"
       
    43 #ifdef QT_QCONTIGUOUSCACHE_DEBUG
       
    44 #include <QDebug>
       
    45 #endif
       
    46 
       
    47 QT_BEGIN_NAMESPACE
       
    48 
       
    49 #ifdef QT_QCONTIGUOUSCACHE_DEBUG
       
    50 void QContiguousCacheData::dump() const
       
    51 {
       
    52     qDebug() << "capacity:" << alloc;
       
    53     qDebug() << "count:" << count;
       
    54     qDebug() << "start:" << start;
       
    55     qDebug() << "offset:" << offset;
       
    56 }
       
    57 #endif
       
    58 
       
    59 /*! \class QContiguousCache
       
    60     \brief The QContiguousCache class is a template class that provides a contiguous cache.
       
    61     \ingroup tools
       
    62     \ingroup shared
       
    63     \reentrant
       
    64     \since 4.6
       
    65 
       
    66     The QContiguousCache class provides an efficient way of caching items for
       
    67     display in a user interface view.  Unlike QCache, it adds a restriction
       
    68     that elements within the cache are contiguous.  This has the advantage
       
    69     of matching how user interface views most commonly request data, as
       
    70     a set of rows localized around the current scrolled position.  This
       
    71     restriction allows the cache to consume less memory and processor
       
    72     cycles than QCache.  The QContiguousCache class also can provide
       
    73     an upper bound on memory usage via setCapacity().
       
    74 
       
    75     The simplest way of using a contiguous cache is to use the append()
       
    76     and prepend().
       
    77 
       
    78 \code
       
    79 MyRecord record(int row) const
       
    80 {
       
    81     Q_ASSERT(row >= 0 && row < count());
       
    82 
       
    83     while(row > cache.lastIndex())
       
    84         cache.append(slowFetchRecord(cache.lastIndex()+1));
       
    85     while(row < cache.firstIndex())
       
    86         cache.prepend(slowFetchRecord(cache.firstIndex()-1));
       
    87 
       
    88     return cache.at(row);
       
    89 }
       
    90 \endcode
       
    91 
       
    92     If the cache is full then the item at the opposite end of the cache from
       
    93     where the new item is appended or prepended will be removed.
       
    94 
       
    95     This usage can be further optimized by using the insert() function
       
    96     in the case where the requested row is a long way from the currently cached
       
    97     items. If there is a gap between where the new item is inserted and the currently
       
    98     cached items then the existing cached items are first removed to retain
       
    99     the contiguous nature of the cache. Hence it is important to take some care then
       
   100     when using insert() in order to avoid unwanted clearing of the cache.
       
   101 
       
   102     The range of valid indexes for the QContiguousCache class are from
       
   103     0 to INT_MAX.  Calling prepend() such that the first index would become less
       
   104     than 0 or append() such that the last index would become greater
       
   105     than INT_MAX can result in the indexes of the cache being invalid.
       
   106     When the cache indexes are invalid it is important to call
       
   107     normalizeIndexes() before calling any of containsIndex(), firstIndex(),
       
   108     lastIndex(), at() or \l{QContiguousCache::operator[]()}{operator[]()}.
       
   109     Calling these functions when the cache has invalid indexes will result in
       
   110     undefined behavior. The indexes can be checked by using areIndexesValid()
       
   111 
       
   112     In most cases the indexes will not exceed 0 to INT_MAX, and
       
   113     normalizeIndexes() will not need to be used.
       
   114 
       
   115     See the \l{Contiguous Cache Example}{Contiguous Cache} example.
       
   116 */
       
   117 
       
   118 /*! \fn QContiguousCache::QContiguousCache(int capacity)
       
   119 
       
   120     Constructs a cache with the given \a capacity.
       
   121 
       
   122     \sa setCapacity()
       
   123 */
       
   124 
       
   125 /*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
       
   126 
       
   127     Constructs a copy of \a other.
       
   128 
       
   129     This operation takes \l{constant time}, because QContiguousCache is
       
   130     \l{implicitly shared}.  This makes returning a QContiguousCache from a
       
   131     function very fast.  If a shared instance is modified, it will be
       
   132     copied (copy-on-write), and that takes \l{linear time}.
       
   133 
       
   134     \sa operator=()
       
   135 */
       
   136 
       
   137 /*! \fn QContiguousCache::~QContiguousCache()
       
   138 
       
   139     Destroys the cache.
       
   140 */
       
   141 
       
   142 /*! \fn void QContiguousCache::detach()
       
   143 
       
   144     \internal
       
   145 */
       
   146 
       
   147 /*! \fn bool QContiguousCache::isDetached() const
       
   148 
       
   149     \internal
       
   150 */
       
   151 
       
   152 /*! \fn void QContiguousCache::setSharable(bool sharable)
       
   153 
       
   154     \internal
       
   155 */
       
   156 
       
   157 /*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
       
   158 
       
   159     Assigns \a other to this cache and returns a reference to this cache.
       
   160 */
       
   161 
       
   162 /*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
       
   163 
       
   164     Returns true if \a other is equal to this cache; otherwise returns false.
       
   165 
       
   166     Two caches are considered equal if they contain the same values at the same
       
   167     indexes.  This function requires the value type to implement the \c operator==().
       
   168 
       
   169     \sa operator!=()
       
   170 */
       
   171 
       
   172 /*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
       
   173 
       
   174     Returns true if \a other is not equal to this cache; otherwise
       
   175     returns false.
       
   176 
       
   177     Two caches are considered equal if they contain the same values at the same
       
   178     indexes.  This function requires the value type to implement the \c operator==().
       
   179 
       
   180     \sa operator==()
       
   181 */
       
   182 
       
   183 /*! \fn int QContiguousCache::capacity() const
       
   184 
       
   185     Returns the number of items the cache can store before it is full.
       
   186     When a cache contains a number of items equal to its capacity, adding new
       
   187     items will cause items farthest from the added item to be removed.
       
   188 
       
   189     \sa setCapacity(), size()
       
   190 */
       
   191 
       
   192 /*! \fn int QContiguousCache::count() const
       
   193 
       
   194     Same as size().
       
   195 */
       
   196 
       
   197 /*! \fn int QContiguousCache::size() const
       
   198 
       
   199     Returns the number of items contained within the cache.
       
   200 
       
   201     \sa capacity()
       
   202 */
       
   203 
       
   204 /*! \fn bool QContiguousCache::isEmpty() const
       
   205 
       
   206     Returns true if no items are stored within the cache.
       
   207 
       
   208     \sa size(), capacity()
       
   209 */
       
   210 
       
   211 /*! \fn bool QContiguousCache::isFull() const
       
   212 
       
   213     Returns true if the number of items stored within the cache is equal
       
   214     to the capacity of the cache.
       
   215 
       
   216     \sa size(), capacity()
       
   217 */
       
   218 
       
   219 /*! \fn int QContiguousCache::available() const
       
   220 
       
   221     Returns the number of items that can be added to the cache before it becomes full.
       
   222 
       
   223     \sa size(), capacity(), isFull()
       
   224 */
       
   225 
       
   226 /*! \fn void QContiguousCache::clear()
       
   227 
       
   228     Removes all items from the cache.  The capacity is unchanged.
       
   229 */
       
   230 
       
   231 /*! \fn void QContiguousCache::setCapacity(int size)
       
   232 
       
   233     Sets the capacity of the cache to the given \a size.  A cache can hold a
       
   234     number of items equal to its capacity.  When inserting, appending or prepending
       
   235     items to the cache, if the cache is already full then the item farthest from
       
   236     the added item will be removed.
       
   237 
       
   238     If the given \a size is smaller than the current count of items in the cache
       
   239     then only the last \a size items from the cache will remain.
       
   240 
       
   241     \sa capacity(), isFull()
       
   242 */
       
   243 
       
   244 /*! \fn const T &QContiguousCache::at(int i) const
       
   245 
       
   246     Returns the item at index position \a i in the cache.  \a i must
       
   247     be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
       
   248 
       
   249     The indexes in the cache refer to the number of positions the item is from the
       
   250     first item appended into the cache.  That is to say a cache with a capacity of
       
   251     100, that has had 150 items appended will have a valid index range of
       
   252     50 to 149.  This allows inserting and retrieving items into the cache based
       
   253     on a theoretical infinite list
       
   254 
       
   255     \sa firstIndex(), lastIndex(), insert(), operator[]()
       
   256 */
       
   257 
       
   258 /*! \fn T &QContiguousCache::operator[](int i)
       
   259 
       
   260     Returns the item at index position \a i as a modifiable reference. If
       
   261     the cache does not contain an item at the given index position \a i
       
   262     then it will first insert an empty item at that position.
       
   263 
       
   264     In most cases it is better to use either at() or insert().
       
   265 
       
   266     \note This non-const overload of operator[] requires QContiguousCache 
       
   267     to make a deep copy. Use at() for read-only access to a non-const 
       
   268     QContiguousCache.
       
   269 
       
   270     \sa insert(), at()
       
   271 */
       
   272 
       
   273 /*! \fn const T &QContiguousCache::operator[](int i) const
       
   274 
       
   275     \overload
       
   276 
       
   277     Same as at(\a i).
       
   278 */
       
   279 
       
   280 /*! \fn void QContiguousCache::append(const T &value)
       
   281 
       
   282     Inserts \a value at the end of the cache.  If the cache is already full
       
   283     the item at the start of the cache will be removed.
       
   284 
       
   285     \sa prepend(), insert(), isFull()
       
   286 */
       
   287 
       
   288 /*! \fn void QContiguousCache::prepend(const T &value)
       
   289 
       
   290     Inserts \a value at the start of the cache.  If the cache is already full
       
   291     the item at the end of the cache will be removed.
       
   292 
       
   293     \sa append(), insert(), isFull()
       
   294 */
       
   295 
       
   296 /*! \fn void QContiguousCache::insert(int i, const T &value)
       
   297 
       
   298     Inserts the \a value at the index position \a i.  If the cache already contains
       
   299     an item at \a i then that value is replaced.  If \a i is either one more than
       
   300     lastIndex() or one less than firstIndex() it is the equivalent to an append()
       
   301     or a prepend().
       
   302 
       
   303     If the given index \a i is not within the current range of the cache nor adjacent
       
   304     to the bounds of the cache's index range, the cache is first cleared before
       
   305     inserting the item.  At this point the cache will have a size of 1.  It is
       
   306     worthwhile taking effort to insert items in an order that starts adjacent
       
   307     to the current index range for the cache.
       
   308 
       
   309     The range of valid indexes for the QContiguousCache class are from
       
   310     0 to INT_MAX. Inserting outside of this range has undefined behavior.
       
   311 
       
   312 
       
   313     \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
       
   314 */
       
   315 
       
   316 /*! \fn bool QContiguousCache::containsIndex(int i) const
       
   317 
       
   318     Returns true if the cache's index range includes the given index \a i.
       
   319 
       
   320     \sa firstIndex(), lastIndex()
       
   321 */
       
   322 
       
   323 /*! \fn int QContiguousCache::firstIndex() const
       
   324 
       
   325     Returns the first valid index in the cache.  The index will be invalid if the
       
   326     cache is empty.
       
   327 
       
   328     \sa capacity(), size(), lastIndex()
       
   329 */
       
   330 
       
   331 /*! \fn int QContiguousCache::lastIndex() const
       
   332 
       
   333     Returns the last valid index in the cache.  The index will be invalid if the cache is empty.
       
   334 
       
   335     \sa capacity(), size(), firstIndex()
       
   336 */
       
   337 
       
   338 
       
   339 /*! \fn T &QContiguousCache::first()
       
   340 
       
   341     Returns a reference to the first item in the cache.  This function
       
   342     assumes that the cache isn't empty.
       
   343 
       
   344     \sa last(), isEmpty()
       
   345 */
       
   346 
       
   347 /*! \fn T &QContiguousCache::last()
       
   348 
       
   349     Returns a reference to the last item in the cache.  This function
       
   350     assumes that the cache isn't empty.
       
   351 
       
   352     \sa first(), isEmpty()
       
   353 */
       
   354 
       
   355 /*! \fn const T& QContiguousCache::first() const
       
   356 
       
   357     \overload
       
   358 */
       
   359 
       
   360 /*! \fn const T& QContiguousCache::last() const
       
   361 
       
   362     \overload
       
   363 */
       
   364 
       
   365 /*! \fn void QContiguousCache::removeFirst()
       
   366 
       
   367     Removes the first item from the cache.  This function assumes that
       
   368     the cache isn't empty.
       
   369 
       
   370     \sa removeLast()
       
   371 */
       
   372 
       
   373 /*! \fn void QContiguousCache::removeLast()
       
   374 
       
   375     Removes the last item from the cache.  This function assumes that
       
   376     the cache isn't empty.
       
   377 
       
   378     \sa removeFirst()
       
   379 */
       
   380 
       
   381 /*! \fn T QContiguousCache::takeFirst()
       
   382 
       
   383     Removes the first item in the cache and returns it.  This function
       
   384     assumes that the cache isn't empty.
       
   385 
       
   386     If you don't use the return value, removeFirst() is more efficient.
       
   387 
       
   388     \sa takeLast(), removeFirst()
       
   389 */
       
   390 
       
   391 /*! \fn T QContiguousCache::takeLast()
       
   392 
       
   393     Removes the last item in the cache and returns it. This function
       
   394     assumes that the cache isn't empty.
       
   395 
       
   396     If you don't use the return value, removeLast() is more efficient.
       
   397 
       
   398     \sa takeFirst(), removeLast()
       
   399 */
       
   400 
       
   401 /*! \fn void QContiguousCache::normalizeIndexes()
       
   402 
       
   403     Moves the first index and last index of the cache
       
   404     such that they point to valid indexes.  The function does not modify
       
   405     the contents of the cache or the ordering of elements within the cache.
       
   406 
       
   407     It is provided so that index overflows can be corrected when using the
       
   408     cache as a circular buffer.
       
   409 
       
   410     \code
       
   411     QContiguousCache<int> cache(10);
       
   412     cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
       
   413     cache.append(2); // cache contains two values but does not have valid indexes.
       
   414     cache.normalizeIndexes(); // cache has two values, 1 and 2.  New first index will be in the range of 0 to capacity().
       
   415     \endcode
       
   416 
       
   417     \sa areIndexesValid(), append(), prepend()
       
   418 */
       
   419 
       
   420 /*! \fn bool QContiguousCache::areIndexesValid() const
       
   421 
       
   422     Returns whether the indexes for items stored in the cache are valid.
       
   423     Indexes can become invalid if items are appended after the index position
       
   424     INT_MAX or prepended before the index position 0.  This is only expected
       
   425     to occur in very long lived circular buffer style usage of the
       
   426     contiguous cache.  Indexes can be made valid again by calling
       
   427     normalizeIndexs().
       
   428 
       
   429     \sa normalizeIndexes(), append(), prepend()
       
   430 */
       
   431 
       
   432 QT_END_NAMESPACE