| 1 | /* |
| 2 | This file is part of the KDE libraries |
| 3 | |
| 4 | SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org> |
| 5 | SPDX-FileCopyrightText: 2002 Michael Matz <matz@kde.org> |
| 6 | |
| 7 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 8 | */ |
| 9 | //---------------------------------------------------------------------------- |
| 10 | // |
| 11 | // KDE Memory Allocator |
| 12 | |
| 13 | #ifndef KZONEALLOCATOR_P_H |
| 14 | #define KZONEALLOCATOR_P_H |
| 15 | |
| 16 | #include <cstddef> // size_t |
| 17 | |
| 18 | template<typename T> |
| 19 | class QList; |
| 20 | |
| 21 | /*! |
| 22 | * Memory allocator for large groups of small objects. |
| 23 | * This should be used for large groups of objects that are created and |
| 24 | * destroyed together. When used carefully for this purpose it is faster |
| 25 | * and more memory efficient than malloc. Additionally to a usual obstack |
| 26 | * like allocator you can also free the objects individually. Because it |
| 27 | * does no compaction it still is faster than malloc()/free(). Depending |
| 28 | * on the exact usage pattern that might come at the expense of some |
| 29 | * memory though. |
| 30 | * |
| 31 | * \internal |
| 32 | */ |
| 33 | class KZoneAllocator |
| 34 | { |
| 35 | public: |
| 36 | /*! |
| 37 | * Creates a KZoneAllocator object. |
| 38 | * \a _blockSize Size in bytes of the blocks requested from malloc. |
| 39 | */ |
| 40 | explicit KZoneAllocator(unsigned long _blockSize = 8 * 1024); |
| 41 | |
| 42 | /*! |
| 43 | * Destructs the ZoneAllocator and free all memory allocated by it. |
| 44 | */ |
| 45 | ~KZoneAllocator(); |
| 46 | |
| 47 | KZoneAllocator(const KZoneAllocator &) = delete; |
| 48 | KZoneAllocator &operator=(const KZoneAllocator &) = delete; |
| 49 | |
| 50 | /*! |
| 51 | * Allocates a memory block. |
| 52 | * \a _size Size in bytes of the memory block. Memory is aligned to |
| 53 | * the size of a pointer. |
| 54 | */ |
| 55 | void *allocate(size_t _size); |
| 56 | |
| 57 | /*! |
| 58 | * Gives back a block returned by allocate() to the zone |
| 59 | * allocator, and possibly deallocates the block holding it (when it's |
| 60 | * empty). The first deallocate() after many allocate() calls |
| 61 | * (or the first at all) builds an internal data structure for speeding |
| 62 | * up deallocation. The consistency of that structure is maintained |
| 63 | * from then on (by allocate() and deallocate()) unless many |
| 64 | * more objects are allocated without any intervening deallocation, in |
| 65 | * which case it's thrown away and rebuilt at the next deallocate(). |
| 66 | * |
| 67 | * The effect of this is, that such initial deallocate() calls take |
| 68 | * more time then the normal calls, and that after this list is built, i.e. |
| 69 | * generally if deallocate() is used at all, also allocate() is a |
| 70 | * little bit slower. This means, that if you want to squeeze out the last |
| 71 | * bit performance you would want to use KZoneAllocator as an obstack, i.e. |
| 72 | * just use the functions allocate() and free_since(). All the |
| 73 | * remaining memory is returned to the system if the zone allocator |
| 74 | * is destroyed. |
| 75 | * \a ptr Pointer as returned by allocate(). |
| 76 | */ |
| 77 | void deallocate(void *ptr); |
| 78 | |
| 79 | /*! |
| 80 | * Deallocate many objects at once. |
| 81 | * free_since() deallocates all objects allocated after \a ptr, |
| 82 | * \e including \a ptr itself. |
| 83 | * |
| 84 | * The intended use is something along the lines of: |
| 85 | * \code |
| 86 | * KZoneAllocator alloc(8192); |
| 87 | * void *remember_me = alloc.allocate(0); |
| 88 | * for (int i = 0; i < 1000; i++) |
| 89 | * do_something_with (alloc.allocate(12)); |
| 90 | * alloc.free_since (remember_me); |
| 91 | * \endcode |
| 92 | * Note, that we don't need to remember all the pointers to the 12-byte |
| 93 | * objects for freeing them. The free_since() does deallocate them |
| 94 | * all at once. |
| 95 | * \a ptr Pointer as returned by allocate(). It acts like |
| 96 | * a kind of mark of a certain position in the stack of all objects, |
| 97 | * off which you can throw away everything above that mark. |
| 98 | */ |
| 99 | void free_since(void *ptr); |
| 100 | |
| 101 | protected: |
| 102 | /*! A single chunk of memory from the heap. \internal */ |
| 103 | class MemBlock; |
| 104 | /*!< A list of chunks. \internal */ |
| 105 | typedef QList<MemBlock *> MemList; |
| 106 | void addBlock(MemBlock *b); |
| 107 | void delBlock(MemBlock *b); |
| 108 | void insertHash(MemBlock *b); |
| 109 | void initHash(); |
| 110 | |
| 111 | private: |
| 112 | class Private; |
| 113 | Private *const d; |
| 114 | }; |
| 115 | |
| 116 | #endif |
| 117 | |