mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-10 14:16:36 +00:00
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.
This commit is contained in:
parent
a77dbecae0
commit
39240dba88
@ -476,6 +476,7 @@ SET(test_SRC
|
||||
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
|
||||
|
@ -289,6 +289,7 @@ test_SOURCES = \
|
||||
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 \
|
||||
|
@ -371,6 +371,7 @@ test_sources = Split("""
|
||||
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
|
||||
|
@ -39,19 +39,10 @@ std::set<t_translation::t_terrain> encountered_terrains_set;
|
||||
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 @@ manager::~manager()
|
||||
set_ping_timeout(network::ping_timeout);
|
||||
}
|
||||
|
||||
std::string get_friends() {
|
||||
return preferences::get("friends");
|
||||
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;
|
||||
}
|
||||
|
||||
std::string get_ignores() {
|
||||
return preferences::get("ignores");
|
||||
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 @@ void clear_ignores() {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -42,8 +42,8 @@ namespace preferences {
|
||||
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);
|
||||
|
@ -993,12 +993,14 @@ void preferences_dialog::set_advanced_menu()
|
||||
|
||||
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
|
||||
|
@ -2449,14 +2449,17 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
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 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void chat_command_handler::do_remove()
|
||||
{
|
||||
for(int i = 1;!get_arg(i).empty();i++){
|
||||
@ -2514,19 +2520,25 @@ private:
|
||||
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);
|
||||
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 (!text_ignore.empty()) {
|
||||
print("ignores list", text_ignore);
|
||||
} else if (text_friend.empty()) {
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -390,18 +390,6 @@ bool wildcard_string_match(const std::string& str, const std::string& match) {
|
||||
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;
|
||||
|
@ -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 @@ std::vector< std::string > paranthetical_split(std::string const &val,
|
||||
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
|
||||
|
36
src/tests/test_serialization.cpp
Normal file
36
src/tests/test_serialization.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/* $Id$ */
|
||||
/*
|
||||
Copyright (C) 2009 by Karol Nowak <grywacz@gmail.com>
|
||||
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" );
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user