1 /**
2  * @file memoryzone.h
3  * Memory zone.
4  *
5  * @par Build Options
6  * Define the macro @c LIBDENG_FAKE_MEMORY_ZONE to force all memory blocks to be
7  * allocated from the real heap. Useful when debugging memory-related problems.
8  *
9  * @authors Copyright © 1999-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
10  * @authors Copyright © 2006-2013 Daniel Swanson <danij@dengine.net>
11  * @authors Copyright © 1993-1996 by id Software, Inc.
12  *
13  * @par License
14  * GPL: http://www.gnu.org/licenses/gpl.html
15  *
16  * <small>This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by the
18  * Free Software Foundation; either version 2 of the License, or (at your
19  * option) any later version. This program is distributed in the hope that it
20  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
21  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
22  * Public License for more details. You should have received a copy of the GNU
23  * General Public License along with this program; if not, write to the Free
24  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA</small>
26  */
27 
28 #ifndef LIBDENG_MEMORY_ZONE_H
29 #define LIBDENG_MEMORY_ZONE_H
30 
31 /**
32  * @defgroup memzone Memory Zone
33  * @ingroup legacy
34  */
35 
36 #include <de/liblegacy.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 /**
43  * @defgroup purgeLevels Purge Levels
44  * @ingroup memzone
45  */
46 ///@{
47 #define PU_APPSTATIC         1 ///< Static entire execution time.
48 
49 #define PU_GAMESTATIC       40 ///< Static until the game plugin which allocated it is unloaded.
50 #define PU_MAP              50 ///< Static until map exited (may still be freed during the map, though).
51 #define PU_MAPSTATIC        52 ///< Not freed until map exited.
52 
53 #define PU_PURGELEVEL       100 ///< Tags >= 100 are purgable whenever needed.
54 ///@}
55 
56 #define LIBDENG_ZONEID      0x1d4a11
57 
58 /// @addtogroup memzone
59 ///@{
60 
61 /**
62  * Determines if the memory zone is available for allocations.
63  */
64 DENG_PUBLIC dd_bool Z_IsInited(void);
65 
66 /**
67  * You can pass a NULL user if the tag is < PU_PURGELEVEL.
68  */
69 DENG_PUBLIC void *Z_Malloc(size_t size, int tag, void *ptr);
70 
71 /**
72  * Memory allocation utility: malloc and clear.
73  */
74 DENG_PUBLIC void *Z_Calloc(size_t size, int tag, void *user);
75 
76 /**
77  * Only resizes blocks with no user. If a block with a user is
78  * reallocated, the user will lose its current block and be set to
79  * NULL. Does not change the tag of existing blocks.
80  */
81 DENG_PUBLIC void *Z_Realloc(void *ptr, size_t n, int mallocTag);
82 
83 /**
84  * Realloc and set possible new memory to zero.
85  */
86 DENG_PUBLIC void *Z_Recalloc(void *ptr, size_t n, int callocTag);
87 
88 /**
89  * Free memory that was allocated with Z_Malloc.
90  */
91 DENG_PUBLIC void Z_Free(void *ptr);
92 
93 /**
94  * Free memory blocks in all volumes with a tag in the specified range.
95  */
96 DENG_PUBLIC void Z_FreeTags(int lowTag, int highTag);
97 
98 /**
99  * Check all zone volumes for consistency.
100  */
101 DENG_PUBLIC void Z_CheckHeap(void);
102 
103 /**
104  * Change the tag of a memory block.
105  */
106 DENG_PUBLIC void Z_ChangeTag2(void *ptr, int tag);
107 
108 /**
109  * Change the user of a memory block.
110  */
111 DENG_PUBLIC void Z_ChangeUser(void *ptr, void *newUser);
112 
113 DENG_PUBLIC uint32_t Z_GetId(void *ptr);
114 
115 /**
116  * Get the user of a memory block.
117  */
118 DENG_PUBLIC void *Z_GetUser(void *ptr);
119 
120 DENG_PUBLIC int Z_GetTag(void *ptr);
121 
122 /**
123  * Checks if @a ptr points to memory inside the memory zone.
124  * @param ptr  Pointer.
125  * @return @c true, if @a ptr points to a valid allocated memory block
126  * inside the zone.
127  */
128 DENG_PUBLIC dd_bool Z_Contains(void *ptr);
129 
130 /**
131  * Copies @a text into a buffer allocated from the zone.
132  * Similar to strdup().
133  *
134  * @param text  Null-terminated C string.
135  *
136  * @return  Copy of the string (in the zone).
137  */
138 DENG_PUBLIC char *Z_StrDup(char const *text);
139 
140 DENG_PUBLIC void *Z_MemDup(void const *ptr, size_t size);
141 
142 struct zblockset_s;
143 typedef struct zblockset_s zblockset_t;
144 
145 /**
146  * Creates a new block memory allocator in the Zone.
147  *
148  * @param sizeOfElement  Required size of each element.
149  * @param batchSize  Number of elements in each block of the set.
150  * @param tag  Purge level for the allocation.
151  *
152  * @return  Ptr to the newly created blockset.
153  */
154 DENG_PUBLIC zblockset_t *ZBlockSet_New(size_t sizeOfElement, uint32_t batchSize, int tag);
155 
156 /**
157  * Destroy the entire blockset.
158  * All memory allocated is released for all elements in all blocks and any
159  * used for the blockset itself.
160  *
161  * @param set  The blockset to be freed.
162  */
163 DENG_PUBLIC void ZBlockSet_Delete(zblockset_t *set);
164 
165 /**
166  * Return a ptr to the next unused element in the blockset.
167  *
168  * @param set  The blockset to return the next element from.
169  *
170  * @return  Ptr to the next unused element in the blockset.
171  */
172 DENG_PUBLIC void *ZBlockSet_Allocate(zblockset_t *set);
173 
174 #define Z_ChangeTag(p,t) { \
175     if (Z_GetId(p) != LIBDENG_ZONEID) \
176         Con_Error("Z_ChangeTag at " __FILE__ ":%i", __LINE__); \
177     Z_ChangeTag2(p, t); }
178 
179 DENG_PUBLIC void Z_PrintStatus(void);
180 
181 /**
182  * Puts a region of memory allocated with Z_Malloc() or malloc() up for garbage
183  * collection.
184  *
185  * @param ptr  Allocated memory (not previously trashed).
186  */
187 DENG_PUBLIC void Garbage_Trash(void *ptr);
188 
189 ///@}
190 
191 #ifdef DENG_DEBUG
192 struct memzone_private_s;
193 typedef struct memzone_private_s MemoryZonePrivateData;
194 DENG_PUBLIC void Z_GetPrivateData(MemoryZonePrivateData *pd);
195 #endif
196 
197 #ifdef __cplusplus
198 } // extern "C"
199 #endif
200 
201 #endif // LIBDENG_MEMORY_ZONE_H
202