/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QRECYCLEPOOL_P_H #define QRECYCLEPOOL_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // QT_BEGIN_NAMESPACE #define QRECYCLEPOOLCOOKIE 0x33218ADF template class QRecyclePoolPrivate { public: QRecyclePoolPrivate() : recyclePoolHold(true), outstandingItems(0), cookie(QRECYCLEPOOLCOOKIE), currentPage(0), nextAllocated(0) { } bool recyclePoolHold; int outstandingItems; quint32 cookie; struct PoolType : public T { union { QRecyclePoolPrivate *pool; PoolType *nextAllocated; }; }; struct Page { Page *nextPage; unsigned int free; union { char array[Step * sizeof(PoolType)]; qint64 q_for_alignment_1; double q_for_alignment_2; }; }; Page *currentPage; PoolType *nextAllocated; inline T *allocate(); static inline void dispose(T *); inline void releaseIfPossible(); }; template class QRecyclePool { public: inline QRecyclePool(); inline ~QRecyclePool(); inline T *New(); template inline T *New(const T1 &); template inline T *New(T1 &); static inline void Delete(T *); private: QRecyclePoolPrivate *d; }; template QRecyclePool::QRecyclePool() : d(new QRecyclePoolPrivate()) { } template QRecyclePool::~QRecyclePool() { d->recyclePoolHold = false; d->releaseIfPossible(); } template T *QRecyclePool::New() { T *rv = d->allocate(); new (rv) T; return rv; } template template T *QRecyclePool::New(const T1 &a) { T *rv = d->allocate(); new (rv) T(a); return rv; } template template T *QRecyclePool::New(T1 &a) { T *rv = d->allocate(); new (rv) T(a); return rv; } template void QRecyclePool::Delete(T *t) { t->~T(); QRecyclePoolPrivate::dispose(t); } template void QRecyclePoolPrivate::releaseIfPossible() { if (recyclePoolHold || outstandingItems) return; Page *p = currentPage; while (p) { Page *n = p->nextPage; free(p); p = n; } delete this; } template T *QRecyclePoolPrivate::allocate() { PoolType *rv = 0; if (nextAllocated) { rv = nextAllocated; nextAllocated = rv->nextAllocated; } else if (currentPage && currentPage->free) { rv = (PoolType *)(currentPage->array + (Step - currentPage->free) * sizeof(PoolType)); currentPage->free--; } else { Page *p = (Page *)malloc(sizeof(Page)); p->nextPage = currentPage; p->free = Step; currentPage = p; rv = (PoolType *)currentPage->array; currentPage->free--; } rv->pool = this; ++outstandingItems; return rv; } template void QRecyclePoolPrivate::dispose(T *t) { PoolType *pt = static_cast(t); Q_ASSERT(pt->pool && pt->pool->cookie == QRECYCLEPOOLCOOKIE); QRecyclePoolPrivate *This = pt->pool; pt->nextAllocated = This->nextAllocated; This->nextAllocated = pt; --This->outstandingItems; This->releaseIfPossible(); } QT_END_NAMESPACE #endif // QRECYCLEPOOL_P_H