From c755cf39f285791abafc9ad1d4bdf111014e6c9c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 9 May 2005 19:57:44 +0000 Subject: [PATCH] =?UTF-8?q?Reference-counting=20in=20Befehlen.=20Derzeit?= =?UTF-8?q?=20nur=20f=C3=BCr=20Befehle=20ohne=20Parameter.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/gamecode/laws.c | 2 +- src/common/gamecode/report.c | 2 +- src/common/gamecode/study.c | 2 +- src/common/kernel/build.c | 4 +- src/common/kernel/magic.c | 2 +- src/common/kernel/message.c | 4 +- src/common/kernel/movement.c | 2 +- src/common/kernel/order.c | 134 ++++++++++++++++++++++++----------- src/common/kernel/order.h | 11 ++- 9 files changed, 105 insertions(+), 58 deletions(-) diff --git a/src/common/gamecode/laws.c b/src/common/gamecode/laws.c index 64de0c9f9..d98cd6861 100644 --- a/src/common/gamecode/laws.c +++ b/src/common/gamecode/laws.c @@ -3450,7 +3450,7 @@ setdefaults (void) } #ifdef LASTORDER /* by default the default long order becomes the new long order. */ - u->thisorder = duplicate_order(u->lastorder); + u->thisorder = copy_order(u->lastorder); #endif /* check all orders for a potential new long order this round: */ for (ord = u->orders; ord; ord = ord->next) { diff --git a/src/common/gamecode/report.c b/src/common/gamecode/report.c index 15e70e2f9..39a4fbaa0 100644 --- a/src/common/gamecode/report.c +++ b/src/common/gamecode/report.c @@ -3780,7 +3780,7 @@ report_init(void) add_function("spell", &eval_spell); register_argtype("string", free, (void*(*)(void*))strdup); - register_argtype("order", (void(*)(void*))free_order, (void*(*)(void*))duplicate_order); + register_argtype("order", (void(*)(void*))free_order, (void*(*)(void*))copy_order); register_function((pf_generic)view_neighbours, "view_neighbours"); register_function((pf_generic)view_regatta, "view_regatta"); } diff --git a/src/common/gamecode/study.c b/src/common/gamecode/study.c index c65cec8a8..1c73985bd 100644 --- a/src/common/gamecode/study.c +++ b/src/common/gamecode/study.c @@ -427,7 +427,7 @@ teach(unit * u, struct order * ord) #ifdef LASTORDER set_order(&u->lastorder, new_order); #else - copy_order(ord, new_order); + replace_order(ord, new_order); #endif free_order(new_order); /* parse_order & set_order have each increased the refcount */ } diff --git a/src/common/kernel/build.c b/src/common/kernel/build.c index 375b29e4c..142f1f16e 100644 --- a/src/common/kernel/build.c +++ b/src/common/kernel/build.c @@ -934,7 +934,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord) #ifdef LASTORDER set_order(&u->lastorder, new_order); #else - copy_order(ord, new_order); + replace_order(ord, new_order); #endif free_order(new_order); @@ -1028,7 +1028,7 @@ create_ship(region * r, unit * u, const struct ship_type * newtype, int want, or #ifdef LASTORDER set_order(&u->lastorder, new_order); #else - copy_order(ord, new_order); + replace_order(ord, new_order); #endif free_order(new_order); diff --git a/src/common/kernel/magic.c b/src/common/kernel/magic.c index a27d4961c..45fb5528c 100644 --- a/src/common/kernel/magic.c +++ b/src/common/kernel/magic.c @@ -2004,7 +2004,7 @@ new_castorder(void *u, unit *u2, spell *sp, region *r, int lev, corder->force = force; corder->rt = r; corder->distance = range; - corder->order = duplicate_order(ord); + corder->order = copy_order(ord); corder->par = p; return corder; diff --git a/src/common/kernel/message.c b/src/common/kernel/message.c index 3223fbd9f..dd12b9f91 100644 --- a/src/common/kernel/message.c +++ b/src/common/kernel/message.c @@ -332,7 +332,7 @@ mistake(const unit * u, struct order * ord, const char *comment, int mtype) if (u->faction->no != MONSTER_FACTION) { char * cmt = strdup(comment); ADDMSG(&u->faction->msgs, msg_message("mistake", - "command error unit region", duplicate_order(ord), cmt, u, u->region)); + "command error unit region", copy_order(ord), cmt, u, u->region)); } } @@ -345,7 +345,7 @@ cmistake(const unit * u, struct order *ord, int mno, int mtype) if (u->faction->no == MONSTER_FACTION) return; sprintf(ebuf, "error%d", mno); ADDMSG(&u->faction->msgs, msg_message(ebuf, - "command unit region", duplicate_order(ord), u, u->region)); + "command unit region", copy_order(ord), u, u->region)); } extern unsigned int new_hashstring(const char* s); diff --git a/src/common/kernel/movement.c b/src/common/kernel/movement.c index 9de0fc0f5..024a89a66 100644 --- a/src/common/kernel/movement.c +++ b/src/common/kernel/movement.c @@ -914,7 +914,7 @@ cycle_route(order * ord, unit *u, int gereist) #ifdef LASTORDER set_order(&u->lastorder, norder); #else - copy_order(ord, norder); + replace_order(ord, norder); #endif free_order(norder); } diff --git a/src/common/kernel/order.c b/src/common/kernel/order.c index d78e5c8df..46b32dbdd 100644 --- a/src/common/kernel/order.c +++ b/src/common/kernel/order.c @@ -21,19 +21,40 @@ #include #include -static const struct locale * locale_array[16]; +typedef struct locale_data { + struct order_data * short_orders[MAXKEYWORDS]; + const struct locale * lang; +} locale_data; + +static struct locale_data * locale_array[16]; static int nlocales = 0; #undef SHORT_STRINGS -void -copy_order(order * dst, const order * src) +typedef struct order_data { + char * _str; + keyword_t _keyword; + int _lindex : 7; + int _refcount : 16; +} order_data; + +static void +release_data(order_data * data) { - if (dst->_str) free(dst->_str); - if (src->_str) dst->_str = strdup(src->_str); - else dst->_str = NULL; - dst->_keyword = src->_keyword; - dst->_lindex = src->_lindex; + if (data) { + if (--data->_refcount == 0) { + if (data->_str) free(data->_str); + free(data); + } + } +} + +void +replace_order(order * dst, const order * src) +{ + release_data(dst->data); + dst->data = src->data; + ++src->data->_refcount; dst->_persistent = src->_persistent; } @@ -43,7 +64,7 @@ get_keyword(const order * ord) if (ord==NULL) { return NOKEYWORD; } - return ord->_keyword; + return ord->data->_keyword; } char * @@ -52,39 +73,45 @@ getcommand(const order * ord) char sbuffer[DISPLAYSIZE*2]; char * str = sbuffer; - assert(ord->_lindexdata->_lindex_persistent) *str++ = '@'; #ifdef SHORT_STRINGS - if (ord->_keyword!=NOKEYWORD) { - const struct locale * lang = locale_array[ord->_lindex]; + if (ord->data->_keyword!=NOKEYWORD) { + const struct locale * lang = locale_array[ord->data->_lindex]->lang; - strcpy(str, LOC(lang, keywords[ord->_keyword])); + strcpy(str, LOC(lang, keywords[ord->data->_keyword])); str += strlen(str); - if (ord->_str) { + if (ord->data->_str) { *str++ = ' '; *str = 0; } } #endif - if (ord->_str) strcpy(str, ord->_str); + if (ord->data->_str) strcpy(str, ord->data->_str); return strdup(sbuffer); } void free_order(order * ord) { - if (ord!=NULL && --ord->_refcount==0) { - assert(ord->next==NULL); - if (ord->_str!=NULL) free(ord->_str); + if (ord!=NULL) { + release_data(ord->data); free(ord); } } order * -duplicate_order(order * ord) +copy_order(order * src) { - if (ord!=NULL) ++ord->_refcount; - return ord; + if (src!=NULL) { + order * ord = (order*)malloc(sizeof(order)); + ord->next = NULL; + ord->_persistent = src->_persistent; + ord->data = src->data; + ++ord->data->_refcount; + return ord; + } + return NULL; } void @@ -92,7 +119,7 @@ set_order(struct order ** destp, struct order * src) { if (*destp==src) return; free_order(*destp); - *destp = duplicate_order(src); + *destp = copy_order(src); } void @@ -126,6 +153,7 @@ parse_order(const char * s, const struct locale * lang) #endif sptr = s; kwd = findkeyword(parse_token(&sptr), lang); + while (isspace(*(unsigned char*)sptr)) ++sptr; /* if this is just nonsense, then we skip it. */ if (lomem) { @@ -138,30 +166,50 @@ parse_order(const char * s, const struct locale * lang) } } - ord = (order*)malloc(sizeof(order)); for (i=0;i!=nlocales;++i) { - if (locale_array[i]==lang) break; + if (locale_array[i]->lang==lang) break; } - if (i==nlocales) locale_array[nlocales++] = lang; - ord->_lindex = (unsigned char)i; - ord->_str = NULL; + if (i==nlocales) { + locale_array[nlocales] = (locale_data*)calloc(1, sizeof(locale_data)); + locale_array[nlocales]->lang = lang; + ++nlocales; + } + + ord = (order*)malloc(sizeof(order)); ord->_persistent = persistent; - ord->_refcount = 1; ord->next = NULL; - ord->_keyword = kwd; -#ifdef SHORT_STRINGS - if (ord->_keyword==NOKEYWORD) { - ord->_str = strdup(s); - } else { - while (isspace(*(unsigned char*)sptr)) ++sptr; - if (*sptr) { - ord->_str = strdup(sptr); + if (kwd!=NOKEYWORD && *sptr == 0) { + ord->data = locale_array[i]->short_orders[kwd]; + if (ord->data != NULL) { + ++ord->data->_refcount; } + } else { + ord->data = NULL; } + + if (ord->data==NULL) { + ord->data = (order_data*)malloc(sizeof(order_data)); + ord->data->_lindex = (unsigned char)i; + ord->data->_str = NULL; + ord->data->_refcount = 1; + ord->data->_keyword = kwd; + if (kwd!=NOKEYWORD && *sptr == 0) { + locale_array[i]->short_orders[kwd] = ord->data; + ++ord->data->_refcount; + } +#ifdef SHORT_STRINGS + if (ord->data->_keyword==NOKEYWORD) { + ord->data->_str = strdup(s); + } else { + if (*sptr) { + ord->data->_str = strdup(sptr); + } + } #else - ord->_str = strdup(s); + ord->data->_str = strdup(s); #endif + } return ord; } } @@ -169,10 +217,10 @@ parse_order(const char * s, const struct locale * lang) boolean is_repeated(const order * ord) { - const struct locale * lang = locale_array[ord->_lindex]; + const struct locale * lang = locale_array[ord->data->_lindex]->lang; param_t param; - switch (ord->_keyword) { + switch (ord->data->_keyword) { case K_CAST: case K_BUY: case K_SELL: @@ -229,10 +277,10 @@ is_repeated(const order * ord) boolean is_exclusive(const order * ord) { - const struct locale * lang = locale_array[ord->_lindex]; + const struct locale * lang = locale_array[ord->data->_lindex]->lang; param_t param; - switch (ord->_keyword) { + switch (ord->data->_keyword) { case K_MOVE: case K_WEREWOLF: /* these should not become persistent */ @@ -290,7 +338,7 @@ boolean is_persistent(const order * ord) { boolean persist = ord->_persistent!=0; - switch (ord->_keyword) { + switch (ord->data->_keyword) { case K_MOVE: case K_WEREWOLF: case NOKEYWORD: @@ -308,7 +356,7 @@ is_persistent(const order * ord) char * write_order(const order * ord, const struct locale * lang, char * buffer, size_t size) { - if (ord==0 || ord->_keyword==NOKEYWORD) { + if (ord==0 || ord->data->_keyword==NOKEYWORD) { buffer[0]=0; } else { char * s = getcommand(ord); diff --git a/src/common/kernel/order.h b/src/common/kernel/order.h index 91b0e762d..82dade651 100644 --- a/src/common/kernel/order.h +++ b/src/common/kernel/order.h @@ -25,22 +25,21 @@ extern "C" { * implemented yet) saving approx. 50% of all string-related memory. */ +struct order_data; + typedef struct order { struct order * next; /* do not access this data: */ - char * _str; - keyword_t _keyword; - int _lindex : 7; + struct order_data * data; int _persistent : 1; - int _refcount : 16; } order; /* constructor */ extern struct order * parse_order(const char * s, const struct locale * lang); -extern void copy_order(order * dst, const order * src); +extern void replace_order(order * dst, const order * src); /* reference counted copies of orders: */ -extern struct order * duplicate_order(struct order * ord); +extern struct order * copy_order(struct order * ord); extern void free_order(struct order * ord); extern void free_orders(struct order ** olist);