diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 6e249bca7..794554cec 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -336,40 +336,6 @@ void write_faction_reference(const faction * f, struct storage *store) WRITE_INT(store, f ? f->no : 0); } -#define DMAXHASH 7919 -typedef struct dead { - struct dead *nexthash; - faction *f; - int no; -} dead; - -static dead *deadhash[DMAXHASH]; - -void dhash(int no, faction * f) -{ - dead *hash = (dead *)calloc(1, sizeof(dead)); - dead *old = deadhash[no % DMAXHASH]; - hash->no = no; - hash->f = f; - deadhash[no % DMAXHASH] = hash; - hash->nexthash = old; -} - -faction *dfindhash(int no) -{ - dead *old; - - if (no < 0) - return 0; - - for (old = deadhash[no % DMAXHASH]; old; old = old->nexthash) { - if (old->no == no) { - return old->f; - } - } - return 0; -} - void free_flist(faction **fp) { faction * flist = *fp; while (flist) { @@ -868,6 +834,7 @@ int writepasswd(void) } void free_factions(void) { +#ifdef DMAXHASH int i; for (i = 0; i != DMAXHASH; ++i) { while (deadhash[i]) { @@ -876,6 +843,7 @@ void free_factions(void) { free(d); } } +#endif free_flist(&factions); free_flist(&dead_factions); } diff --git a/src/kernel/faction.h b/src/kernel/faction.h index 2cb2fc9f3..5a1ca893b 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -180,10 +180,6 @@ extern "C" { struct faction *getfaction(void); - /* looking up dead factions: */ - void dhash(int no, struct faction * f); - struct faction *dfindhash(int no); - #ifdef __cplusplus } #endif diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 7ebcd1a45..75ced96df 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -191,29 +191,10 @@ static void test_set_origin_bug(CuTest *tc) { test_cleanup(); } -static void test_deadhash(CuTest *tc) { - faction *f; - int no; - test_setup(); - f = test_create_faction(0); - no = f->no; - CuAssertPtrEquals(tc, f, findfaction(no)); - CuAssertPtrEquals(tc, NULL, dfindhash(42)); - dhash(41, f); - dhash(42, f); - assert(f == factions); - destroyfaction(&factions); - CuAssertPtrEquals(tc, 0, findfaction(no)); - CuAssertPtrEquals(tc, f, dfindhash(42)); - CuAssertPtrEquals(tc, f, dfindhash(41)); - test_cleanup(); -} - CuSuite *get_faction_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_addfaction); - SUITE_ADD_TEST(suite, test_deadhash); SUITE_ADD_TEST(suite, test_remove_empty_factions); SUITE_ADD_TEST(suite, test_destroyfaction_allies); SUITE_ADD_TEST(suite, test_remove_empty_factions_alliance); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index cdd08cb43..fb4723f29 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -366,6 +366,51 @@ int gift_items(unit * u, int flags) static unit *deleted_units = NULL; +#define DMAXHASH 7919 +#undef DMAXHASH // TODO: makes dfindhash slow! +#ifdef DMAXHASH +typedef struct dead { + struct dead *nexthash; + faction *f; + int no; +} dead; + +static dead *deadhash[DMAXHASH]; + +static void dhash(int no, faction * f) +{ + dead *hash = (dead *)calloc(1, sizeof(dead)); + dead *old = deadhash[no % DMAXHASH]; + hash->no = no; + hash->f = f; + deadhash[no % DMAXHASH] = hash; + hash->nexthash = old; +} + +faction *dfindhash(int no) +{ + dead *old; + + if (no < 0) + return 0; + + for (old = deadhash[no % DMAXHASH]; old; old = old->nexthash) { + if (old->no == no) { + return old->f; + } + } + return 0; +} +#else +struct faction *dfindhash(int no) { + unit *u = deleted_units; + while (u && u->no != no) { + u = u->next; + } + return u ? u->faction : NULL; +} +#endif + int remove_unit(unit ** ulist, unit * u) { int result; @@ -379,8 +424,9 @@ int remove_unit(unit ** ulist, unit * u) return -1; } - if (u->number) + if (u->number) { set_number(u, 0); + } leave(u, true); u->region = NULL; @@ -393,11 +439,22 @@ int remove_unit(unit ** ulist, unit * u) *ulist = u->next; } + if (u->prevF) { + u->prevF->nextF = u->nextF; + } + if (u->nextF) { + u->nextF->prevF = u->prevF; + } + u->nextF = 0; + u->prevF = 0; + u->next = deleted_units; deleted_units = u; +#ifdef DMAXHASH dhash(u->no, u->faction); +#endif + // u_setfaction(u, NULL); - u_setfaction(u, NULL); u->region = NULL; return 0; diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 2a74e4fbb..459d0b656 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -174,6 +174,9 @@ extern "C" { const struct region *r, bool noitem); int remove_unit(struct unit **ulist, struct unit *u); + /* looking up dead units' factions: */ + struct faction *dfindhash(int no); + #define GIFT_SELF 1<<0 #define GIFT_FRIENDS 1<<1 #define GIFT_PEASANTS 1<<2 diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index df8496dce..162bf1570 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -50,14 +50,16 @@ static void test_remove_empty_units_in_region(CuTest *tc) { test_create_world(); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); + u = test_create_unit(u->faction, u->region); + CuAssertPtrNotNull(tc, u->nextF); uid = u->no; remove_empty_units_in_region(u->region); CuAssertPtrNotNull(tc, findunit(uid)); u->number = 0; remove_empty_units_in_region(u->region); CuAssertPtrEquals(tc, 0, findunit(uid)); + CuAssertPtrEquals(tc, 0, u->nextF); CuAssertPtrEquals(tc, 0, u->region); - CuAssertPtrEquals(tc, 0, u->faction); test_cleanup(); } @@ -422,7 +424,7 @@ static void test_remove_unit(CuTest *tc) { CuAssertIntEquals(tc, 0, u->number); CuAssertPtrEquals(tc, 0, u->region); CuAssertPtrEquals(tc, 0, u->items); - CuAssertPtrEquals(tc, 0, u->faction); + CuAssertPtrEquals(tc, 0, u->nextF); CuAssertPtrEquals(tc, 0, r->units); CuAssertPtrEquals(tc, 0, findunit(uno)); CuAssertPtrEquals(tc, f, dfindhash(uno));