[1] | 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_ */ |
---|