summaryrefslogtreecommitdiff
path: root/src/network/network_gamelist.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-01-20 03:44:43 +0000
committerrubidium <rubidium@openttd.org>2009-01-20 03:44:43 +0000
commit6a3aaef4868ed0812a569c1a048a6511dac80ba7 (patch)
tree9998eb5852e48d00ab69b2684a14c266b28117b4 /src/network/network_gamelist.cpp
parentbb770717494ec94d54edb4c1dd1f5a7a0c830ead (diff)
downloadopenttd-6a3aaef4868ed0812a569c1a048a6511dac80ba7.tar.xz
(svn r15159) -Fix: move the UDP queries that resolve a hostname into threads so they don't freeze OpenTTD when for example the network connection got severed. Thanks to glx for writing the mutex implementation for Windows.
Diffstat (limited to 'src/network/network_gamelist.cpp')
-rw-r--r--src/network/network_gamelist.cpp47
1 files changed, 45 insertions, 2 deletions
diff --git a/src/network/network_gamelist.cpp b/src/network/network_gamelist.cpp
index 235e9afe3..e50f5cc38 100644
--- a/src/network/network_gamelist.cpp
+++ b/src/network/network_gamelist.cpp
@@ -11,6 +11,8 @@
#include "../debug.h"
#include "../newgrf_config.h"
#include "../core/alloc_func.hpp"
+#include "../thread.h"
+#include "../string_func.h"
#include "network_internal.h"
#include "core/game.h"
#include "network_udp.h"
@@ -19,6 +21,46 @@
NetworkGameList *_network_game_list = NULL;
+ThreadMutex *_network_game_list_mutex = ThreadMutex::New();
+NetworkGameList *_network_game_delayed_insertion_list = NULL;
+
+/** Add a new item to the linked gamelist, but do it delayed in the next tick
+ * or so to prevent race conditions.
+ * @param item the item to add. Will be freed once added.
+ */
+void NetworkGameListAddItemDelayed(NetworkGameList *item)
+{
+ _network_game_list_mutex->BeginCritical();
+ item->next = _network_game_delayed_insertion_list;
+ _network_game_delayed_insertion_list = item;
+ _network_game_list_mutex->EndCritical();
+}
+
+/** Perform the delayed (thread safe) insertion into the game list */
+static void NetworkGameListHandleDelayedInsert()
+{
+ _network_game_list_mutex->BeginCritical();
+ while (_network_game_delayed_insertion_list != NULL) {
+ NetworkGameList *ins_item = _network_game_delayed_insertion_list;
+ _network_game_delayed_insertion_list = ins_item->next;
+
+ NetworkGameList *item = NetworkGameListAddItem(ins_item->ip, ins_item->port);
+
+ if (item != NULL) {
+ if (StrEmpty(item->info.server_name)) {
+ memset(&item->info, 0, sizeof(item->info));
+ strecpy(item->info.server_name, ins_item->info.server_name, lastof(item->info.server_name));
+ strecpy(item->info.hostname, ins_item->info.hostname, lastof(item->info.hostname));
+ item->online = false;
+ }
+ item->manually = ins_item->manually;
+ UpdateNetworkGameWindow(false);
+ }
+ free(ins_item);
+ }
+ _network_game_list_mutex->EndCritical();
+}
+
/** Add a new item to the linked gamelist. If the IP and Port match
* return the existing item instead of adding it again
* @param ip the IP-address (inet_addr) of the to-be added item
@@ -36,8 +78,7 @@ NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port)
prev_item = item;
}
- item = MallocT<NetworkGameList>(1);
- memset(item, 0, sizeof(*item));
+ item = CallocT<NetworkGameList>(1);
item->next = NULL;
item->ip = ip;
item->port = port;
@@ -91,6 +132,8 @@ enum {
/** Requeries the (game) servers we have not gotten a reply from */
void NetworkGameListRequery()
{
+ NetworkGameListHandleDelayedInsert();
+
static uint8 requery_cnt = 0;
if (++requery_cnt < REQUERY_EVERY_X_GAMELOOPS) return;