Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2004:
[Freeciv-Dev] Re: (PR#9640) RfP: help_items_iterate isn't reentrant
Home

[Freeciv-Dev] Re: (PR#9640) RfP: help_items_iterate isn't reentrant

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] Re: (PR#9640) RfP: help_items_iterate isn't reentrant
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 8 Aug 2004 23:34:02 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=9640 >

Jason Short wrote:
> <URL: http://rt.freeciv.org/Ticket/Display.html?id=9640 >
> 
> help_items_iterate isn't reentrant.  You can't embed one iteration 
> inside another.
> 
> This probably isn't a big deal, except that this iterator is global and 
> it should be very easy to fix it.  We should just make it a speclist...

Here's a patch.

This isn't necessarily much safer but it is simpler and 50 lines shorter.

Note there are two iterators.  help_items_iterate is used by lots of GUI 
code so I didn't want to rename it; it also uses the single global list 
for its iteration.  help_list_iterate is the classical form that's only 
used in one place.

jason

? diff
Index: client/civclient.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/civclient.c,v
retrieving revision 1.193
diff -u -r1.193 civclient.c
--- client/civclient.c  2 Aug 2004 23:19:35 -0000       1.193
+++ client/civclient.c  9 Aug 2004 06:31:32 -0000
@@ -49,7 +49,7 @@
 #include "diplodlg_g.h"
 #include "goto.h"
 #include "gui_main_g.h"
-#include "helpdata.h"          /* boot_help_texts() */
+#include "helpdata.h"          /* load_help_texts() */
 #include "mapctrl_g.h"
 #include "mapview_g.h"
 #include "menu_g.h"
@@ -232,7 +232,8 @@
      have cosmetic effects only (eg city name suggestions).  --dwp */
   mysrand(time(NULL));
 
-  boot_help_texts();
+  init_help_texts();
+  load_help_texts();
   if (!tilespec_read_toplevel(tileset_name)) {
     /* get tile sizes etc */
     exit(EXIT_FAILURE);
@@ -398,7 +399,7 @@
       precalc_tech_data();
       update_research(game.player_ptr);
       role_unit_precalcs();
-      boot_help_texts();       /* reboot */
+      load_help_texts();       /* reload */
       update_unit_focus();
     }
     else if (client_state == CLIENT_PRE_GAME_STATE) {
Index: client/helpdata.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.c,v
retrieving revision 1.70
diff -u -r1.70 helpdata.c
--- client/helpdata.c   8 May 2004 00:00:21 -0000       1.70
+++ client/helpdata.c   9 Aug 2004 06:31:32 -0000
@@ -47,49 +47,25 @@
 
 #define MAX_LAST (MAX(MAX(MAX(A_LAST,B_LAST),U_LAST),T_COUNT))
 
-#define SPECLIST_TAG help
-#define SPECLIST_TYPE struct help_item
-#include "speclist.h"
-
-#define help_list_iterate(helplist, phelp) \
-    TYPED_LIST_ITERATE(struct help_item, helplist, phelp)
-#define help_list_iterate_end  LIST_ITERATE_END
+#define help_list_iterate(helplist, pitem)                     \
+  TYPED_LIST_ITERATE(struct help_item, helplist, pitem)
+#define help_list_iterate_end LIST_ITERATE_END
 
-static struct genlist_link *help_nodes_iterator;
-static struct help_list help_nodes;
+struct help_list help_nodes;
 static bool help_nodes_init = FALSE;
-/* helpnodes_init is not quite the same as booted in boot_help_texts();
-   latter can be 0 even after call, eg if couldn't find helpdata.txt.
-*/
 
 char long_buffer[64000];
 
 /****************************************************************
-  Make sure help_nodes is initialised.
-  Should call this just about everywhere which uses help_nodes,
-  to be careful...  or at least where called by external
-  (non-static) functions.
-*****************************************************************/
-static void check_help_nodes_init(void)
-{
-  if (!help_nodes_init) {
-    help_list_init(&help_nodes);
-    help_nodes_init = TRUE;    /* before help_iter_start to avoid recursion! */
-    help_iter_start();
-  }
-}
-
-/****************************************************************
   Free all allocations associated with help_nodes.
 *****************************************************************/
 void free_help_texts(void)
 {
-  check_help_nodes_init();
-  help_list_iterate(help_nodes, ptmp) {
+  help_items_iterate(ptmp) {
     free(ptmp->topic);
     free(ptmp->text);
     free(ptmp);
-  } help_list_iterate_end;
+  } help_items_iterate_end;
   help_list_unlink_all(&help_nodes);
 }
 
@@ -171,12 +147,19 @@
 }
 
 /****************************************************************
-...
+  Initialize the help texts.
 *****************************************************************/
-void boot_help_texts(void)
+void init_help_texts(void)
 {
-  static bool booted = FALSE;
+  help_list_init(&help_nodes);
+  help_nodes_init = TRUE;
+}
 
+/****************************************************************
+...
+*****************************************************************/
+void load_help_texts(void)
+{
   struct section_file file, *sf = &file;
   char *filename;
   struct help_item *pitem;
@@ -184,18 +167,14 @@
   char **sec, **paras;
   int nsec, npara;
 
-  check_help_nodes_init();
-
   /* need to do something like this or bad things happen */
   popdown_help_dialog();
 
-  if(!booted) {
-    freelog(LOG_VERBOSE, "Booting help texts");
-  } else {
-    /* free memory allocated last time booted */
-    free_help_texts();
-    freelog(LOG_VERBOSE, "Rebooting help texts");
-  }    
+  assert(help_nodes_init);
+
+  /* free memory allocated last time loaded */
+  free_help_texts();
+  freelog(LOG_VERBOSE, "Rebooting help texts");
 
   filename = datafilename("helpdata.txt");
   if (!filename) {
@@ -217,9 +196,6 @@
     
     if (gen_str) {
       enum help_page_type current_type = HELP_ANY;
-      if (!booted) {
-       continue; /* on initial boot data tables are empty */
-      }
       for(i=2; help_type_names[i]; i++) {
        if(strcmp(gen_str, help_type_names[i])==0) {
          current_type = i;
@@ -352,7 +328,6 @@
   sec = NULL;
   section_file_check_unused(sf, sf->filename);
   section_file_free(sf);
-  booted = TRUE;
   freelog(LOG_VERBOSE, "Booted help texts ok");
 }
 
@@ -368,7 +343,6 @@
 *****************************************************************/
 int num_help_items(void)
 {
-  check_help_nodes_init();
   return help_list_size(&help_nodes);
 }
 
@@ -381,7 +355,6 @@
 {
   int size;
   
-  check_help_nodes_init();
   size = help_list_size(&help_nodes);
   if (pos < 0 || pos > size) {
     freelog(LOG_ERROR, "Bad index %d to get_help_item (size %d)", pos, size);
@@ -408,7 +381,6 @@
   static char vtopic[128];
   static char vtext[256];
 
-  check_help_nodes_init();
   idx = 0;
   help_list_iterate(help_nodes, ptmp) {
     char *p=ptmp->topic;
@@ -446,34 +418,6 @@
 }
 
 /****************************************************************
-  Start iterating through help items;
-  that is, reset iterator to start position.
-  (Could iterate using get_help_item(), but that would be
-  less efficient due to scanning to find pos.)
-*****************************************************************/
-void help_iter_start(void)
-{
-  check_help_nodes_init();
-  help_nodes_iterator = help_nodes.list.head_link;
-}
-
-/****************************************************************
-  Returns next help item; after help_iter_start(), this is
-  the first item.  At end, returns NULL.
-*****************************************************************/
-const struct help_item *help_iter_next(void)
-{
-  const struct help_item *pitem;
-  
-  check_help_nodes_init();
-  pitem = help_nodes_iterator->dataptr;
-  help_nodes_iterator = help_nodes_iterator->next;
-
-  return pitem;
-}
-
-
-/****************************************************************
   FIXME:
   All these helptext_* functions have a pretty crappy interface:
   we just write to buf and hope that its long enough.
Index: client/helpdata.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/helpdata.h,v
retrieving revision 1.7
diff -u -r1.7 helpdata.h
--- client/helpdata.h   28 Sep 2002 01:36:20 -0000      1.7
+++ client/helpdata.h   9 Aug 2004 06:31:32 -0000
@@ -20,7 +20,17 @@
   enum help_page_type type;
 };
 
-void boot_help_texts(void);
+/* Get 'struct help_item_list' and related functions: */
+#define SPECLIST_TAG help
+#define SPECLIST_TYPE struct help_item
+#include "speclist.h"
+
+#define help_items_iterate(pitem)                      \
+  TYPED_LIST_ITERATE(struct help_item, help_nodes, pitem)
+#define help_items_iterate_end LIST_ITERATE_END
+
+void init_help_texts(void);
+void load_help_texts(void);
 void free_help_texts(void);
 
 int num_help_items(void);
@@ -28,8 +38,6 @@
 const struct help_item *get_help_item_spec(const char *name,
                                           enum help_page_type htype,
                                           int *pos);
-void help_iter_start(void);
-const struct help_item *help_iter_next(void);
 
 void helptext_improvement(char *buf, int which, const char *user_text);
 void helptext_wonder(char *buf, int which, const char *user_text);
@@ -40,12 +48,7 @@
 
 char *helptext_unit_upkeep_str(int i);
 
-#define help_items_iterate(pitem) {       \
-        const struct help_item *pitem;    \
-        help_iter_start();                \
-        while((pitem=help_iter_next())) {   
-#define help_items_iterate_end }}
-
 extern char long_buffer[64000];
+extern struct help_list help_nodes;
 
 #endif  /* FC__HELPDATA_H */
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.393
diff -u -r1.393 packhand.c
--- client/packhand.c   2 Aug 2004 16:59:14 -0000       1.393
+++ client/packhand.c   9 Aug 2004 06:31:35 -0000
@@ -53,7 +53,7 @@
 #include "goto.h"               /* client_goto_init() */
 #include "graphics_g.h"
 #include "gui_main_g.h"
-#include "helpdata.h"          /* boot_help_texts() */
+#include "helpdata.h"          /* load_help_texts() */
 #include "inteldlg_g.h"
 #include "mapctrl_g.h"         /* popup_newcity_dialog() */
 #include "mapview_g.h"
@@ -1346,7 +1346,7 @@
 void handle_game_info(struct packet_game_info *pinfo)
 {
   int i;
-  bool boot_help, need_effect_update = FALSE;
+  bool load_help, need_effect_update = FALSE;
 
   game.gold=pinfo->gold;
   game.tech=pinfo->tech;
@@ -1403,7 +1403,7 @@
   game.unhappysize = pinfo->unhappysize;
   game.cityfactor = pinfo->cityfactor;
 
-  boot_help = (can_client_change_view()
+  load_help = (can_client_change_view()
               && game.spacerace != pinfo->spacerace);
   game.spacerace=pinfo->spacerace;
   if (game.timeout != 0) {
@@ -1411,8 +1411,8 @@
       seconds_to_turndone = pinfo->seconds_to_turndone;
   } else
     seconds_to_turndone = 0;
-  if (boot_help) {
-    boot_help_texts();         /* reboot, after setting game.spacerace */
+  if (load_help) {
+    load_help_texts();         /* reboot, after setting game.spacerace */
   }
 
   update_unit_focus();

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] Re: (PR#9640) RfP: help_items_iterate isn't reentrant, Jason Short <=