Browse Source

Hello! few things.
1) fixed bugreport:6603 - delayed clearunit now makes use of the ERS which is quite convenient for it speeds up due to the previous amount of mallocs that function would spend.
2) added extra debug information to the ERS system (before on any of its warnings we'd go OH MY GOD WHICH ONE OF THEM DID IT!!!), now upon allocation you give it a const, human-readable, name.
3) added support for options in the ERS system to save multiple/redudant processing in battle_delayed_damage and clif_clearunit_delayed and perhaps also in the future.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@16736 54d463be-8e91-2dee-dedb-b68131a5f0ec

shennetsind 12 years ago
parent
commit
779d97c1cb
14 changed files with 67 additions and 47 deletions
  1. 1 1
      src/common/db.c
  2. 25 12
      src/common/ers.c
  3. 7 2
      src/common/ers.h
  4. 1 1
      src/map/battle.c
  5. 1 1
      src/map/chrif.c
  6. 21 21
      src/map/clif.c
  7. 1 0
      src/map/clif.h
  8. 1 1
      src/map/guild.c
  9. 1 0
      src/map/map.c
  10. 2 2
      src/map/mob.c
  11. 1 1
      src/map/npc.c
  12. 2 2
      src/map/pet.c
  13. 2 2
      src/map/skill.c
  14. 1 1
      src/map/status.c

+ 1 - 1
src/common/db.c

@@ -2440,7 +2440,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
 	db->free_max = 0;
 	db->free_max = 0;
 	db->free_lock = 0;
 	db->free_lock = 0;
 	/* Other */
 	/* Other */
-	db->nodes = ers_new(sizeof(struct dbn));
+	db->nodes = ers_new(sizeof(struct dbn),"db.c::db_alloc",ERS_OPT_NONE);
 	db->cmp = db_default_cmp(type);
 	db->cmp = db_default_cmp(type);
 	db->hash = db_default_hash(type);
 	db->hash = db_default_hash(type);
 	db->release = db_default_release(type, options);
 	db->release = db_default_release(type, options);

+ 25 - 12
src/common/ers.c

@@ -139,6 +139,16 @@ typedef struct ers_impl {
 	 */
 	 */
 	size_t size;
 	size_t size;
 
 
+	/**
+	 * Reference to this instance of the table
+	 */
+	char *name;
+	
+	/**
+	 * Options used by this instance
+	 */
+	enum ERSOptions options;
+	
 } *ERS_impl;
 } *ERS_impl;
 
 
 /**
 /**
@@ -195,8 +205,8 @@ static void *ers_obj_alloc_entry(ERS self)
 	} else { // allocate a new block
 	} else { // allocate a new block
 		if (obj->num == obj->max) { // expand the block array
 		if (obj->num == obj->max) { // expand the block array
 			if (obj->max == UINT32_MAX) { // No more space for blocks
 			if (obj->max == UINT32_MAX) { // No more space for blocks
-				ShowFatalError("ers::alloc : maximum number of blocks reached, increase ERS_BLOCK_ENTRIES.\n"
-						"exiting the program...\n");
+				ShowFatalError("ers::alloc : maximum number of blocks reached, increase ERS_BLOCK_ENTRIES. (by %s)\n"
+						"exiting the program...\n",obj->name);
 				exit(EXIT_FAILURE);
 				exit(EXIT_FAILURE);
 			}
 			}
 			obj->max = (obj->max*4)+3; // left shift bits '11' - overflow won't happen
 			obj->max = (obj->max*4)+3; // left shift bits '11' - overflow won't happen
@@ -229,7 +239,7 @@ static void ers_obj_free_entry(ERS self, void *entry)
 		ShowError("ers::free : NULL object, aborting entry freeing.\n");
 		ShowError("ers::free : NULL object, aborting entry freeing.\n");
 		return;
 		return;
 	} else if (entry == NULL) {
 	} else if (entry == NULL) {
-		ShowError("ers::free : NULL entry, nothing to free.\n");
+		ShowError("ers::free : NULL entry in obj '%s', nothing to free.\n",obj->name);
 		return;
 		return;
 	}
 	}
 
 
@@ -311,15 +321,16 @@ static void ers_obj_destroy(ERS self)
 		}
 		}
 	}
 	}
 	if (count) { // missing entries
 	if (count) { // missing entries
-		ShowWarning("ers::destroy : %u entries missing (possible double free), continuing destruction (entry size=%u).\n",
-				count, obj->size);
+		if( !(obj->options&ERS_OPT_CLEAR) )
+			ShowWarning("ers::destroy : %u entries missing in '%s' (possible double free), continuing destruction (entry size=%u).\n",
+				count, obj->name, obj->size);
 	} else if (reuse) { // extra entries
 	} else if (reuse) { // extra entries
 		while (reuse && count != UINT32_MAX) {
 		while (reuse && count != UINT32_MAX) {
 			count++;
 			count++;
 			reuse = reuse->next;
 			reuse = reuse->next;
 		}
 		}
-		ShowWarning("ers::destroy : %u extra entries found, continuing destruction (entry size=%u).\n",
-				count, obj->size);
+		ShowWarning("ers::destroy : %u extra entries found in '%s', continuing destruction (entry size=%u).\n",
+				count, obj->name, obj->size);
 	}
 	}
 	// destroy the entry manager
 	// destroy the entry manager
 	if (obj->max) {
 	if (obj->max) {
@@ -350,8 +361,7 @@ static void ers_obj_destroy(ERS self)
  * @see #ers_root
  * @see #ers_root
  * @see #ers_num
  * @see #ers_num
  */
  */
-ERS ers_new(uint32 size)
-{
+ERS ers_new(uint32 size, char *name, enum ERSOptions options) {
 	ERS_impl obj;
 	ERS_impl obj;
 	uint32 i;
 	uint32 i;
 
 
@@ -376,8 +386,8 @@ ERS ers_new(uint32 size)
 	}
 	}
 	// create a new manager to handle the entry size
 	// create a new manager to handle the entry size
 	if (ers_num == ERS_ROOT_SIZE) {
 	if (ers_num == ERS_ROOT_SIZE) {
-		ShowFatalError("ers_alloc: too many root objects, increase ERS_ROOT_SIZE.\n"
-				"exiting the program...\n");
+		ShowFatalError("ers_alloc: too many root objects, increase ERS_ROOT_SIZE. (by %s)\n"
+				"exiting the program...\n",name);
 		exit(EXIT_FAILURE);
 		exit(EXIT_FAILURE);
 	}
 	}
 	obj = (ERS_impl)aMalloc(sizeof(struct ers_impl));
 	obj = (ERS_impl)aMalloc(sizeof(struct ers_impl));
@@ -395,6 +405,9 @@ ERS ers_new(uint32 size)
 	obj->destroy = 1;
 	obj->destroy = 1;
 	// Properties
 	// Properties
 	obj->size = size;
 	obj->size = size;
+	obj->options = options;
+	// Info
+	obj->name = name;
 	ers_root[ers_num++] = obj;
 	ers_root[ers_num++] = obj;
 	return &obj->vtable;
 	return &obj->vtable;
 }
 }
@@ -460,7 +473,7 @@ void ers_report(void)
 			reuse = reuse->next;
 			reuse = reuse->next;
 		}
 		}
 		// Entry manager report
 		// Entry manager report
-		ShowMessage(CL_BOLD"[Entry manager #%u report]\n"CL_NORMAL, i);
+		ShowMessage(CL_BOLD"[Entry manager '%s' #%u report]\n"CL_NORMAL, obj->name, i);
 		ShowMessage("\tinstances          : %u\n", obj->destroy);
 		ShowMessage("\tinstances          : %u\n", obj->destroy);
 		ShowMessage("\tentry size         : %u\n", obj->size);
 		ShowMessage("\tentry size         : %u\n", obj->size);
 		ShowMessage("\tblock array size   : %u\n", obj->max);
 		ShowMessage("\tblock array size   : %u\n", obj->max);

+ 7 - 2
src/common/ers.h

@@ -70,6 +70,11 @@
 #	define ERS_ALIGNED 1
 #	define ERS_ALIGNED 1
 #endif /* not ERS_ALIGN_ENTRY */
 #endif /* not ERS_ALIGN_ENTRY */
 
 
+enum ERSOptions {
+	ERS_OPT_NONE           = 0,
+	ERS_OPT_CLEAR          = 1,/* silently clears any entries left in the manager upon destruction */
+};
+
 /**
 /**
  * Public interface of the entry manager.
  * Public interface of the entry manager.
  * @param alloc Allocate an entry from this manager
  * @param alloc Allocate an entry from this manager
@@ -121,7 +126,7 @@ typedef struct eri {
 #	define ers_entry_size(obj) (size_t)0
 #	define ers_entry_size(obj) (size_t)0
 #	define ers_destroy(obj)
 #	define ers_destroy(obj)
 // Disable the public functions
 // Disable the public functions
-#	define ers_new(size) NULL
+#	define ers_new(size,name) NULL
 #	define ers_report()
 #	define ers_report()
 #	define ers_force_destroy_all()
 #	define ers_force_destroy_all()
 #else /* not DISABLE_ERS */
 #else /* not DISABLE_ERS */
@@ -142,7 +147,7 @@ typedef struct eri {
  * @param The requested size of the entry in bytes
  * @param The requested size of the entry in bytes
  * @return Interface of the object
  * @return Interface of the object
  */
  */
-ERS ers_new(uint32 size);
+ERS ers_new(uint32 size, char *name, enum ERSOptions options);
 
 
 /**
 /**
  * Print a report about the current state of the Entry Reusage System.
  * Print a report about the current state of the Entry Reusage System.

+ 1 - 1
src/map/battle.c

@@ -5834,7 +5834,7 @@ int battle_config_read(const char* cfgName)
 
 
 void do_init_battle(void)
 void do_init_battle(void)
 {
 {
-	delay_damage_ers = ers_new(sizeof(struct delay_damage));
+	delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR);
 	add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
 	add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
 }
 }
 
 

+ 1 - 1
src/map/chrif.c

@@ -1598,7 +1598,7 @@ int do_final_chrif(void)
 int do_init_chrif(void)
 int do_init_chrif(void)
 {
 {
 	auth_db = idb_alloc(DB_OPT_BASE);
 	auth_db = idb_alloc(DB_OPT_BASE);
-	auth_db_ers = ers_new(sizeof(struct auth_node));
+	auth_db_ers = ers_new(sizeof(struct auth_node),"chrif.c::auth_db_ers",ERS_OPT_NONE);
 
 
 	add_timer_func_list(check_connect_char_server, "check_connect_char_server");
 	add_timer_func_list(check_connect_char_server, "check_connect_char_server");
 	add_timer_func_list(ping_char_server, "ping_char_server");
 	add_timer_func_list(ping_char_server, "ping_char_server");

+ 21 - 21
src/map/clif.c

@@ -11,6 +11,7 @@
 #include "../common/showmsg.h"
 #include "../common/showmsg.h"
 #include "../common/strlib.h"
 #include "../common/strlib.h"
 #include "../common/utils.h"
 #include "../common/utils.h"
+#include "../common/ers.h"
 
 
 #include "map.h"
 #include "map.h"
 #include "chrif.h"
 #include "chrif.h"
@@ -48,6 +49,9 @@
 #include <stdarg.h>
 #include <stdarg.h>
 #include <time.h>
 #include <time.h>
 
 
+/* for clif_clearunit_delayed */
+static struct eri *delay_clearunit_ers;
+
 //#define DUMP_UNKNOWN_PACKET
 //#define DUMP_UNKNOWN_PACKET
 //#define DUMP_INVALID_PACKET
 //#define DUMP_INVALID_PACKET
 
 
@@ -103,18 +107,15 @@ static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short*
 {
 {
 	p += pos;
 	p += pos;
 
 
-	if( x )
-	{
+	if( x ) {
 		x[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 );
 		x[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 );
 	}
 	}
 
 
-	if( y )
-	{
+	if( y ) {
 		y[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 );
 		y[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 );
 	}
 	}
 
 
-	if( dir )
-	{
+	if( dir ) {
 		dir[0] = ( p[2] & 0x0f );
 		dir[0] = ( p[2] & 0x0f );
 	}
 	}
 }
 }
@@ -124,33 +125,27 @@ static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short
 {
 {
 	p += pos;
 	p += pos;
 
 
-	if( x0 )
-	{
+	if( x0 ) {
 		x0[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 );
 		x0[0] = ( ( p[0] & 0xff ) << 2 ) | ( p[1] >> 6 );
 	}
 	}
 
 
-	if( y0 )
-	{
+	if( y0 ) {
 		y0[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 );
 		y0[0] = ( ( p[1] & 0x3f ) << 4 ) | ( p[2] >> 4 );
 	}
 	}
 
 
-	if( x1 )
-	{
+	if( x1 ) {
 		x1[0] = ( ( p[2] & 0x0f ) << 6 ) | ( p[3] >> 2 );
 		x1[0] = ( ( p[2] & 0x0f ) << 6 ) | ( p[3] >> 2 );
 	}
 	}
 
 
-	if( y1 )
-	{
+	if( y1 ) {
 		y1[0] = ( ( p[3] & 0x03 ) << 8 ) | ( p[4] >> 0 );
 		y1[0] = ( ( p[3] & 0x03 ) << 8 ) | ( p[4] >> 0 );
 	}
 	}
 
 
-	if( sx0 )
-	{
+	if( sx0 ) {
 		sx0[0] = ( p[5] & 0xf0 ) >> 4;
 		sx0[0] = ( p[5] & 0xf0 ) >> 4;
 	}
 	}
 
 
-	if( sy0 )
-	{
+	if( sy0 ) {
 		sy0[0] = ( p[5] & 0x0f ) >> 0;
 		sy0[0] = ( p[5] & 0x0f ) >> 0;
 	}
 	}
 }
 }
@@ -848,13 +843,12 @@ static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr
 {
 {
 	struct block_list *bl = (struct block_list *)data;
 	struct block_list *bl = (struct block_list *)data;
 	clif_clearunit_area(bl, (clr_type) id);
 	clif_clearunit_area(bl, (clr_type) id);
-	aFree(bl);
+	ers_free(delay_clearunit_ers,bl);
 	return 0;
 	return 0;
 }
 }
 void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick)
 void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick)
 {
 {
-	struct block_list *tbl;
-	tbl = (struct block_list*)aMalloc(sizeof (struct block_list));
+	struct block_list *tbl = ers_alloc(delay_clearunit_ers, struct block_list);
 	memcpy (tbl, bl, sizeof (struct block_list));
 	memcpy (tbl, bl, sizeof (struct block_list));
 	add_timer(tick, clif_clearunit_delayed_sub, (int)type, (intptr_t)tbl);
 	add_timer(tick, clif_clearunit_delayed_sub, (int)type, (intptr_t)tbl);
 }
 }
@@ -17031,5 +17025,11 @@ int do_init_clif(void) {
 	add_timer_func_list(clif_clearunit_delayed_sub, "clif_clearunit_delayed_sub");
 	add_timer_func_list(clif_clearunit_delayed_sub, "clif_clearunit_delayed_sub");
 	add_timer_func_list(clif_delayquit, "clif_delayquit");
 	add_timer_func_list(clif_delayquit, "clif_delayquit");
 
 
+	delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR);
+	
 	return 0;
 	return 0;
 }
 }
+
+void do_final_clif(void) {
+	ers_destroy(delay_clearunit_ers);
+}

+ 1 - 0
src/map/clif.h

@@ -639,6 +639,7 @@ void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, b
 
 
 int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type);
 int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type);
 int do_init_clif(void);
 int do_init_clif(void);
+void do_final_clif(void);
 
 
 // MAIL SYSTEM
 // MAIL SYSTEM
 void clif_Mail_window(int fd, int flag);
 void clif_Mail_window(int fd, int flag);

+ 1 - 1
src/map/guild.c

@@ -1990,7 +1990,7 @@ void do_init_guild(void)
 	castle_db=idb_alloc(DB_OPT_BASE);
 	castle_db=idb_alloc(DB_OPT_BASE);
 	guild_expcache_db=idb_alloc(DB_OPT_BASE);
 	guild_expcache_db=idb_alloc(DB_OPT_BASE);
 	guild_infoevent_db=idb_alloc(DB_OPT_BASE);
 	guild_infoevent_db=idb_alloc(DB_OPT_BASE);
-	expcache_ers = ers_new(sizeof(struct guild_expcache)); 
+	expcache_ers = ers_new(sizeof(struct guild_expcache),"guild.c::expcache_ers",ERS_OPT_NONE);
 
 
 	sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb);
 	sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb);
 
 

+ 1 - 0
src/map/map.c

@@ -3633,6 +3633,7 @@ void do_final(void)
 	do_final_atcommand();
 	do_final_atcommand();
 	do_final_battle();
 	do_final_battle();
 	do_final_chrif();
 	do_final_chrif();
+	do_final_clif();
 	do_final_npc();
 	do_final_npc();
 	do_final_script();
 	do_final_script();
 	do_final_instance();
 	do_final_instance();

+ 2 - 2
src/map/mob.c

@@ -4624,8 +4624,8 @@ int do_init_mob(void)
 	memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
 	memset(mob_db_data,0,sizeof(mob_db_data)); //Clear the array
 	mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db));	//This mob is used for random spawns
 	mob_db_data[0] = (struct mob_db*)aCalloc(1, sizeof (struct mob_db));	//This mob is used for random spawns
 	mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
 	mob_makedummymobdb(0); //The first time this is invoked, it creates the dummy mob
-	item_drop_ers = ers_new(sizeof(struct item_drop));
-	item_drop_list_ers = ers_new(sizeof(struct item_drop_list));
+	item_drop_ers = ers_new(sizeof(struct item_drop),"mob.c::item_drop_ers",ERS_OPT_NONE);
+	item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"mob.c::item_drop_list_ers",ERS_OPT_NONE);
 
 
 	mob_load();
 	mob_load();
 
 

+ 1 - 1
src/map/npc.c

@@ -3734,7 +3734,7 @@ int do_init_npc(void)
 	npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
 	npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH);
 	npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
 	npc_path_db = strdb_alloc(DB_OPT_BASE|DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA,80);
 	
 	
-	timer_event_ers = ers_new(sizeof(struct timer_event_data));
+	timer_event_ers = ers_new(sizeof(struct timer_event_data),"clif.c::timer_event_ers",ERS_OPT_NONE);
 	
 	
 	// process all npc files
 	// process all npc files
 	ShowStatus("Loading NPCs...\r");
 	ShowStatus("Loading NPCs...\r");

+ 2 - 2
src/map/pet.c

@@ -1349,8 +1349,8 @@ int do_init_pet(void)
 {
 {
 	read_petdb();
 	read_petdb();
 
 
-	item_drop_ers = ers_new(sizeof(struct item_drop));
-	item_drop_list_ers = ers_new(sizeof(struct item_drop_list));
+	item_drop_ers = ers_new(sizeof(struct item_drop),"pet.c::item_drop_ers",ERS_OPT_NONE);
+	item_drop_list_ers = ers_new(sizeof(struct item_drop_list),"pet.c::item_drop_list_ers",ERS_OPT_NONE);
 	
 	
 	add_timer_func_list(pet_hungry,"pet_hungry");
 	add_timer_func_list(pet_hungry,"pet_hungry");
 	add_timer_func_list(pet_ai_hard,"pet_ai_hard");
 	add_timer_func_list(pet_ai_hard,"pet_ai_hard");

+ 2 - 2
src/map/skill.c

@@ -17545,8 +17545,8 @@ int do_init_skill (void)
 	skillunit_db = idb_alloc(DB_OPT_BASE);
 	skillunit_db = idb_alloc(DB_OPT_BASE);
 	skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
 	skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
-	skill_unit_ers = ers_new(sizeof(struct skill_unit_group));
-	skill_timer_ers  = ers_new(sizeof(struct skill_timerskill));
+	skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE);
+	skill_timer_ers  = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE);
 
 
 	add_timer_func_list(skill_unit_timer,"skill_unit_timer");
 	add_timer_func_list(skill_unit_timer,"skill_unit_timer");
 	add_timer_func_list(skill_castend_id,"skill_castend_id");
 	add_timer_func_list(skill_castend_id,"skill_castend_id");

+ 1 - 1
src/map/status.c

@@ -10939,7 +10939,7 @@ int do_init_status(void)
 	status_readdb();
 	status_readdb();
 	status_calc_sigma();
 	status_calc_sigma();
 	natural_heal_prev_tick = gettick();
 	natural_heal_prev_tick = gettick();
-	sc_data_ers = ers_new(sizeof(struct status_change_entry));
+	sc_data_ers = ers_new(sizeof(struct status_change_entry),"status.c::sc_data_ers",ERS_OPT_NONE);
 	add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
 	add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
 	return 0;
 	return 0;
 }
 }