diff options
Diffstat (limited to 'src/common/ers.h')
-rw-r--r-- | src/common/ers.h | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/common/ers.h b/src/common/ers.h new file mode 100644 index 000000000..a512f6365 --- /dev/null +++ b/src/common/ers.h @@ -0,0 +1,193 @@ +/*****************************************************************************\
+ * Copyright (c) Athena Dev Teams - Licensed under GNU GPL *
+ * For more information, see LICENCE in the main folder *
+ * *
+ * <H1>Entry Reusage System</H1> *
+ * *
+ * There are several root entry managers, each with a different entry size. *
+ * Each manager will keep track of how many instances have been 'created'. *
+ * They will only automatically destroy themselves after the last instance *
+ * is destroyed. *
+ * *
+ * Entries can be allocated from the managers. *
+ * If it has reusable entries (freed entry), it uses one. *
+ * So no assumption should be made about the data of the entry. *
+ * Entries should be freed in the manager they where allocated from. *
+ * Failure to do so can lead to unexpected behaviours. *
+ * *
+ * <H2>Advantages:</H2> *
+ * - The same manager is used for entries of the same size. *
+ * So entries freed in one instance of the manager can be used by other *
+ * instances of the manager. *
+ * - Much less memory allocation/deallocation - program will be faster. *
+ * - Avoids memory fragmentaion - program will run better for longer. *
+ * *
+ * <H2>Disavantages:</H2> *
+ * - Unused entries are almost inevitable - memory being wasted. *
+ * - A manager will only auto-destroy when all of its instances are *
+ * destroyed so memory will usually only be recovered near the end. *
+ * - Always wastes space for entries smaller than a pointer. *
+ * *
+ * WARNING: The system is not thread-safe at the moment. *
+ * *
+ * HISTORY: *
+ * 0.1 - Initial version *
+ * *
+ * @version 0.1 - Initial version *
+ * @author Flavio @ Amazon Project *
+ * @encoding US-ASCII *
+ * @see common#ers.c *
+\*****************************************************************************/
+#ifndef _ERS_H_
+#define _ERS_H_
+
+#include "../common/cbasetypes.h"
+
+/*****************************************************************************\
+ * (1) All public parts of the Entry Reusage System. *
+ * DISABLE_ERS - Define to disable this system. *
+ * ERS_ALIGNED - Alignment of the entries in the blocks. *
+ * ERInterface - Interface of the entry manager. *
+ * ers_new - Allocate an instance of an entry manager. *
+ * ers_report - Print a report about the current state. *
+ * ers_force_destroy_all - Force the destruction of all the managers. *
+\*****************************************************************************/
+
+/**
+ * Define this to disable the Entry Reusage System.
+ * All code except the typedef of ERInterface will be disabled.
+ * To allow a smooth transition,
+ * @public
+ */
+//#define DISABLE_ERS
+
+/**
+ * Entries are aligned to ERS_ALIGNED bytes in the blocks of entries.
+ * By default it aligns to one byte, using the "natural order" of the entries.
+ * This should NEVER be set to zero or less.
+ * If greater than one, some memory can be wasted. This should never be needed
+ * but is here just in case some aligment issues arise.
+ * @public
+ * @see #ers_new(uint32)
+ */
+#ifndef ERS_ALIGNED
+# define ERS_ALIGNED 1
+#endif /* not ERS_ALIGN_ENTRY */
+
+/**
+ * Public interface of the entry manager.
+ * @param alloc Allocate an entry from this manager
+ * @param free Free an entry allocated from this manager
+ * @param entry_size Return the size of the entries of this manager
+ * @param destroy Destroy this instance of the manager
+ * @public
+ * @see #ers_new(uint32)
+ */
+typedef struct eri {
+
+ /**
+ * Allocate an entry from this entry manager.
+ * If there are reusable entries available, it reuses one instead.
+ * @param self Interface of the entry manager
+ * @return An entry
+ * @protected
+ * @see #ERInterface
+ * @see ERInterface#free(ERInterface,void *)
+ */
+ void *(*alloc)(struct eri *self);
+
+ /**
+ * Free an entry allocated from this manager.
+ * WARNING: Does not check if the entry was allocated by this manager.
+ * Freeing such an entry can lead to unexpected behaviour.
+ * @param self Interface of the entry manager
+ * @param entry Entry to be freed
+ * @protected
+ * @see #ERInterface
+ * @see ERInterface#alloc(ERInterface)
+ */
+ void (*free)(struct eri *self, void *entry);
+
+ /**
+ * Return the size of the entries allocated from this manager.
+ * @param self Interface of the entry manager
+ * @return Size of the entries of this manager in bytes
+ * @protected
+ * @see #ERInterface
+ */
+ uint32 (*entry_size)(struct eri *self);
+
+ /**
+ * Destroy this instance of the manager.
+ * The manager is actually only destroyed when all the instances are destroyed.
+ * When destroying the manager a warning is shown if the manager has
+ * missing/extra entries.
+ * @param self Interface of the entry manager
+ * @protected
+ * @see #ERInterface
+ * @see #ers_new(uint32)
+ */
+ void (*destroy)(struct eri *self);
+
+} *ERInterface;
+
+#ifdef DISABLE_ERS
+// Use memory manager to allocate/free and disable other interface functions
+# define ers_alloc(obj,type) (type *)aMalloc(sizeof(type))
+# define ers_free(obj,entry) aFree(entry)
+# define ers_entry_size(obj) (uint32)0
+# define ers_destroy(obj)
+// Disable the public functions
+# define ers_new(size) NULL
+# define ers_report()
+# define ers_force_destroy_all()
+#else /* not DISABLE_ERS */
+// These defines should be used to allow the code to keep working whenever
+// the system is disabled
+# define ers_alloc(obj,type) (type *)(obj)->alloc(obj)
+# define ers_free(obj,entry) (obj)->free((obj),(entry))
+# define ers_entry_size(obj) (obj)->entry_size(obj)
+# define ers_destroy(obj) (obj)->destroy(obj)
+
+/**
+ * Get a new instance of the manager that handles the specified entry size.
+ * Size has to greater than 0.
+ * If the specified size is smaller than a pointer, the size of a pointer is
+ * used instead.
+ * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of
+ * ERS_ALIGNED that is greater or equal to size is what's actually used.
+ * @param The requested size of the entry in bytes
+ * @return Interface of the object
+ * @public
+ * @see #ERS_ALIGNED
+ * @see #ERInterface
+ * @see ERInterface#destroy(ERInterface)
+ * @see common\ers.c#ers_new(uint32)
+ */
+ERInterface ers_new(uint32 size);
+
+/**
+ * Print a report about the current state of the Entry Reusage System.
+ * Shows information about the global system and each entry manager.
+ * The number of entries are checked and a warning is shown if extra reusable
+ * entries are found.
+ * The extra entries are included in the count of reusable entries.
+ * @public
+ * @see common\ers.c#ers_report(void)
+ */
+void ers_report(void);
+
+/**
+ * Forcibly destroy all the entry managers, checking for nothing.
+ * The system is left as if no instances or entries had ever been allocated.
+ * All previous entries and instances of the managers become invalid.
+ * The use of this is NOT recommended.
+ * It should only be used in extreme situations to make shure all the memory
+ * allocated by this system is released.
+ * @public
+ * @see common\ers.c#ers_force_destroy_all(void)
+ */
+void ers_force_destroy_all(void);
+#endif /* DISABLE_ERS / not DISABLE_ERS */
+
+#endif /* _ERS_H_ */
|