Freeciv-3.1
Loading...
Searching...
No Matches
taiplayer.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18/* utility */
19#include "log.h"
20
21/* common */
22#include "ai.h"
23#include "city.h"
24#include "game.h"
25#include "unit.h"
26
27/* server/advisors */
28#include "infracache.h"
29
30/* ai/default */
31#include "aiplayer.h"
32
33/* ai/threaded */
34#include "taicity.h"
35
36#include "taiplayer.h"
37
38/* What level of operation we should abort because
39 * of received messages. Lower is more critical;
40 * TAI_ABORT_EXIT means that whole thread should exit,
41 * TAI_ABORT_NONE means that we can continue what we were doing */
48
49static enum tai_abort_msg_class tai_check_messages(struct ai_type *ait);
50
59
60/**********************************************************************/
64{
66
68}
69
70/**********************************************************************/
73static void tai_thread_start(void *arg)
74{
75 bool finished = FALSE;
76 struct ai_type *ait = arg;
77
78 log_debug("New AI thread launched");
79
80 /* Just wait until we are signaled to shutdown */
82 while (!finished) {
84
86 finished = TRUE;
87 }
88 }
90
91 log_debug("AI thread exiting");
92}
93
94/**********************************************************************/
98{
99 enum tai_abort_msg_class ret_abort= TAI_ABORT_NONE;
100
101 taimsg_list_allocate_mutex(thrai.msgs_to.msglist);
102 while (taimsg_list_size(thrai.msgs_to.msglist) > 0) {
103 struct tai_msg *msg;
104 enum tai_abort_msg_class new_abort = TAI_ABORT_NONE;
105
106 msg = taimsg_list_get(thrai.msgs_to.msglist, 0);
107 taimsg_list_remove(thrai.msgs_to.msglist, msg);
108 taimsg_list_release_mutex(thrai.msgs_to.msglist);
109
110 log_debug("Plr thr got %s", taimsgtype_name(msg->type));
111
112 switch (msg->type) {
113 case TAI_MSG_FIRST_ACTIVITIES:
115
117
118 /* Use _safe iterate in case the main thread
119 * destroyes cities while we are iterating through these. */
120 city_list_iterate_safe(msg->plr->cities, pcity) {
121 tai_city_worker_requests_create(ait, msg->plr, pcity);
122
123 /* Release mutex for a second in case main thread
124 * wants to do something to city list. */
126
127 /* Recursive message check in case phase is finished. */
128 new_abort = tai_check_messages(ait);
130 if (new_abort < TAI_ABORT_NONE) {
131 break;
132 }
135
136 tai_send_req(TAI_REQ_TURN_DONE, msg->plr, NULL);
137
138 break;
139 case TAI_MSG_PHASE_FINISHED:
140 new_abort = TAI_ABORT_PHASE_END;
141 break;
142 case TAI_MSG_THR_EXIT:
143 new_abort = TAI_ABORT_EXIT;
144 break;
145 default:
146 log_error("Illegal message type %s (%d) for threaded ai!",
147 taimsgtype_name(msg->type), msg->type);
148 break;
149 }
150
151 if (new_abort < ret_abort) {
152 ret_abort = new_abort;
153 }
154
155 FC_FREE(msg);
156
157 taimsg_list_allocate_mutex(thrai.msgs_to.msglist);
158 }
159 taimsg_list_release_mutex(thrai.msgs_to.msglist);
160
161 return ret_abort;
162}
163
164/**********************************************************************/
167void tai_player_alloc(struct ai_type *ait, struct player *pplayer)
168{
169 struct tai_plr *player_data = fc_calloc(1, sizeof(struct tai_plr));
170
171 player_set_ai_data(pplayer, ait, player_data);
172
173 /* Default AI */
174 dai_data_init(ait, pplayer);
175}
176
177/**********************************************************************/
180void tai_player_free(struct ai_type *ait, struct player *pplayer)
181{
182 struct tai_plr *player_data = player_ai_data(pplayer, ait);
183
184 /* Default AI */
185 dai_data_close(ait, pplayer);
186
187 if (player_data != NULL) {
188 player_set_ai_data(pplayer, ait, NULL);
189 FC_FREE(player_data);
190 }
191}
192
193/**********************************************************************/
196void tai_control_gained(struct ai_type *ait, struct player *pplayer)
197{
199
200 log_debug("%s now under threaded AI (%d)", pplayer->name, thrai.num_players);
201
202 if (!thrai.thread_running) {
203 thrai.msgs_to.msglist = taimsg_list_new();
204 thrai.reqs_from.reqlist = taireq_list_new();
205
207
211 }
212}
213
214/**********************************************************************/
217void tai_control_lost(struct ai_type *ait, struct player *pplayer)
218{
220
221 log_debug("%s no longer under threaded AI (%d)", pplayer->name, thrai.num_players);
222
223 if (thrai.num_players <= 0) {
224 tai_send_msg(TAI_MSG_THR_EXIT, pplayer, NULL);
225
228
231 taimsg_list_destroy(thrai.msgs_to.msglist);
232 taireq_list_destroy(thrai.reqs_from.reqlist);
233 }
234}
235
236/**********************************************************************/
239void tai_refresh(struct ai_type *ait, struct player *pplayer)
240{
241 if (thrai.thread_running) {
242 taireq_list_allocate_mutex(thrai.reqs_from.reqlist);
243 while (taireq_list_size(thrai.reqs_from.reqlist) > 0) {
244 struct tai_req *req;
245
246 req = taireq_list_get(thrai.reqs_from.reqlist, 0);
247 taireq_list_remove(thrai.reqs_from.reqlist, req);
248
249 taireq_list_release_mutex(thrai.reqs_from.reqlist);
250
251 log_debug("Plr thr sent %s", taireqtype_name(req->type));
252
253 switch (req->type) {
254 case TAI_REQ_WORKER_TASK:
256 break;
257 case TAI_REQ_TURN_DONE:
258 req->plr->ai_phase_done = TRUE;
259 break;
260 }
261
262 FC_FREE(req);
263
264 taireq_list_allocate_mutex(thrai.reqs_from.reqlist);
265 }
266 taireq_list_release_mutex(thrai.reqs_from.reqlist);
267 }
268}
269
270/**********************************************************************/
281
282/**********************************************************************/
285void tai_req_from_thr(struct tai_req *req)
286{
287 taireq_list_allocate_mutex(thrai.reqs_from.reqlist);
288 taireq_list_append(thrai.reqs_from.reqlist, req);
289 taireq_list_release_mutex(thrai.reqs_from.reqlist);
290}
291
292/**********************************************************************/
296{
297 return thrai.thread_running;
298}
void dai_data_init(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:59
void dai_data_close(struct ai_type *ait, struct player *pplayer)
Definition aidata.c:104
#define city_list_iterate_safe(citylist, _city)
Definition city.h:502
#define city_list_iterate_safe_end
Definition city.h:524
void fc_thread_cond_destroy(fc_thread_cond *cond)
Definition fcthread.c:385
void fc_thread_cond_signal(fc_thread_cond *cond)
Definition fcthread.c:397
void fc_thread_cond_wait(fc_thread_cond *cond, fc_mutex *mutex)
Definition fcthread.c:391
void fc_thread_cond_init(fc_thread_cond *cond)
Definition fcthread.c:379
int fc_thread_start(fc_thread *thread, void(*function)(void *arg), void *arg)
void fc_allocate_mutex(fc_mutex *mutex)
void fc_release_mutex(fc_mutex *mutex)
void fc_thread_wait(fc_thread *thread)
void fc_destroy_mutex(fc_mutex *mutex)
void fc_init_mutex(fc_mutex *mutex)
struct civ_game game
Definition game.c:57
void initialize_infrastructure_cache(struct player *pplayer)
Definition infracache.c:250
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
void * player_ai_data(const struct player *pplayer, const struct ai_type *ai)
Definition player.c:1904
void player_set_ai_data(struct player *pplayer, const struct ai_type *ai, void *data)
Definition player.c:1912
Definition ai.h:50
struct civ_game::@30::@34 server
fc_mutex city_list
Definition game.h:267
struct civ_game::@30::@34::@38 mutexes
struct city_list * cities
Definition player.h:281
char name[MAX_LEN_NAME]
Definition player.h:251
bool ai_phase_done
Definition player.h:264
struct player * plr
Definition taimsg.h:35
enum taimsgtype type
Definition taimsg.h:34
fc_mutex mutex
Definition taiplayer.h:33
fc_thread_cond thr_cond
Definition taiplayer.h:32
struct taimsg_list * msglist
Definition taiplayer.h:34
struct player * plr
Definition taimsg.h:42
enum taireqtype type
Definition taimsg.h:41
struct taireq_list * reqlist
Definition taiplayer.h:39
bool thread_running
Definition taiplayer.c:56
int num_players
Definition taiplayer.c:53
struct tai_msgs msgs_to
Definition taiplayer.c:54
fc_thread ait
Definition taiplayer.c:57
struct tai_reqs reqs_from
Definition taiplayer.c:55
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
void tai_city_worker_requests_create(struct ai_type *ait, struct player *pplayer, struct city *pcity)
Definition taicity.c:65
void tai_req_worker_task_rcv(struct tai_req *req)
Definition taicity.c:478
void tai_send_req(enum taireqtype type, struct player *pplayer, void *data)
Definition taimsg.c:48
void tai_send_msg(enum taimsgtype type, struct player *pplayer, void *data)
Definition taimsg.c:26
void tai_msg_to_thr(struct tai_msg *msg)
Definition taiplayer.c:274
bool tai_thread_running(void)
Definition taiplayer.c:295
void tai_control_gained(struct ai_type *ait, struct player *pplayer)
Definition taiplayer.c:196
void tai_control_lost(struct ai_type *ait, struct player *pplayer)
Definition taiplayer.c:217
void tai_player_alloc(struct ai_type *ait, struct player *pplayer)
Definition taiplayer.c:167
tai_abort_msg_class
Definition taiplayer.c:43
@ TAI_ABORT_NONE
Definition taiplayer.c:46
@ TAI_ABORT_PHASE_END
Definition taiplayer.c:45
@ TAI_ABORT_EXIT
Definition taiplayer.c:44
void tai_player_free(struct ai_type *ait, struct player *pplayer)
Definition taiplayer.c:180
void tai_init_threading(void)
Definition taiplayer.c:63
void tai_req_from_thr(struct tai_req *req)
Definition taiplayer.c:285
void tai_refresh(struct ai_type *ait, struct player *pplayer)
Definition taiplayer.c:239
static enum tai_abort_msg_class tai_check_messages(struct ai_type *ait)
Definition taiplayer.c:97
static void tai_thread_start(void *arg)
Definition taiplayer.c:73
struct tai_thr thrai