1 | /*****************************************************************************\ |
---|
2 | * Copyright (c) Athena Dev Teams - Licensed under GNU GPL * |
---|
3 | * For more information, see LICENCE in the main folder * |
---|
4 | * * |
---|
5 | * <H1>Entry Reusage System</H1> * |
---|
6 | * * |
---|
7 | * There are several root entry managers, each with a different entry size. * |
---|
8 | * Each manager will keep track of how many instances have been 'created'. * |
---|
9 | * They will only automatically destroy themselves after the last instance * |
---|
10 | * is destroyed. * |
---|
11 | * * |
---|
12 | * Entries can be allocated from the managers. * |
---|
13 | * If it has reusable entries (freed entry), it uses one. * |
---|
14 | * So no assumption should be made about the data of the entry. * |
---|
15 | * Entries should be freed in the manager they where allocated from. * |
---|
16 | * Failure to do so can lead to unexpected behaviours. * |
---|
17 | * * |
---|
18 | * <H2>Advantages:</H2> * |
---|
19 | * - The same manager is used for entries of the same size. * |
---|
20 | * So entries freed in one instance of the manager can be used by other * |
---|
21 | * instances of the manager. * |
---|
22 | * - Much less memory allocation/deallocation - program will be faster. * |
---|
23 | * - Avoids memory fragmentaion - program will run better for longer. * |
---|
24 | * * |
---|
25 | * <H2>Disavantages:</H2> * |
---|
26 | * - Unused entries are almost inevitable - memory being wasted. * |
---|
27 | * - A manager will only auto-destroy when all of its instances are * |
---|
28 | * destroyed so memory will usually only be recovered near the end. * |
---|
29 | * - Always wastes space for entries smaller than a pointer. * |
---|
30 | * * |
---|
31 | * WARNING: The system is not thread-safe at the moment. * |
---|
32 | * * |
---|
33 | * HISTORY: * |
---|
34 | * 0.1 - Initial version * |
---|
35 | * * |
---|
36 | * @version 0.1 - Initial version * |
---|
37 | * @author Flavio @ Amazon Project * |
---|
38 | * @encoding US-ASCII * |
---|
39 | \*****************************************************************************/ |
---|
40 | #ifndef _ERS_H_ |
---|
41 | #define _ERS_H_ |
---|
42 | |
---|
43 | #ifndef _CBASETYPES_H_ |
---|
44 | #include "../common/cbasetypes.h" |
---|
45 | #endif |
---|
46 | |
---|
47 | /*****************************************************************************\ |
---|
48 | * (1) All public parts of the Entry Reusage System. * |
---|
49 | * DISABLE_ERS - Define to disable this system. * |
---|
50 | * ERS_ALIGNED - Alignment of the entries in the blocks. * |
---|
51 | * ERS - Entry manager. * |
---|
52 | * ers_new - Allocate an instance of an entry manager. * |
---|
53 | * ers_report - Print a report about the current state. * |
---|
54 | * ers_force_destroy_all - Force the destruction of all the managers. * |
---|
55 | \*****************************************************************************/ |
---|
56 | |
---|
57 | /** |
---|
58 | * Define this to disable the Entry Reusage System. |
---|
59 | * All code except the typedef of ERInterface will be disabled. |
---|
60 | * To allow a smooth transition, |
---|
61 | */ |
---|
62 | //#define DISABLE_ERS |
---|
63 | |
---|
64 | /** |
---|
65 | * Entries are aligned to ERS_ALIGNED bytes in the blocks of entries. |
---|
66 | * By default it aligns to one byte, using the "natural order" of the entries. |
---|
67 | * This should NEVER be set to zero or less. |
---|
68 | * If greater than one, some memory can be wasted. This should never be needed |
---|
69 | * but is here just in case some aligment issues arise. |
---|
70 | */ |
---|
71 | #ifndef ERS_ALIGNED |
---|
72 | # define ERS_ALIGNED 1 |
---|
73 | #endif /* not ERS_ALIGN_ENTRY */ |
---|
74 | |
---|
75 | /** |
---|
76 | * Public interface of the entry manager. |
---|
77 | * @param alloc Allocate an entry from this manager |
---|
78 | * @param free Free an entry allocated from this manager |
---|
79 | * @param entry_size Return the size of the entries of this manager |
---|
80 | * @param destroy Destroy this instance of the manager |
---|
81 | */ |
---|
82 | typedef struct eri { |
---|
83 | |
---|
84 | /** |
---|
85 | * Allocate an entry from this entry manager. |
---|
86 | * If there are reusable entries available, it reuses one instead. |
---|
87 | * @param self Interface of the entry manager |
---|
88 | * @return An entry |
---|
89 | */ |
---|
90 | void *(*alloc)(struct eri *self); |
---|
91 | |
---|
92 | /** |
---|
93 | * Free an entry allocated from this manager. |
---|
94 | * WARNING: Does not check if the entry was allocated by this manager. |
---|
95 | * Freeing such an entry can lead to unexpected behaviour. |
---|
96 | * @param self Interface of the entry manager |
---|
97 | * @param entry Entry to be freed |
---|
98 | */ |
---|
99 | void (*free)(struct eri *self, void *entry); |
---|
100 | |
---|
101 | /** |
---|
102 | * Return the size of the entries allocated from this manager. |
---|
103 | * @param self Interface of the entry manager |
---|
104 | * @return Size of the entries of this manager in bytes |
---|
105 | */ |
---|
106 | size_t (*entry_size)(struct eri *self); |
---|
107 | |
---|
108 | /** |
---|
109 | * Destroy this instance of the manager. |
---|
110 | * The manager is actually only destroyed when all the instances are destroyed. |
---|
111 | * When destroying the manager a warning is shown if the manager has |
---|
112 | * missing/extra entries. |
---|
113 | * @param self Interface of the entry manager |
---|
114 | */ |
---|
115 | void (*destroy)(struct eri *self); |
---|
116 | |
---|
117 | } *ERS; |
---|
118 | |
---|
119 | #ifdef DISABLE_ERS |
---|
120 | // Use memory manager to allocate/free and disable other interface functions |
---|
121 | # define ers_alloc(obj,type) (type *)aMalloc(sizeof(type)) |
---|
122 | # define ers_free(obj,entry) aFree(entry) |
---|
123 | # define ers_entry_size(obj) (size_t)0 |
---|
124 | # define ers_destroy(obj) |
---|
125 | // Disable the public functions |
---|
126 | # define ers_new(size) NULL |
---|
127 | # define ers_report() |
---|
128 | # define ers_force_destroy_all() |
---|
129 | #else /* not DISABLE_ERS */ |
---|
130 | // These defines should be used to allow the code to keep working whenever |
---|
131 | // the system is disabled |
---|
132 | # define ers_alloc(obj,type) (type *)(obj)->alloc(obj) |
---|
133 | # define ers_free(obj,entry) (obj)->free((obj),(entry)) |
---|
134 | # define ers_entry_size(obj) (obj)->entry_size(obj) |
---|
135 | # define ers_destroy(obj) (obj)->destroy(obj) |
---|
136 | |
---|
137 | /** |
---|
138 | * Get a new instance of the manager that handles the specified entry size. |
---|
139 | * Size has to greater than 0. |
---|
140 | * If the specified size is smaller than a pointer, the size of a pointer is |
---|
141 | * used instead. |
---|
142 | * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of |
---|
143 | * ERS_ALIGNED that is greater or equal to size is what's actually used. |
---|
144 | * @param The requested size of the entry in bytes |
---|
145 | * @return Interface of the object |
---|
146 | */ |
---|
147 | ERS ers_new(uint32 size); |
---|
148 | |
---|
149 | /** |
---|
150 | * Print a report about the current state of the Entry Reusage System. |
---|
151 | * Shows information about the global system and each entry manager. |
---|
152 | * The number of entries are checked and a warning is shown if extra reusable |
---|
153 | * entries are found. |
---|
154 | * The extra entries are included in the count of reusable entries. |
---|
155 | */ |
---|
156 | void ers_report(void); |
---|
157 | |
---|
158 | /** |
---|
159 | * Forcibly destroy all the entry managers, checking for nothing. |
---|
160 | * The system is left as if no instances or entries had ever been allocated. |
---|
161 | * All previous entries and instances of the managers become invalid. |
---|
162 | * The use of this is NOT recommended. |
---|
163 | * It should only be used in extreme situations to make shure all the memory |
---|
164 | * allocated by this system is released. |
---|
165 | */ |
---|
166 | void ers_force_destroy_all(void); |
---|
167 | #endif /* DISABLE_ERS / not DISABLE_ERS */ |
---|
168 | |
---|
169 | #endif /* _ERS_H_ */ |
---|