ers.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 behaviors. *
  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 fragmentation - program will run better for longer. *
  24. * *
  25. * <H2>Disadvantages:</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. #ifdef __cplusplus
  43. extern "C" {
  44. #endif
  45. #include "cbasetypes.h"
  46. /*****************************************************************************\
  47. * (1) All public parts of the Entry Reusage System. *
  48. * DISABLE_ERS - Define to disable this system. *
  49. * ERS_ALIGNED - Alignment of the entries in the blocks. *
  50. * ERS - Entry manager. *
  51. * ers_new - Allocate an instance of an entry manager. *
  52. * ers_report - Print a report about the current state. *
  53. * ers_final - Clears the remainder of the managers. *
  54. \*****************************************************************************/
  55. /**
  56. * Define this to disable the Entry Reusage System.
  57. * All code except the typedef of ERInterface will be disabled.
  58. * To allow a smooth transition,
  59. */
  60. //#define DISABLE_ERS
  61. /**
  62. * Entries are aligned to ERS_ALIGNED bytes in the blocks of entries.
  63. * By default it aligns to one byte, using the "natural order" of the entries.
  64. * This should NEVER be set to zero or less.
  65. * If greater than one, some memory can be wasted. This should never be needed
  66. * but is here just in case some alignment issues arise.
  67. */
  68. #ifndef ERS_ALIGNED
  69. # define ERS_ALIGNED 1
  70. #endif /* not ERS_ALIGN_ENTRY */
  71. enum ERSOptions {
  72. ERS_OPT_NONE = 0x00,
  73. ERS_OPT_CLEAR = 0x01,/* silently clears any entries left in the manager upon destruction */
  74. ERS_OPT_WAIT = 0x02,/* wait for entries to come in order to list! */
  75. ERS_OPT_FREE_NAME = 0x04,/* name is dynamic memory, and should be freed */
  76. ERS_OPT_CLEAN = 0x08,/* clears used memory upon ers_free so that its all new to be reused on the next alloc */
  77. ERS_OPT_FLEX_CHUNK = 0x10,/* signs that it should look for its own cache given it'll have a dynamic chunk size, so that it doesn't affect the other ERS it'd otherwise be sharing */
  78. /* Compound, is used to determine whether it should be looking for a cache of matching options */
  79. ERS_CACHE_OPTIONS = ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK,
  80. ERS_CLEAN_OPTIONS = ERS_OPT_CLEAN|ERS_OPT_CLEAR,
  81. };
  82. /**
  83. * Public interface of the entry manager.
  84. * @param alloc Allocate an entry from this manager
  85. * @param free Free an entry allocated from this manager
  86. * @param entry_size Return the size of the entries of this manager
  87. * @param destroy Destroy this instance of the manager
  88. */
  89. typedef struct eri {
  90. /**
  91. * Allocate an entry from this entry manager.
  92. * If there are reusable entries available, it reuses one instead.
  93. * @param self Interface of the entry manager
  94. * @return An entry
  95. */
  96. void *(*alloc)(struct eri *self);
  97. /**
  98. * Free an entry allocated from this manager.
  99. * WARNING: Does not check if the entry was allocated by this manager.
  100. * Freeing such an entry can lead to unexpected behavior.
  101. * @param self Interface of the entry manager
  102. * @param entry Entry to be freed
  103. */
  104. void (*free)(struct eri *self, void *entry);
  105. /**
  106. * Return the size of the entries allocated from this manager.
  107. * @param self Interface of the entry manager
  108. * @return Size of the entries of this manager in bytes
  109. */
  110. size_t (*entry_size)(struct eri *self);
  111. /**
  112. * Destroy this instance of the manager.
  113. * The manager is actually only destroyed when all the instances are destroyed.
  114. * When destroying the manager a warning is shown if the manager has
  115. * missing/extra entries.
  116. * @param self Interface of the entry manager
  117. */
  118. void (*destroy)(struct eri *self);
  119. /* */
  120. void (*chunk_size) (struct eri *self, unsigned int new_size);
  121. } ERS;
  122. #ifdef DISABLE_ERS
  123. // Use memory manager to allocate/free and disable other interface functions
  124. # define ers_alloc(obj,type) (type *)aMalloc(sizeof(type))
  125. # define ers_free(obj,entry) aFree(entry)
  126. # define ers_entry_size(obj) (size_t)0
  127. # define ers_destroy(obj)
  128. # define ers_chunk_size(obj,size)
  129. // Disable the public functions
  130. # define ers_new(size,name,options) NULL
  131. # define ers_report()
  132. # define ers_final()
  133. #else /* not DISABLE_ERS */
  134. // These defines should be used to allow the code to keep working whenever
  135. // the system is disabled
  136. # define ers_alloc(obj,type) ((type *)(obj)->alloc(obj))
  137. # define ers_free(obj,entry) ((obj)->free((obj),(entry)))
  138. # define ers_entry_size(obj) ((obj)->entry_size(obj))
  139. # define ers_destroy(obj) ((obj)->destroy(obj))
  140. # define ers_chunk_size(obj,size) ((obj)->chunk_size((obj),(size)))
  141. /**
  142. * Get a new instance of the manager that handles the specified entry size.
  143. * Size has to greater than 0.
  144. * If the specified size is smaller than a pointer, the size of a pointer is
  145. * used instead.
  146. * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of
  147. * ERS_ALIGNED that is greater or equal to size is what's actually used.
  148. * @param The requested size of the entry in bytes
  149. * @return Interface of the object
  150. */
  151. ERS *ers_new(uint32 size, const char *name, enum ERSOptions options);
  152. /**
  153. * Print a report about the current state of the Entry Reusage System.
  154. * Shows information about the global system and each entry manager.
  155. * The number of entries are checked and a warning is shown if extra reusable
  156. * entries are found.
  157. * The extra entries are included in the count of reusable entries.
  158. */
  159. void ers_report(void);
  160. /**
  161. * Clears the remainder of the managers
  162. **/
  163. void ers_final(void);
  164. #endif /* DISABLE_ERS / not DISABLE_ERS */
  165. #ifdef __cplusplus
  166. }
  167. #endif
  168. #endif /* _ERS_H_ */