Author: grzywacz
Date: Wed Feb  4 22:48:16 2009
New Revision: 32608

URL: http://svn.gna.org/viewcvs/wesnoth?rev=32608&view=rev
Log:
Optimized handling of friends/ignores lists.

These are now backed by a set, instead of doing string operations on
preferences. This resolves the problem of very high CPU usage
in multiplayer lobby when friend/ignore lists are long.

Added:
    trunk/src/tests/test_serialization.cpp
Modified:
    trunk/src/CMakeLists.txt
    trunk/src/Makefile.am
    trunk/src/SConscript
    trunk/src/game_preferences.cpp
    trunk/src/game_preferences.hpp
    trunk/src/game_preferences_display.cpp
    trunk/src/menu_events.cpp
    trunk/src/serialization/string_utils.cpp
    trunk/src/serialization/string_utils.hpp

Modified: trunk/src/CMakeLists.txt
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/CMakeLists.txt?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/CMakeLists.txt (original)
+++ trunk/src/CMakeLists.txt Wed Feb  4 22:48:16 2009
@@ -476,6 +476,7 @@
     tests/test_policy.cpp
        tests/test_team.cpp
     tests/test_util.cpp
+    tests/test_serialization.cpp
     tests/test_version.cpp
        tests/gui/test_save_dialog.cpp
        tests/gui/test_drop_target.cpp

Modified: trunk/src/Makefile.am
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/Makefile.am?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Wed Feb  4 22:48:16 2009
@@ -289,6 +289,7 @@
        tests/test_policy.cpp \
        tests/test_team.cpp \
        tests/test_util.cpp \
+       tests/test_serialization.cpp \
        tests/test_version.cpp \
        tests/gui/test_save_dialog.cpp \
        tests/gui/test_drop_target.cpp \

Modified: trunk/src/SConscript
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/SConscript?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/SConscript (original)
+++ trunk/src/SConscript Wed Feb  4 22:48:16 2009
@@ -371,6 +371,7 @@
     tests/test_policy.cpp
     tests/test_team.cpp
     tests/test_util.cpp
+    tests/test_serialization.cpp
     tests/test_version.cpp
     tests/gui/test_drop_target.cpp
     tests/gui/test_save_dialog.cpp

Modified: trunk/src/game_preferences.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_preferences.cpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/game_preferences.cpp (original)
+++ trunk/src/game_preferences.cpp Wed Feb  4 22:48:16 2009
@@ -39,19 +39,10 @@
 std::map<std::string, std::vector<std::string> > history_map;
 const unsigned max_history_saved = 50;
 
-/** Add a nick to the specified relation setting. */
-void add_relation(const std::string& nick, const std::string& relation) {
-       std::vector<std::string> r = utils::split(preferences::get(relation));
-       r.push_back(nick);
-       preferences::set(relation, utils::join(r));
-}
-
-/** Remove a nick from the specified relation setting. */
-void remove_relation(const std::string& nick, const std::string& relation) {
-       std::vector<std::string> r = utils::split(preferences::get(relation));
-       r.erase(std::remove(r.begin(), r.end(), nick), r.end());
-       preferences::set(relation, utils::join(r));
-}
+std::set<std::string> friends;
+std::set<std::string> ignores;
+bool friends_initialized = false;
+bool ignores_initialized = false;
 
 } // anon namespace
 
@@ -149,32 +140,58 @@
        set_ping_timeout(network::ping_timeout);
 }
 
-std::string get_friends() {
-       return preferences::get("friends");
-}
-
-std::string get_ignores() {
-       return preferences::get("ignores");
+const std::set<std::string> & get_friends() {
+       if(!friends_initialized) {
+               std::vector<std::string> names = 
utils::split(preferences::get("friends"));
+               std::set<std::string> tmp(names.begin(), names.end());
+               friends.swap(tmp);
+
+               friends_initialized = true;
+       }
+
+       return friends;
+}
+
+const std::set<std::string> & get_ignores() {
+       if(!ignores_initialized) {
+               std::vector<std::string> names = 
utils::split(preferences::get("ignores"));
+               std::set<std::string> tmp(names.begin(), names.end());
+               ignores.swap(tmp);
+
+               ignores_initialized = true;
+       }
+
+       return ignores;
 }
 
 bool add_friend(const std::string& nick) {
        if (!utils::isvalid_wildcard(nick)) return false;
-       add_relation(nick, "friends");
+       friends.insert(nick);
+       preferences::set("friends", utils::join(friends));
        return true;
 }
 
 bool add_ignore(const std::string& nick) {
        if (!utils::isvalid_wildcard(nick)) return false;
-       add_relation(nick, "ignores");
+       ignores.insert(nick);
+       preferences::set("ignores", utils::join(ignores));
        return true;
 }
 
 void remove_friend(const std::string& nick) {
-       remove_relation(nick, "friends");
+       std::set<std::string>::iterator i = friends.find(nick);
+       if(i != friends.end()) {
+               friends.erase(i);
+               preferences::set("friends", utils::join(friends));
+       }
 }
 
 void remove_ignore(const std::string& nick) {
-       remove_relation(nick, "ignores");
+       std::set<std::string>::iterator i = ignores.find(nick);
+       if(i != ignores.end()) {
+               ignores.erase(i);
+               preferences::set("ignores", utils::join(ignores));
+       }
 }
 
 void clear_friends() {
@@ -186,21 +203,11 @@
 }
 
 bool is_friend(const std::string& nick) {
-       const std::vector<std::string>& friends = utils::split(get_friends());
-    foreach(const std::string& var, friends) {
-        if(utils::wildcard_string_match(nick, var))
-            return true;
-    }
-    return false;
+       return friends.find(nick) != friends.end();
 }
 
 bool is_ignored(const std::string& nick) {
-       const std::vector<std::string>& ignores = utils::split(get_ignores());
-    foreach(const std::string& var, ignores) {
-        if(utils::wildcard_string_match(nick, var))
-            return true;
-    }
-    return false;
+       return ignores.find(nick) != ignores.end();
 }
 
 bool show_lobby_join(const std::string& sender, const std::string& message) {

Modified: trunk/src/game_preferences.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_preferences.hpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/game_preferences.hpp (original)
+++ trunk/src/game_preferences.hpp Wed Feb  4 22:48:16 2009
@@ -42,8 +42,8 @@
        void _set_lobby_joins(int show);
        enum { SHOW_NONE, SHOW_FRIENDS, SHOW_ALL };
 
-       std::string get_friends();
-       std::string get_ignores();
+       const std::set<std::string> & get_friends();
+       const std::set<std::string> & get_ignores();
        bool add_friend(const std::string& nick);
        bool add_ignore(const std::string& nick);
        void remove_friend(const std::string& nick);

Modified: trunk/src/game_preferences_display.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/game_preferences_display.cpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/game_preferences_display.cpp (original)
+++ trunk/src/game_preferences_display.cpp Wed Feb  4 22:48:16 2009
@@ -993,12 +993,14 @@
 
 void preferences_dialog::set_friends_menu()
 {
-       const std::vector<std::string>& friends = 
utils::split(preferences::get_friends());
-       const std::vector<std::string>& ignores = 
utils::split(preferences::get_ignores());
+       const std::set<std::string>& friends = preferences::get_friends();
+       const std::set<std::string>& ignores = preferences::get_ignores();
+
        std::vector<std::string> friends_items;
        std::vector<std::string> friends_names;
        std::string const imgpre = IMAGE_PREFIX + std::string("misc/status-");
-       std::vector<std::string>::const_iterator i;
+
+       std::set<std::string>::const_iterator i;
        for (i = friends.begin(); i != friends.end(); ++i)
        {
                friends_items.push_back(imgpre + "friend.png" + COLUMN_SEPARATOR

Modified: trunk/src/menu_events.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/menu_events.cpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/menu_events.cpp (original)
+++ trunk/src/menu_events.cpp Wed Feb  4 22:48:16 2009
@@ -2449,14 +2449,17 @@
                chat_command_handler cch(*this, allies_only);
                cch.dispatch(cmd);
        }
+
        void chat_command_handler::do_emote()
        {
                chat_handler_.send_chat_message("/me " + get_data(), 
allies_only_);
        }
+
        void chat_command_handler::do_network_send()
        {
                chat_handler_.send_command(get_cmd(), get_data());
        }
+
        void chat_command_handler::do_whisper()
        {
                if (get_data(1).empty()) return command_failed_need_arg(1);
@@ -2471,6 +2474,7 @@
                        cwhisper["message"], game_display::MESSAGE_PRIVATE);
                network::send_data(data, 0, true);
        }
+
        void chat_command_handler::do_log()
        {
                chat_handler_.change_logging(get_data());
@@ -2479,10 +2483,10 @@
        void chat_command_handler::do_ignore()
        {
                if (get_arg(1).empty()) {
-                       const std::string& tmp = preferences::get_ignores();
-                       print("ignores list", tmp.empty() ? "(empty)" : tmp);
+                       const std::set<std::string>& tmp = 
preferences::get_ignores();
+                       print("ignores list", tmp.empty() ? "(empty)" : 
utils::join(tmp));
                } else {
-                       for(int i = 1;!get_arg(i).empty();i++){
+                       for(int i = 1; !get_arg(i).empty(); i++){
                                if (preferences::add_ignore(get_arg(i))) {
                                        print("ignore",  _("Added to ignore 
list: ") + get_arg(i));
                                } else {
@@ -2491,11 +2495,12 @@
                        }
                }
        }
+
        void chat_command_handler::do_friend()
        {
                if (get_arg(1).empty()) {
-                       const std::string& tmp = preferences::get_friends();
-                       print("friends list", tmp.empty() ? "(empty)" : tmp);
+                       const std::set<std::string>& tmp = 
preferences::get_friends();
+                       print("friends list", tmp.empty() ? "(empty)" : 
utils::join(tmp));
                } else {
                        for(int i = 1;!get_arg(i).empty();i++){
                                if (preferences::add_friend(get_arg(i))) {
@@ -2506,6 +2511,7 @@
                        }
                }
        }
+
        void chat_command_handler::do_remove()
        {
                for(int i = 1;!get_arg(i).empty();i++){
@@ -2514,19 +2520,25 @@
                        print("list", _("Removed from list: ") + get_arg(i));
                }
        }
+
        void chat_command_handler::do_display()
        {
-               const std::string& text_friend = preferences::get_friends();
-               const std::string& text_ignore = preferences::get_ignores();
-               if (!text_friend.empty()) {
-                       print("friends list", text_friend);
-               }
-               if (!text_ignore.empty()) {
-                       print("ignores list", text_ignore);
-               } else if (text_friend.empty()) {
+               const std::set<std::string> & friends = 
preferences::get_friends();
+               const std::set<std::string> & ignores = 
preferences::get_ignores();
+
+               if (!friends.empty()) {
+                       print("friends list", utils::join(friends));
+               }
+
+               if (!ignores.empty()) {
+                       print("ignores list", utils::join(ignores));
+               } 
+               
+               if (friends.empty() && ignores.empty()) {
                        print("list", _("There are no players on your friends 
or ignore list."));
                }
        }
+
        void chat_command_handler::do_version() {
                print("version", game_config::revision);
        }

Modified: trunk/src/serialization/string_utils.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/serialization/string_utils.cpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/serialization/string_utils.cpp (original)
+++ trunk/src/serialization/string_utils.cpp Wed Feb  4 22:48:16 2009
@@ -390,18 +390,6 @@
        return matches;
 }
 
-std::string join(std::vector< std::string > const &v, char c)
-{
-       std::stringstream str;
-       for(std::vector< std::string >::const_iterator i = v.begin(); i != 
v.end(); ++i) {
-               str << *i;
-               if (i + 1 != v.end())
-                       str << c;
-       }
-
-       return str.str();
-}
-
 std::vector< std::string > quoted_split(std::string const &val, char c, int 
flags, char quote)
 {
        std::vector<std::string> res;

Modified: trunk/src/serialization/string_utils.hpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/serialization/string_utils.hpp?rev=32608&r1=32607&r2=32608&view=diff
==============================================================================
--- trunk/src/serialization/string_utils.hpp (original)
+++ trunk/src/serialization/string_utils.hpp Wed Feb  4 22:48:16 2009
@@ -20,8 +20,10 @@
 
 #include <algorithm>
 #include <map>
+#include <sstream>
 #include <string>
 #include <vector>
+#include <boost/utility.hpp>
 #include "../tstring.hpp"
 #include "../util.hpp"
 
@@ -77,7 +79,18 @@
        const char separator = 0 , std::string const &left="(",
        std::string const &right=")",int flags = REMOVE_EMPTY | STRIP_SPACES);
 
-std::string join(std::vector< std::string > const &v, char c = ',');
+template <typename T>
+std::string join(T const &v, char c = ',')
+{
+        std::stringstream str;
+        for(typename T::const_iterator i = v.begin(); i != v.end(); ++i) {
+                str << *i;
+                if (boost::next(i) != v.end())
+                        str << c;
+        }
+ 
+        return str.str();
+}
 
 /**
  * This function is identical to split(), except it does not split

Added: trunk/src/tests/test_serialization.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/test_serialization.cpp?rev=32608&view=auto
==============================================================================
--- trunk/src/tests/test_serialization.cpp (added)
+++ trunk/src/tests/test_serialization.cpp Wed Feb  4 22:48:16 2009
@@ -1,0 +1,36 @@
+/* $Id$ */
+/*
+   Copyright (C) 2009 by Karol Nowak <[email protected]>
+   Part of the Battle for Wesnoth Project http://www.wesnoth.org/
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License 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.
+
+   See the COPYING file for more details.
+*/
+#include <vector>
+#include <string>
+#include "serialization/string_utils.hpp"
+#include <boost/test/auto_unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE( utils_join_test )
+{
+       BOOST_MESSAGE( "Starting utils::join test!" );
+
+       std::vector<std::string> fruit;
+
+       BOOST_CHECK( utils::join(fruit) == "" );
+
+       fruit.push_back("apples");
+
+       BOOST_CHECK( utils::join(fruit) == "apples" );
+
+       fruit.push_back("oranges");
+       fruit.push_back("lemons");
+
+       BOOST_CHECK( utils::join(fruit) == "apples,oranges,lemons" );
+}
+


_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits

Reply via email to