/**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the QtDeclarative module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** 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, Nokia gives you certain additional ** rights. These rights are described in the Nokia 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. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QDECLARATIVEPOOL_P_H #define QDECLARATIVEPOOL_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. // #include #include #include QT_BEGIN_NAMESPACE // Exported for QtQuick1 class Q_DECLARATIVE_EXPORT QDeclarativePool { public: // The class has a destructor that needs to be called class Class { public: inline QDeclarativePool *pool() const; private: void *operator new(size_t); void *operator new(size_t, void *m) { return m; } friend class QDeclarativePool; QDeclarativePool *_pool; Class *_next; void (*_destroy)(Class *); }; // The class is plain old data and no destructor needs to // be called class POD { public: inline QDeclarativePool *pool() const; private: void *operator new(size_t); void *operator new(size_t, void *m) { return m; } friend class QDeclarativePool; QDeclarativePool *_pool; }; inline QDeclarativePool(); inline ~QDeclarativePool(); void clear(); template inline T *New(); template inline T *NewRaw(); template inline T *NewRawArray(int length); inline QString *NewString(const QString &); inline QByteArray *NewByteArray(const QByteArray &); inline QUrl *NewUrl(const QUrl &); template struct List { List() : m_length(0), m_data(0) {} List(const List &o) : m_length(o.m_length), m_data(o.m_data) {} List &operator=(const List &o) { m_length = o.m_length; m_data = o.m_data; return *this; } int count() const { return m_length; } int length() const { return m_length; } const T &at(int index) const { Q_ASSERT(index < m_length); return m_data[index]; }; T &operator[](int index) { Q_ASSERT(index < m_length); return m_data[index]; }; private: friend class QDeclarativePool; List(T *d, int l) : m_length(l), m_data(d) {} int m_length; T *m_data; }; template inline List NewRawList(int length); private: struct StringClass : public QString, public Class { }; struct ByteArrayClass : public QByteArray, public Class { }; struct UrlClass : public QUrl, public Class { }; inline void *allocate(int size); void newpage(); template inline void initialize(POD *); template inline void initialize(Class *); template static void destroy(Class *c); struct Page { struct Header { Page *next; char *free; } header; static const int pageSize = 4 * 4096 - sizeof(Header); char memory[pageSize]; }; Page *_page; Class *_classList; }; QDeclarativePool::QDeclarativePool() : _page(0), _classList(0) { } QDeclarativePool::~QDeclarativePool() { clear(); } template T *QDeclarativePool::New() { T *rv = new (allocate(sizeof(T))) T; initialize(rv); rv->_pool = this; return rv; } template T *QDeclarativePool::NewRaw() { return (T*)allocate(sizeof(T)); } template T *QDeclarativePool::NewRawArray(int length) { return (T*)allocate(length * sizeof(T)); } template QDeclarativePool::List QDeclarativePool::NewRawList(int length) { return List(NewRawArray(length), length); } QString *QDeclarativePool::NewString(const QString &s) { QString *rv = New(); *rv = s; return rv; } QByteArray *QDeclarativePool::NewByteArray(const QByteArray &s) { QByteArray *rv = New(); *rv = s; return rv; } QUrl *QDeclarativePool::NewUrl(const QUrl &s) { QUrl *rv = New(); *rv = s; return rv; } void *QDeclarativePool::allocate(int size) { if (!_page || (_page->header.free + size) > (_page->memory + Page::pageSize)) newpage(); void *rv = _page->header.free; _page->header.free += size + ((8 - size) & 7); // ensure 8 byte alignment; return rv; } template void QDeclarativePool::initialize(QDeclarativePool::POD *) { } template void QDeclarativePool::initialize(QDeclarativePool::Class *c) { c->_next = _classList; c->_destroy = &destroy; _classList = c; } template void QDeclarativePool::destroy(Class *c) { static_cast(c)->~T(); } QDeclarativePool *QDeclarativePool::Class::pool() const { return _pool; } QDeclarativePool *QDeclarativePool::POD::pool() const { return _pool; } QT_END_NAMESPACE #endif // QDECLARATIVEPOOL_P_H