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 | |