Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2006:
[Freeciv-Dev] Re: (PR#13351) Meta-ticket: AI and threads
Home

[Freeciv-Dev] Re: (PR#13351) Meta-ticket: AI and threads

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: per@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#13351) Meta-ticket: AI and threads
From: "Marko Lindqvist" <cazfi74@xxxxxxxxx>
Date: Wed, 12 Jul 2006 11:25:05 -0700
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=13351 >

Marko Lindqvist wrote:
> 
>   AI -thread is possible to make more gradually than AI -process. First 
> protect huge blocks of code by mutexes and then make protected portions 
> smaller and smaller. Of course, first versions would have no advantage 
> over single thread model but only thread overhead. Only one thread is 
> actually executing as other is waiting for mutex.

  I hacked together example implementation about initial version. Meant 
mainly to stir discussion.


  - ML

diff -Nurd -X.diff_ignore freeciv/ai/Makefile.am freeciv/ai/Makefile.am
--- freeciv/ai/Makefile.am      2006-07-12 20:26:06.941328200 +0300
+++ freeciv/ai/Makefile.am      2006-07-12 20:34:32.099174200 +0300
@@ -39,6 +39,8 @@
                aisettler.h     \
                aitech.c        \
                aitech.h        \
+               aithread.c      \
+               aithread.h      \
                aitools.c       \
                aitools.h       \
                aiunit.c        \
diff -Nurd -X.diff_ignore freeciv/ai/aithread.c freeciv/ai/aithread.c
--- freeciv/ai/aithread.c       1970-01-01 02:00:00.000000000 +0200
+++ freeciv/ai/aithread.c       2006-07-12 21:12:50.566594200 +0300
@@ -0,0 +1,73 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "fcthread.h"
+#include "log.h"
+
+#include "game.h"
+#include "unitlist.h"
+
+#include "aihand.h"
+#include "aisettler.h"
+#include "aithread.h"
+
+#include "plrhand.h"
+#include "sernet.h"
+#include "settlers.h"
+#include "srv_main.h"
+
+void *ai_thread_start(void *arg)
+{
+  int last_turn = -1;
+
+  while(server_state == RUN_GAME_STATE) {
+
+    fc_allocate_mutex(&game.ai_mutex_mutex);
+    fc_allocate_mutex(&game.ai_mega_mutex);
+    fc_release_mutex(&game.ai_mutex_mutex);
+
+    if (server_state == RUN_GAME_STATE
+        && last_turn != game.info.turn ) {
+      /* Sometimes we run two rounds before main thread
+       * grabs ai_mutex_mutex. */
+
+      /* AI end of turn activities */
+      players_iterate(pplayer) {
+        unit_list_iterate(pplayer->units, punit) {
+          punit->ai.hunted = 0;
+        } unit_list_iterate_end;
+      } players_iterate_end;
+
+      phase_players_iterate(pplayer) {
+        if (pplayer->ai.control) {
+          ai_settler_init(pplayer);
+        }
+        auto_settlers_player(pplayer);
+        if (pplayer->ai.control) {
+          ai_do_last_activities(pplayer);
+        }
+      } phase_players_iterate_end;
+
+      last_turn = game.info.turn;
+
+    }
+
+    fc_release_mutex(&game.ai_mega_mutex);
+  }
+
+  return NULL;
+}
diff -Nurd -X.diff_ignore freeciv/ai/aithread.h freeciv/ai/aithread.h
--- freeciv/ai/aithread.h       1970-01-01 02:00:00.000000000 +0200
+++ freeciv/ai/aithread.h       2006-07-12 20:34:32.130346200 +0300
@@ -0,0 +1,19 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifndef FC__AITHREAD_H
+#define FC__AITHREAD_H
+
+void *ai_thread_start(void *arg);
+
+#endif /* FC__AITHREAD_H */
diff -Nurd -X.diff_ignore freeciv/common/game.h freeciv/common/game.h
--- freeciv/common/game.h       2006-07-12 20:27:14.849530200 +0300
+++ freeciv/common/game.h       2006-07-12 20:34:32.145932200 +0300
@@ -19,6 +19,7 @@
 #include <sys/time.h>
 #endif
 
+#include "fcthread.h"
 #include "shared.h"
 #include "timing.h"
 
@@ -114,6 +115,9 @@
     /* Function to be called in game_remove_unit when a unit is deleted. */
     void (*unit_deallocate)(int unit_id);
   } callbacks;
+
+  fc_mutex ai_mega_mutex;
+  fc_mutex ai_mutex_mutex;
 };
 
 void game_init(void);
diff -Nurd -X.diff_ignore freeciv/server/srv_main.c freeciv/server/srv_main.c
--- freeciv/server/srv_main.c   2006-07-12 20:30:13.932670200 +0300
+++ freeciv/server/srv_main.c   2006-07-12 20:45:00.355248200 +0300
@@ -46,6 +46,7 @@
 
 #include "fciconv.h"
 #include "fcintl.h"
+#include "fcthread.h"
 #include "log.h"
 #include "mem.h"
 #include "netintf.h"
@@ -106,6 +107,7 @@
 #include "aidata.h"
 #include "aihand.h"
 #include "aisettler.h"
+#include "aithread.h"
 #include "citymap.h"
 
 #include "mapgen.h"
@@ -507,6 +509,7 @@
       flush_packets();                 /* AIs can be such spammers... */
     }
   } phase_players_iterate_end;
+
   kill_dying_players();
 }
 
@@ -677,21 +680,13 @@
   /* Freeze sending of cities. */
   nocity_send = TRUE;
 
-  /* AI end of turn activities */
-  players_iterate(pplayer) {
-    unit_list_iterate(pplayer->units, punit) {
-      punit->ai.hunted = 0;
-    } unit_list_iterate_end;
-  } players_iterate_end;
-  phase_players_iterate(pplayer) {
-    if (pplayer->ai.control) {
-      ai_settler_init(pplayer);
-    }
-    auto_settlers_player(pplayer);
-    if (pplayer->ai.control) {
-      ai_do_last_activities(pplayer);
-    }
-  } phase_players_iterate_end;
+  /* Give control to ai thread */
+  fc_release_mutex(&game.ai_mega_mutex);
+  fc_allocate_mutex(&game.ai_mutex_mutex);
+
+  /* Take control back */
+  fc_allocate_mutex(&game.ai_mega_mutex);
+  fc_release_mutex(&game.ai_mutex_mutex);
 
   /* Refresh cities */
   phase_players_iterate(pplayer) {
@@ -1764,8 +1759,12 @@
     exit(EXIT_FAILURE);
   }
 
+  fc_init_mutex(&game.ai_mega_mutex);
+  fc_init_mutex(&game.ai_mutex_mutex);
+
   /* Run server loop */
   while (TRUE) {
+
     srv_loop();
 
     /* Recalculate the scores in case of a spaceship victory */
@@ -1830,6 +1829,8 @@
 **************************************************************************/
 static void srv_loop(void)
 {
+  fc_thread ai_thread;
+
   init_available_nations();
 
   freelog(LOG_NORMAL, _("Now accepting new client connections."));
@@ -1955,10 +1956,16 @@
     init_new_game();
   }
 
+  fc_allocate_mutex(&game.ai_mega_mutex);
+  fc_thread_start(&ai_thread, ai_thread_start, NULL);
+
   send_game_state(game.est_connections, CLIENT_GAME_RUNNING_STATE);
 
   /*** Where the action is. ***/
   main_loop();
+
+  fc_release_mutex(&game.ai_mega_mutex);
+  fc_thread_wait(&ai_thread);
 }
 
 /**************************************************************************
diff -Nurd -X.diff_ignore freeciv/utility/Makefile.am 
freeciv/utility/Makefile.am
--- freeciv/utility/Makefile.am 2006-07-12 21:18:33.832658200 +0300
+++ freeciv/utility/Makefile.am 2006-07-12 21:19:04.724110200 +0300
@@ -19,6 +19,8 @@
                distribute.h    \
                fcintl.c        \
                fcintl.h        \
+               fcthread.c      \
+               fcthread.h      \
                genlist.c       \
                genlist.h       \
                hash.c          \
diff -Nurd -X.diff_ignore freeciv/utility/fcthread.c freeciv/utility/fcthread.c
--- freeciv/utility/fcthread.c  1970-01-01 02:00:00.000000000 +0200
+++ freeciv/utility/fcthread.c  2006-07-12 20:34:32.270620200 +0300
@@ -0,0 +1,61 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "fcthread.h"
+
+/**********************************************************************
+  Create new thread
+***********************************************************************/
+int fc_thread_start(fc_thread *thread, void *(*function) (void *arg), void 
*arg)
+{
+  return pthread_create(thread, NULL, function, arg);
+}
+
+/**********************************************************************
+  Wait for thread to finish
+***********************************************************************/
+void *fc_thread_wait(fc_thread *thread)
+{
+  void **return_value = NULL;
+
+  pthread_join(*thread, return_value);
+  return *return_value;
+}
+
+/**********************************************************************
+  Initialize mutex
+***********************************************************************/
+void fc_init_mutex(fc_mutex *mutex)
+{
+  *mutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+/**********************************************************************
+  Lock mutex
+***********************************************************************/
+void fc_allocate_mutex(fc_mutex *mutex)
+{
+  pthread_mutex_lock(mutex);
+}
+
+/**********************************************************************
+  Release mutex
+***********************************************************************/
+void fc_release_mutex(fc_mutex *mutex)
+{
+  pthread_mutex_unlock(mutex);
+}
diff -Nurd -X.diff_ignore freeciv/utility/fcthread.h freeciv/utility/fcthread.h
--- freeciv/utility/fcthread.h  1970-01-01 02:00:00.000000000 +0200
+++ freeciv/utility/fcthread.h  2006-07-12 20:34:32.286206200 +0300
@@ -0,0 +1,29 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifndef FC__THREAD_H
+#define FC__THREAD_H
+
+#include <pthread.h>
+
+#define fc_thread pthread_t
+#define fc_mutex  pthread_mutex_t
+
+int fc_thread_start(fc_thread *thread, void *(*function) (void *arg), void 
*arg);
+void *fc_thread_wait(fc_thread *thread);
+
+void fc_init_mutex(fc_mutex *mutex);
+void fc_allocate_mutex(fc_mutex *mutex);
+void fc_release_mutex(fc_mutex *mutex);
+
+#endif /* FC__THREAD_H */

[Prev in Thread] Current Thread [Next in Thread]