ers.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. #ifndef _CBASETYPES_H_
  43. #include "../common/cbasetypes.h"
  44. #endif
  45. /*****************************************************************************\
  46. * (1) All public parts of the Entry Reusage System. *
  47. * DISABLE_ERS - Define to disable this system. *
  48. * ERS_ALIGNED - Alignment of the entries in the blocks. *
  49. * ERS - Entry manager. *
  50. * ers_new - Allocate an instance of an entry manager. *
  51. * ers_report - Print a report about the current state. *
  52. * ers_force_destroy_all - Force the destruction of all the managers. *
  53. \*****************************************************************************/
  54. /**
  55. * Define this to disable the Entry Reusage System.
  56. * All code except the typedef of ERInterface will be disabled.
  57. * To allow a smooth transition,
  58. */
  59. //#define DISABLE_ERS
  60. /**
  61. * Entries are aligned to ERS_ALIGNED bytes in the blocks of entries.
  62. * By default it aligns to one byte, using the "natural order" of the entries.
  63. * This should NEVER be set to zero or less.
  64. * If greater than one, some memory can be wasted. This should never be needed
  65. * but is here just in case some aligment issues arise.
  66. */
  67. #ifndef ERS_ALIGNED
  68. # define ERS_ALIGNED 1
  69. #endif /* not ERS_ALIGN_ENTRY */
  70. /**
  71. * Public interface of the entry manager.
  72. * @param alloc Allocate an entry from this manager
  73. * @param free Free an entry allocated from this manager
  74. * @param entry_size Return the size of the entries of this manager
  75. * @param destroy Destroy this instance of the manager
  76. */
  77. typedef struct eri {
  78. /**
  79. * Allocate an entry from this entry manager.
  80. * If there are reusable entries available, it reuses one instead.
  81. * @param self Interface of the entry manager
  82. * @return An entry
  83. */
  84. void *(*alloc)(struct eri *self);
  85. /**
  86. * Free an entry allocated from this manager.
  87. * WARNING: Does not check if the entry was allocated by this manager.
  88. * Freeing such an entry can lead to unexpected behaviour.
  89. * @param self Interface of the entry manager
  90. * @param entry Entry to be freed
  91. */
  92. void (*free)(struct eri *self, void *entry);
  93. /**
  94. * Return the size of the entries allocated from this manager.
  95. * @param self Interface of the entry manager
  96. * @return Size of the entries of this manager in bytes
  97. */
  98. size_t (*entry_size)(struct eri *self);
  99. /**
  100. * Destroy this instance of the manager.
  101. * The manager is actually only destroyed when all the instances are destroyed.
  102. * When destroying the manager a warning is shown if the manager has
  103. * missing/extra entries.
  104. * @param self Interface of the entry manager
  105. */
  106. void (*destroy)(struct eri *self);
  107. } *ERS;
  108. #ifdef DISABLE_ERS
  109. // Use memory manager to allocate/free and disable other interface functions
  110. # define ers_alloc(obj,type) (type *)aMalloc(sizeof(type))
  111. # define ers_free(obj,entry) aFree(entry)
  112. # define ers_entry_size(obj) (size_t)0
  113. # define ers_destroy(obj)
  114. // Disable the public functions
  115. # define ers_new(size) NULL
  116. # define ers_report()
  117. # define ers_force_destroy_all()
  118. #else /* not DISABLE_ERS */
  119. // These defines should be used to allow the code to keep working whenever
  120. // the system is disabled
  121. # define ers_alloc(obj,type) (type *)(obj)->alloc(obj)
  122. # define ers_free(obj,entry) (obj)->free((obj),(entry))
  123. # define ers_entry_size(obj) (obj)->entry_size(obj)
  124. # define ers_destroy(obj) (obj)->destroy(obj)
  125. /**
  126. * Get a new instance of the manager that handles the specified entry size.
  127. * Size has to greater than 0.
  128. * If the specified size is smaller than a pointer, the size of a pointer is
  129. * used instead.
  130. * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of
  131. * ERS_ALIGNED that is greater or equal to size is what's actually used.
  132. * @param The requested size of the entry in bytes
  133. * @return Interface of the object
  134. */
  135. ERS ers_new(uint32 size);
  136. /**
  137. * Print a report about the current state of the Entry Reusage System.
  138. * Shows information about the global system and each entry manager.
  139. * The number of entries are checked and a warning is shown if extra reusable
  140. * entries are found.
  141. * The extra entries are included in the count of reusable entries.
  142. */
  143. void ers_report(void);
  144. /**
  145. * Forcibly destroy all the entry managers, checking for nothing.
  146. * The system is left as if no instances or entries had ever been allocated.
  147. * All previous entries and instances of the managers become invalid.
  148. * The use of this is NOT recommended.
  149. * It should only be used in extreme situations to make shure all the memory
  150. * allocated by this system is released.
  151. */
  152. void ers_force_destroy_all(void);
  153. #endif /* DISABLE_ERS / not DISABLE_ERS */
  154. #endif /* _ERS_H_ */