File indexing completed on 2024-04-28 03:53:10

0001 /*
0002     This file is part of the KDE libraries
0003 
0004     SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org>
0005     SPDX-FileCopyrightText: 2002 Michael Matz <matz@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 //----------------------------------------------------------------------------
0010 //
0011 // KDE Memory Allocator
0012 
0013 #ifndef KZONEALLOCATOR_P_H
0014 #define KZONEALLOCATOR_P_H
0015 
0016 #include <cstddef> // size_t
0017 
0018 template<typename T>
0019 class QList;
0020 
0021 /**
0022  * \class KZoneAllocator kallocator.h <KZoneAllocator>
0023  *
0024  * Memory allocator for large groups of small objects.
0025  * This should be used for large groups of objects that are created and
0026  * destroyed together. When used carefully for this purpose it is faster
0027  * and more memory efficient than malloc. Additionally to a usual obstack
0028  * like allocator you can also free the objects individually. Because it
0029  * does no compaction it still is faster than malloc()/free(). Depending
0030  * on the exact usage pattern that might come at the expense of some
0031  * memory though.
0032  * @author Waldo Bastian <bastian@kde.org>, Michael Matz <matz@kde.org>
0033  */
0034 class KZoneAllocator
0035 {
0036 public:
0037     /**
0038      * Creates a KZoneAllocator object.
0039      * @param _blockSize Size in bytes of the blocks requested from malloc.
0040      */
0041     explicit KZoneAllocator(unsigned long _blockSize = 8 * 1024);
0042 
0043     /**
0044      * Destructs the ZoneAllocator and free all memory allocated by it.
0045      */
0046     ~KZoneAllocator();
0047 
0048     KZoneAllocator(const KZoneAllocator &) = delete;
0049     KZoneAllocator &operator=(const KZoneAllocator &) = delete;
0050 
0051     /**
0052      * Allocates a memory block.
0053      * @param _size Size in bytes of the memory block. Memory is aligned to
0054      * the size of a pointer.
0055      */
0056     void *allocate(size_t _size);
0057 
0058     /**
0059      * Gives back a block returned by allocate() to the zone
0060      * allocator, and possibly deallocates the block holding it (when it's
0061      * empty). The first deallocate() after many allocate() calls
0062      * (or the first at all) builds an internal data structure for speeding
0063      * up deallocation. The consistency of that structure is maintained
0064      * from then on (by allocate() and deallocate()) unless many
0065      * more objects are allocated without any intervening deallocation, in
0066      * which case it's thrown away and rebuilt at the next deallocate().
0067      *
0068      * The effect of this is, that such initial deallocate() calls take
0069      * more time then the normal calls, and that after this list is built, i.e.
0070      * generally if deallocate() is used at all, also allocate() is a
0071      * little bit slower. This means, that if you want to squeeze out the last
0072      * bit performance you would want to use KZoneAllocator as an obstack, i.e.
0073      * just use the functions allocate() and free_since(). All the
0074      * remaining memory is returned to the system if the zone allocator
0075      * is destroyed.
0076      * @param ptr Pointer as returned by allocate().
0077      */
0078     void deallocate(void *ptr);
0079 
0080     /**
0081      * Deallocate many objects at once.
0082      * free_since() deallocates all objects allocated after @p ptr,
0083      * @em including @p ptr itself.
0084      *
0085      * The intended use is something along the lines of:
0086      * \code
0087      * KZoneAllocator alloc(8192);
0088      * void *remember_me = alloc.allocate(0);
0089      * for (int i = 0; i < 1000; i++)
0090      *   do_something_with (alloc.allocate(12));
0091      * alloc.free_since (remember_me);
0092      * \endcode
0093      * Note, that we don't need to remember all the pointers to the 12-byte
0094      * objects for freeing them. The free_since() does deallocate them
0095      * all at once.
0096      * @param ptr Pointer as returned by allocate(). It acts like
0097      * a kind of mark of a certain position in the stack of all objects,
0098      * off which you can throw away everything above that mark.
0099      */
0100     void free_since(void *ptr);
0101 
0102 protected:
0103     /** A single chunk of memory from the heap. @internal */
0104     class MemBlock;
0105     /**< A list of chunks. @internal */
0106     typedef QList<MemBlock *> MemList;
0107     void addBlock(MemBlock *b);
0108     void delBlock(MemBlock *b);
0109     void insertHash(MemBlock *b);
0110     void initHash();
0111 
0112 private:
0113     class Private;
0114     Private *const d;
0115 };
0116 
0117 #endif