qtmobility/src/publishsubscribe/qmallocpool.cpp
changeset 1 2b40d63a9c3d
child 11 06b8e2af4411
equal deleted inserted replaced
0:cfcbf08528c4 1:2b40d63a9c3d
       
     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 Qt Mobility Components.
       
     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 "qmallocpool_p.h"
       
    43 #include <qglobal.h>
       
    44 
       
    45 struct malloc_state;
       
    46 
       
    47 QTM_BEGIN_NAMESPACE
       
    48 
       
    49 static void* qmallocpool_sbrk(intptr_t increment);
       
    50 
       
    51 #define USE_DL_PREFIX
       
    52 #define MORECORE QTM_NAMESPACE::qmallocpool_sbrk
       
    53 #define HAVE_MMAP 0
       
    54 #define __STD_C 1
       
    55 #ifdef Q_OS_WINCE
       
    56 #define WIN32
       
    57 #define LACKS_ERRNO_H
       
    58 #define MALLOC_FAILURE_ACTION
       
    59 #endif
       
    60 
       
    61 static QMallocPoolPrivate * qmallocpool_instance = 0;
       
    62 static struct malloc_state * qmallocpool_state(QMallocPoolPrivate *);
       
    63 #define get_malloc_state() (QTM_NAMESPACE::qmallocpool_state(QTM_NAMESPACE::qmallocpool_instance))
       
    64 
       
    65 QTM_END_NAMESPACE
       
    66 
       
    67 #include "dlmalloc.c"
       
    68 
       
    69 QTM_BEGIN_NAMESPACE
       
    70 
       
    71 class QMallocPoolPrivate
       
    72 {
       
    73 public:
       
    74     QMallocPoolPrivate(void * _pool, unsigned int _poolLen,
       
    75                        QMallocPool::PoolType type, const QString &_name)
       
    76         : name(_name), pool((char *)_pool), poolLength(_poolLen), poolPtr(0)
       
    77     {
       
    78         Q_ASSERT(pool);
       
    79         Q_ASSERT(poolLength > 0);
       
    80 
       
    81         if(QMallocPool::Owned == type) {
       
    82             qMemSet(&owned_mstate, 0, sizeof(struct malloc_state));
       
    83             mstate = &owned_mstate;
       
    84         } else if(QMallocPool::NewShared == type) {
       
    85             Q_ASSERT(poolLength >= sizeof(struct malloc_state));
       
    86             qMemSet(pool, 0, sizeof(struct malloc_state));
       
    87             mstate = (struct malloc_state *)pool;
       
    88             pool += sizeof(struct malloc_state);
       
    89             poolLength -= sizeof(struct malloc_state);
       
    90         } else if(QMallocPool::Shared == type) {
       
    91             Q_ASSERT(poolLength >= sizeof(struct malloc_state));
       
    92             mstate = (struct malloc_state *)pool;
       
    93             pool += sizeof(struct malloc_state);
       
    94             poolLength -= sizeof(struct malloc_state);
       
    95         }
       
    96     }
       
    97 
       
    98     QString name;
       
    99     char * pool;
       
   100     unsigned int poolLength;
       
   101     unsigned int poolPtr;
       
   102     struct malloc_state *mstate;
       
   103     struct malloc_state owned_mstate;
       
   104 };
       
   105 
       
   106 static struct malloc_state * qmallocpool_state(QMallocPoolPrivate *d)
       
   107 {
       
   108     Q_ASSERT(d);
       
   109     return d->mstate;
       
   110 }
       
   111 
       
   112 static void* qmallocpool_sbrk(intptr_t increment)
       
   113 {
       
   114     Q_ASSERT(qmallocpool_instance);
       
   115     QMallocPoolPrivate * const d = qmallocpool_instance;
       
   116 
       
   117     if(increment > 0) {
       
   118         if((unsigned)increment > d->poolLength ||
       
   119            (d->poolLength - increment) < d->poolPtr)
       
   120             // Failure
       
   121             return (void *)MORECORE_FAILURE;
       
   122 
       
   123         void * rv = (void *)(d->pool + d->poolPtr);
       
   124         d->poolPtr += increment;
       
   125         return rv;
       
   126 
       
   127     } else /* increment <= 0 */ {
       
   128         Q_ASSERT(d->poolPtr >= (unsigned)(-1 * increment));
       
   129         d->poolPtr += increment;
       
   130         return (void *)(d->pool + d->poolPtr);
       
   131     }
       
   132 }
       
   133 
       
   134 struct QMallocPtr
       
   135 {
       
   136     QMallocPtr(QMallocPoolPrivate * d)
       
   137     {
       
   138         Q_ASSERT(!qmallocpool_instance);
       
   139         qmallocpool_instance = d;
       
   140     }
       
   141     ~QMallocPtr()
       
   142     {
       
   143         Q_ASSERT(qmallocpool_instance);
       
   144         qmallocpool_instance = 0;
       
   145     }
       
   146 };
       
   147 
       
   148 /*!
       
   149   \class QMallocPool
       
   150   \internal
       
   151   \ingroup publishsubscribe
       
   152 
       
   153   \brief The QMallocPool class allows management of allocations within a
       
   154   designated memory region.
       
   155 
       
   156   QMallocPool provides heap management capabilities into a fixed region of
       
   157   memory.  Primarily this is useful for managing allocations in a shared
       
   158   memory region, but could be used in other scenarios.
       
   159 
       
   160   The QMallocPool class provides equivalents for most standard memory management
       
   161   functions, such as \c {malloc}, \c {calloc}, \c {realloc} and \c {free}.
       
   162   However, unlike these standard functions which acquire their memory from the
       
   163   system kernel, QMallocPool operators on a region of memory provided to it
       
   164   during construction.
       
   165 
       
   166   QMallocPool is based on dlmalloc, a public domain malloc implementation
       
   167   written by Doug Lea.  dlmalloc is used as the default allocator in many
       
   168   projects, including several versions of Linux libc.
       
   169 
       
   170   QMallocPool is not thread safe.
       
   171 */
       
   172 
       
   173 /*!
       
   174   \enum QMallocPool::PoolType
       
   175 
       
   176   Controls the type of pool to be created.  In order to manage memory, a small
       
   177   amount of book keeping information is maintained.  While this information is
       
   178   not required for reading from the managed pool, it is required for
       
   179   allocations.  The PoolType controls where this bookkeeping data is stored.
       
   180 
       
   181   \value Owned
       
   182   The bookkeeping data is maintained in the QMallocPool instance.  Allocation to
       
   183   the pool is only possible via this instance.
       
   184   \value NewShared
       
   185   The bookkeeping data is maintained in the managed region itself.  This allows
       
   186   multiple QMallocPool instances, possibly in separate processes, to allocate
       
   187   from the pool.
       
   188 
       
   189   The NewShared PoolType also initializes this bookkeeping data to its default
       
   190   state.  Thus, while the bookkeeping data is shared, only one of the sharing
       
   191   instances should use a NewShared type.  All other instances should use the
       
   192   Shared pool type.
       
   193 
       
   194   The malloc pool bookkeeping data contains absolute pointers.  As such, if
       
   195   multiple processes intend to allocate into the malloc pool, is is essential 
       
   196   that they map the memory region to the same virtual address location.
       
   197   \value Shared
       
   198   The bookkeeping data is stored in the managed region, and has previously been
       
   199   initialized by another QMallocPool instance constructed using the NewShared
       
   200   pool type.
       
   201 
       
   202   The malloc pool bookkeeping data contains absolute pointers.  As such, if
       
   203   multiple processes intend to allocate into the malloc pool, is is essential 
       
   204   that they map the memory region to the same virtual address location.
       
   205   */
       
   206 
       
   207 /*!
       
   208   Creates an invalid QMallocPool.
       
   209   */
       
   210 QMallocPool::QMallocPool()
       
   211 : d(0)
       
   212 {
       
   213 }
       
   214 
       
   215 /*!
       
   216   Creates a QMallocPool on the memory region \a poolBase of length
       
   217   \a poolLength.  The pool will be constructed with the passed \a type and
       
   218   \a name. The \a name is used for diagnostics purposes only.
       
   219   */
       
   220 QMallocPool::QMallocPool(void * poolBase, unsigned int poolLength,
       
   221                          PoolType type, const QString& name)
       
   222 : d(0)
       
   223 {
       
   224     if((type == NewShared || Shared == type) &&
       
   225             poolLength < sizeof(struct malloc_state))
       
   226         return;
       
   227 
       
   228     d = new QMallocPoolPrivate(poolBase, poolLength, type, name);
       
   229 }
       
   230 
       
   231 /*!
       
   232   Destroys the malloc pool.
       
   233   */
       
   234 QMallocPool::~QMallocPool()
       
   235 {
       
   236     if(d)
       
   237         delete d;
       
   238     d = 0;
       
   239 }
       
   240 
       
   241 /*!
       
   242   Returns the allocated size of \a mem, assuming \a mem was previously returned
       
   243   by malloc(), calloc() or realloc().
       
   244   */
       
   245 size_t QMallocPool::size_of(void *mem)
       
   246 {
       
   247     return chunksize(mem2chunk(mem)) - sizeof(mchunkptr);
       
   248 }
       
   249 
       
   250 /*!
       
   251   Allocates memory for an array of \a nmemb elements of \a size each and returns
       
   252   a pointer to the allocated memory.  The memory is  set to zero.  Returns 0 if
       
   253   the memory could not be allocated.
       
   254   */
       
   255 void *QMallocPool::calloc(size_t nmemb, size_t size)
       
   256 {
       
   257     Q_ASSERT(d && "Cannot operate on a null malloc pool");
       
   258     QMallocPtr p(d);
       
   259     return dlcalloc(nmemb, size);
       
   260 }
       
   261 
       
   262 /*!
       
   263   Allocates \a size  bytes and returns a pointer to the allocated memory.  The
       
   264   memory is not cleared.  Returns 0 if the memory could not be allocated.
       
   265  */
       
   266 void *QMallocPool::malloc(size_t size)
       
   267 {
       
   268     Q_ASSERT(d && "Cannot operate on a null malloc pool");
       
   269     QMallocPtr p(d);
       
   270     return dlmalloc(size);
       
   271 }
       
   272 
       
   273 /*!
       
   274   Frees the memory space pointed to by \a ptr, which must  have  been returned
       
   275   by a previous call to malloc(), calloc() or realloc().  Otherwise, or  if
       
   276   \c {free(ptr)}  has  already  been  called  before,  undefined behavior
       
   277   occurs.  If \a ptr is 0, no operation is performed.
       
   278  */
       
   279 void QMallocPool::free(void *ptr)
       
   280 {
       
   281     Q_ASSERT(d && "Cannot operate on a null malloc pool");
       
   282     QMallocPtr p(d);
       
   283     dlfree(ptr);
       
   284 }
       
   285 
       
   286 /*!
       
   287   Changes the size of the memory block pointed to by \a ptr to \a size bytes.
       
   288   The contents will be unchanged to the minimum of the old and new sizes; newly
       
   289   allocated memory will be uninitialized.  If \a ptr is 0, the call is
       
   290   equivalent to malloc(size); if size is equal to zero, the  call is equivalent
       
   291   to free(ptr).  Unless ptr is 0, it must have been returned by an earlier call
       
   292   to malloc(),  calloc()  or  realloc().  If the area pointed to was moved, a
       
   293   free(ptr) is done.
       
   294  */
       
   295 void *QMallocPool::realloc(void *ptr, size_t size)
       
   296 {
       
   297     Q_ASSERT(d && "Cannot operate on a null malloc pool");
       
   298     QMallocPtr p(d);
       
   299     return dlrealloc(ptr, size);
       
   300 }
       
   301 
       
   302 /*!
       
   303   Returns true if this is a valid malloc pool.  Invalid malloc pools cannot be
       
   304   allocated from.
       
   305  */
       
   306 bool QMallocPool::isValid() const
       
   307 {
       
   308     return d;
       
   309 }
       
   310 
       
   311 /*!
       
   312   Returns a MemoryStats structure containing information about the memory use
       
   313   of this pool.
       
   314  */
       
   315 QMallocPool::MemoryStats QMallocPool::memoryStatistics() const
       
   316 {
       
   317     Q_ASSERT(d && "Cannot operate on a null malloc pool");
       
   318     QMallocPtr p(d);
       
   319 
       
   320     struct mallinfo info = dlmallinfo();
       
   321 
       
   322     MemoryStats rv = { d->poolLength,
       
   323                        (unsigned long)info.usmblks,
       
   324                        (unsigned long)info.arena,
       
   325                        (unsigned long)info.uordblks,
       
   326                        (unsigned long)info.keepcost };
       
   327     return rv;
       
   328 }
       
   329 
       
   330 QTM_END_NAMESPACE