Reference-counting in Befehlen. Derzeit nur für Befehle ohne Parameter.

This commit is contained in:
Enno Rehling 2005-05-09 19:57:44 +00:00
parent 43f7c7413c
commit c755cf39f2
9 changed files with 105 additions and 58 deletions

View File

@ -3450,7 +3450,7 @@ setdefaults (void)
} }
#ifdef LASTORDER #ifdef LASTORDER
/* by default the default long order becomes the new long order. */ /* by default the default long order becomes the new long order. */
u->thisorder = duplicate_order(u->lastorder); u->thisorder = copy_order(u->lastorder);
#endif #endif
/* check all orders for a potential new long order this round: */ /* check all orders for a potential new long order this round: */
for (ord = u->orders; ord; ord = ord->next) { for (ord = u->orders; ord; ord = ord->next) {

View File

@ -3780,7 +3780,7 @@ report_init(void)
add_function("spell", &eval_spell); add_function("spell", &eval_spell);
register_argtype("string", free, (void*(*)(void*))strdup); 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_neighbours, "view_neighbours");
register_function((pf_generic)view_regatta, "view_regatta"); register_function((pf_generic)view_regatta, "view_regatta");
} }

View File

@ -427,7 +427,7 @@ teach(unit * u, struct order * ord)
#ifdef LASTORDER #ifdef LASTORDER
set_order(&u->lastorder, new_order); set_order(&u->lastorder, new_order);
#else #else
copy_order(ord, new_order); replace_order(ord, new_order);
#endif #endif
free_order(new_order); /* parse_order & set_order have each increased the refcount */ free_order(new_order); /* parse_order & set_order have each increased the refcount */
} }

View File

@ -934,7 +934,7 @@ build_building(unit * u, const building_type * btype, int want, order * ord)
#ifdef LASTORDER #ifdef LASTORDER
set_order(&u->lastorder, new_order); set_order(&u->lastorder, new_order);
#else #else
copy_order(ord, new_order); replace_order(ord, new_order);
#endif #endif
free_order(new_order); free_order(new_order);
@ -1028,7 +1028,7 @@ create_ship(region * r, unit * u, const struct ship_type * newtype, int want, or
#ifdef LASTORDER #ifdef LASTORDER
set_order(&u->lastorder, new_order); set_order(&u->lastorder, new_order);
#else #else
copy_order(ord, new_order); replace_order(ord, new_order);
#endif #endif
free_order(new_order); free_order(new_order);

View File

@ -2004,7 +2004,7 @@ new_castorder(void *u, unit *u2, spell *sp, region *r, int lev,
corder->force = force; corder->force = force;
corder->rt = r; corder->rt = r;
corder->distance = range; corder->distance = range;
corder->order = duplicate_order(ord); corder->order = copy_order(ord);
corder->par = p; corder->par = p;
return corder; return corder;

View File

@ -332,7 +332,7 @@ mistake(const unit * u, struct order * ord, const char *comment, int mtype)
if (u->faction->no != MONSTER_FACTION) { if (u->faction->no != MONSTER_FACTION) {
char * cmt = strdup(comment); char * cmt = strdup(comment);
ADDMSG(&u->faction->msgs, msg_message("mistake", 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; if (u->faction->no == MONSTER_FACTION) return;
sprintf(ebuf, "error%d", mno); sprintf(ebuf, "error%d", mno);
ADDMSG(&u->faction->msgs, msg_message(ebuf, 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); extern unsigned int new_hashstring(const char* s);

View File

@ -914,7 +914,7 @@ cycle_route(order * ord, unit *u, int gereist)
#ifdef LASTORDER #ifdef LASTORDER
set_order(&u->lastorder, norder); set_order(&u->lastorder, norder);
#else #else
copy_order(ord, norder); replace_order(ord, norder);
#endif #endif
free_order(norder); free_order(norder);
} }

View File

@ -21,19 +21,40 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
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; static int nlocales = 0;
#undef SHORT_STRINGS #undef SHORT_STRINGS
void typedef struct order_data {
copy_order(order * dst, const order * src) 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 (data) {
if (src->_str) dst->_str = strdup(src->_str); if (--data->_refcount == 0) {
else dst->_str = NULL; if (data->_str) free(data->_str);
dst->_keyword = src->_keyword; free(data);
dst->_lindex = src->_lindex; }
}
}
void
replace_order(order * dst, const order * src)
{
release_data(dst->data);
dst->data = src->data;
++src->data->_refcount;
dst->_persistent = src->_persistent; dst->_persistent = src->_persistent;
} }
@ -43,7 +64,7 @@ get_keyword(const order * ord)
if (ord==NULL) { if (ord==NULL) {
return NOKEYWORD; return NOKEYWORD;
} }
return ord->_keyword; return ord->data->_keyword;
} }
char * char *
@ -52,39 +73,45 @@ getcommand(const order * ord)
char sbuffer[DISPLAYSIZE*2]; char sbuffer[DISPLAYSIZE*2];
char * str = sbuffer; char * str = sbuffer;
assert(ord->_lindex<nlocales); assert(ord->data->_lindex<nlocales);
if (ord->_persistent) *str++ = '@'; if (ord->_persistent) *str++ = '@';
#ifdef SHORT_STRINGS #ifdef SHORT_STRINGS
if (ord->_keyword!=NOKEYWORD) { if (ord->data->_keyword!=NOKEYWORD) {
const struct locale * lang = locale_array[ord->_lindex]; 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); str += strlen(str);
if (ord->_str) { if (ord->data->_str) {
*str++ = ' '; *str++ = ' ';
*str = 0; *str = 0;
} }
} }
#endif #endif
if (ord->_str) strcpy(str, ord->_str); if (ord->data->_str) strcpy(str, ord->data->_str);
return strdup(sbuffer); return strdup(sbuffer);
} }
void void
free_order(order * ord) free_order(order * ord)
{ {
if (ord!=NULL && --ord->_refcount==0) { if (ord!=NULL) {
assert(ord->next==NULL); release_data(ord->data);
if (ord->_str!=NULL) free(ord->_str);
free(ord); free(ord);
} }
} }
order * order *
duplicate_order(order * ord) copy_order(order * src)
{ {
if (ord!=NULL) ++ord->_refcount; if (src!=NULL) {
return ord; 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 void
@ -92,7 +119,7 @@ set_order(struct order ** destp, struct order * src)
{ {
if (*destp==src) return; if (*destp==src) return;
free_order(*destp); free_order(*destp);
*destp = duplicate_order(src); *destp = copy_order(src);
} }
void void
@ -126,6 +153,7 @@ parse_order(const char * s, const struct locale * lang)
#endif #endif
sptr = s; sptr = s;
kwd = findkeyword(parse_token(&sptr), lang); kwd = findkeyword(parse_token(&sptr), lang);
while (isspace(*(unsigned char*)sptr)) ++sptr;
/* if this is just nonsense, then we skip it. */ /* if this is just nonsense, then we skip it. */
if (lomem) { 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) { 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; if (i==nlocales) {
ord->_lindex = (unsigned char)i; locale_array[nlocales] = (locale_data*)calloc(1, sizeof(locale_data));
ord->_str = NULL; locale_array[nlocales]->lang = lang;
++nlocales;
}
ord = (order*)malloc(sizeof(order));
ord->_persistent = persistent; ord->_persistent = persistent;
ord->_refcount = 1;
ord->next = NULL; ord->next = NULL;
ord->_keyword = kwd; if (kwd!=NOKEYWORD && *sptr == 0) {
#ifdef SHORT_STRINGS ord->data = locale_array[i]->short_orders[kwd];
if (ord->_keyword==NOKEYWORD) { if (ord->data != NULL) {
ord->_str = strdup(s); ++ord->data->_refcount;
} else {
while (isspace(*(unsigned char*)sptr)) ++sptr;
if (*sptr) {
ord->_str = strdup(sptr);
} }
} 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 #else
ord->_str = strdup(s); ord->data->_str = strdup(s);
#endif #endif
}
return ord; return ord;
} }
} }
@ -169,10 +217,10 @@ parse_order(const char * s, const struct locale * lang)
boolean boolean
is_repeated(const order * ord) 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; param_t param;
switch (ord->_keyword) { switch (ord->data->_keyword) {
case K_CAST: case K_CAST:
case K_BUY: case K_BUY:
case K_SELL: case K_SELL:
@ -229,10 +277,10 @@ is_repeated(const order * ord)
boolean boolean
is_exclusive(const order * ord) 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; param_t param;
switch (ord->_keyword) { switch (ord->data->_keyword) {
case K_MOVE: case K_MOVE:
case K_WEREWOLF: case K_WEREWOLF:
/* these should not become persistent */ /* these should not become persistent */
@ -290,7 +338,7 @@ boolean
is_persistent(const order * ord) is_persistent(const order * ord)
{ {
boolean persist = ord->_persistent!=0; boolean persist = ord->_persistent!=0;
switch (ord->_keyword) { switch (ord->data->_keyword) {
case K_MOVE: case K_MOVE:
case K_WEREWOLF: case K_WEREWOLF:
case NOKEYWORD: case NOKEYWORD:
@ -308,7 +356,7 @@ is_persistent(const order * ord)
char * char *
write_order(const order * ord, const struct locale * lang, char * buffer, size_t size) 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; buffer[0]=0;
} else { } else {
char * s = getcommand(ord); char * s = getcommand(ord);

View File

@ -25,22 +25,21 @@ extern "C" {
* implemented yet) saving approx. 50% of all string-related memory. * implemented yet) saving approx. 50% of all string-related memory.
*/ */
struct order_data;
typedef struct order { typedef struct order {
struct order * next; struct order * next;
/* do not access this data: */ /* do not access this data: */
char * _str; struct order_data * data;
keyword_t _keyword;
int _lindex : 7;
int _persistent : 1; int _persistent : 1;
int _refcount : 16;
} order; } order;
/* constructor */ /* constructor */
extern struct order * parse_order(const char * s, const struct locale * lang); 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: */ /* 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_order(struct order * ord);
extern void free_orders(struct order ** olist); extern void free_orders(struct order ** olist);