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