aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/guiPauseMenu.cpp14
-rw-r--r--src/main.cpp33
-rw-r--r--src/mapblock.cpp12
-rw-r--r--src/porting.cpp47
-rw-r--r--src/porting.h11
-rw-r--r--src/server.cpp282
-rw-r--r--src/server.h32
-rw-r--r--src/servermain.cpp18
-rw-r--r--src/test.cpp2
-rw-r--r--src/utility.h34
11 files changed, 380 insertions, 111 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7fefc0238..6d9601c65 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,6 +5,8 @@ if(RUN_IN_PLACE)
add_definitions ( -DRUN_IN_PLACE )
endif(RUN_IN_PLACE)
+set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++")
+
# Use cmake_config.h
add_definitions ( -DUSE_CMAKE_CONFIG_H )
@@ -161,6 +163,10 @@ else()
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG ${WARNING_FLAGS} -O3 -ffast-math -Wall -fomit-frame-pointer -pipe -funroll-loops")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O1 -Wall")
+
+ if(USE_GPROF)
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -pg")
+ endif()
if(BUILD_SERVER)
set_target_properties(minetestserver PROPERTIES
diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp
index b6f913d6b..2d42fdb77 100644
--- a/src/guiPauseMenu.cpp
+++ b/src/guiPauseMenu.cpp
@@ -174,10 +174,18 @@ bool GUIPauseMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
- if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
+ if(event.KeyInput.PressedDown)
{
- quitMenu();
- return true;
+ if(event.KeyInput.Key==KEY_ESCAPE)
+ {
+ quitMenu();
+ return true;
+ }
+ else if(event.KeyInput.Key==KEY_RETURN)
+ {
+ quitMenu();
+ return true;
+ }
}
}
if(event.EventType==EET_GUI_EVENT)
diff --git a/src/main.cpp b/src/main.cpp
index bcc8dc446..452030a24 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -268,7 +268,7 @@ Doing now (most important at the top):
# maybe done
* not done
-=== Stuff to do before release
+=== Fixmes
* Make server find the spawning place from the real map data, not from
the heightmap
- But the changing borders of chunk have to be avoided, because
@@ -277,15 +277,15 @@ Doing now (most important at the top):
placement and transfer
* only_from_disk might not work anymore - check and fix it.
* Check the fixmes in the list above
-* FIXME: Sneaking doesn't switch sneak node when moving sideways
+* When sending blocks to the client, the server takes way too much
+ CPU time (20-30% for single player), find out what it is doing.
+ - Make a simple profiler
=== Making it more portable
* Some MSVC: std::sto* are defined without a namespace and collide
with the ones in utility.h
-* On Kray's machine, the new find_library(XXF86VM_LIBRARY, Xxf86vm)
- line doesn't find the library.
-=== Stuff to do after release
+=== Features
* Make an "environment metafile" to store at least time of day
* Move digging property stuff from material.{h,cpp} to mapnode.cpp...
- Or maybe move content_features to material.{h,cpp}?
@@ -567,7 +567,25 @@ struct TextDestChat : public TextDest
}
void gotText(std::wstring text)
{
+ // Discard empty line
+ if(text == L"")
+ return;
+
+ // Parse command (server command starts with "/#")
+ if(text[0] == L'/' && text[1] != L'#')
+ {
+ std::wstring reply = L"Local: ";
+
+ reply += L"Local commands not yet supported. "
+ "Server prefix is \"/#\".";
+
+ m_client->addChatMessage(reply);
+ return;
+ }
+
+ // Send to others
m_client->sendChatMessage(text);
+ // Show locally
m_client->addChatMessage(text);
}
@@ -1546,6 +1564,9 @@ int main(int argc, char *argv[])
DSTACK(__FUNCTION_NAME);
+ porting::signal_handler_init();
+ bool &kill = *porting::signal_handler_killstatus();
+
porting::initializePaths();
// Create user data directory
fs::CreateDir(porting::path_userdata);
@@ -1681,7 +1702,7 @@ int main(int argc, char *argv[])
server.start(port);
// Run server
- dedicated_server_loop(server);
+ dedicated_server_loop(server, kill);
return 0;
}
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index 422d3b531..1dbbe5c4e 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -1771,11 +1771,11 @@ void MapBlock::serialize(std::ostream &os, u8 version)
// First byte
u8 flags = 0;
if(is_underground)
- flags |= 1;
+ flags |= 0x01;
if(m_day_night_differs)
- flags |= 2;
+ flags |= 0x02;
if(m_lighting_expired)
- flags |= 3;
+ flags |= 0x04;
os.write((char*)&flags, 1);
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
@@ -1895,9 +1895,9 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
u8 flags;
is.read((char*)&flags, 1);
- is_underground = (flags & 1) ? true : false;
- m_day_night_differs = (flags & 2) ? true : false;
- m_lighting_expired = (flags & 3) ? true : false;
+ is_underground = (flags & 0x01) ? true : false;
+ m_day_night_differs = (flags & 0x02) ? true : false;
+ m_lighting_expired = (flags & 0x04) ? true : false;
// Uncompress data
std::ostringstream os(std::ios_base::binary);
diff --git a/src/porting.cpp b/src/porting.cpp
index 592636336..f92b291ac 100644
--- a/src/porting.cpp
+++ b/src/porting.cpp
@@ -29,6 +29,53 @@ with this program; if not, write to the Free Software Foundation, Inc.,
namespace porting
{
+/*
+ Signal handler (grabs Ctrl-C on POSIX systems)
+*/
+
+#if !defined(_WIN32) // POSIX
+ #include <signal.h>
+
+bool g_killed = false;
+
+void sigint_handler(int sig)
+{
+ if(g_killed == false)
+ {
+ dstream<<DTIME<<"sigint_handler(): "
+ <<"Ctrl-C pressed, shutting down."<<std::endl;
+ g_killed = true;
+ }
+ else
+ {
+ (void)signal(SIGINT, SIG_DFL);
+ }
+}
+
+void signal_handler_init(void)
+{
+ dstream<<"signal_handler_init()"<<std::endl;
+ (void)signal(SIGINT, sigint_handler);
+}
+
+#else // _WIN32
+
+void signal_handler_init(void)
+{
+ // No-op
+}
+
+#endif
+
+bool * signal_handler_killstatus(void)
+{
+ return &g_killed;
+}
+
+/*
+ Path mangler
+*/
+
std::string path_data = "../data";
std::string path_userdata = "../";
diff --git a/src/porting.h b/src/porting.h
index 3133fcc80..3cf8df594 100644
--- a/src/porting.h
+++ b/src/porting.h
@@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PORTING_HEADER
#include <string>
-// Included for u64 and such
+// Included for u32 and such
#include "common_irrlicht.h"
#include "debug.h"
#include "constants.h"
@@ -48,6 +48,15 @@ namespace porting
{
/*
+ Signal handler (grabs Ctrl-C on POSIX systems)
+*/
+
+void signal_handler_init(void);
+// Returns a pointer to a bool.
+// When the bool is true, program should quit.
+bool * signal_handler_killstatus(void);
+
+/*
Path of static data directory.
*/
extern std::string path_data;
diff --git a/src/server.cpp b/src/server.cpp
index dc72661ff..31ebfacbb 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -46,7 +46,12 @@ void * ServerThread::Thread()
while(getRun())
{
try{
- m_server->AsyncRunStep();
+ //TimeTaker timer("AsyncRunStep() + Receive()");
+
+ {
+ //TimeTaker timer("AsyncRunStep()");
+ m_server->AsyncRunStep();
+ }
//dout_server<<"Running m_server->Receive()"<<std::endl;
m_server->Receive();
@@ -967,7 +972,8 @@ Server::Server(
m_time_counter(0),
m_time_of_day_send_timer(0),
m_uptime(0),
- m_mapsavedir(mapsavedir)
+ m_mapsavedir(mapsavedir),
+ m_shutdown_requested(false)
{
//m_flowwater_timer = 0.0;
m_liquid_transform_timer = 0.0;
@@ -987,28 +993,62 @@ Server::Server(
Server::~Server()
{
- // Save players
+ /*
+ Send shutdown message
+ */
+ {
+ JMutexAutoLock conlock(m_con_mutex);
+
+ std::wstring line = L"*** Server shutting down";
+
+ /*
+ Send the message to clients
+ */
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd() == false; i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i.getNode()->getValue();
+ assert(client->peer_id == i.getNode()->getKey());
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+
+ SendChatMessage(client->peer_id, line);
+ }
+ }
+
+ /*
+ Save players
+ */
m_env.serializePlayers(m_mapsavedir);
- // Stop threads
+ /*
+ Stop threads
+ */
stop();
-
- JMutexAutoLock clientslock(m_con_mutex);
-
- for(core::map<u16, RemoteClient*>::Iterator
- i = m_clients.getIterator();
- i.atEnd() == false; i++)
+
+ /*
+ Delete clients
+ */
{
- /*// Delete player
- // NOTE: These are removed by env destructor
+ JMutexAutoLock clientslock(m_con_mutex);
+
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd() == false; i++)
{
- u16 peer_id = i.getNode()->getKey();
- JMutexAutoLock envlock(m_env_mutex);
- m_env.removePlayer(peer_id);
- }*/
-
- // Delete client
- delete i.getNode()->getValue();
+ /*// Delete player
+ // NOTE: These are removed by env destructor
+ {
+ u16 peer_id = i.getNode()->getKey();
+ JMutexAutoLock envlock(m_env_mutex);
+ m_env.removePlayer(peer_id);
+ }*/
+
+ // Delete client
+ delete i.getNode()->getValue();
+ }
}
}
@@ -1586,39 +1626,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
m_time_of_day.get());
m_con.Send(peer->id, 0, data, true);
}
-
+
// Send information about server to player in chat
- {
- std::wostringstream os(std::ios_base::binary);
- os<<L"# Server: ";
- // Uptime
- os<<L"uptime="<<m_uptime.get();
- // Information about clients
- os<<L", clients={";
- for(core::map<u16, RemoteClient*>::Iterator
- i = m_clients.getIterator();
- i.atEnd() == false; i++)
- {
- // Get client and check that it is valid
- RemoteClient *client = i.getNode()->getValue();
- assert(client->peer_id == i.getNode()->getKey());
- if(client->serialization_version == SER_FMT_VER_INVALID)
- continue;
- // Get player
- Player *player = m_env.getPlayer(client->peer_id);
- // Get name of player
- std::wstring name = L"unknown";
- if(player != NULL)
- name = narrow_to_wide(player->getName());
- // Add name to information string
- os<<name<<L",";
- }
- os<<L"}";
- if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
- os<<" WARNING: Map saving is disabled."<<std::endl;
- // Send message
- SendChatMessage(peer_id, os.str());
- }
+ SendChatMessage(peer_id, getStatusString());
// Send information about joining in chat
{
@@ -2461,29 +2471,115 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Get player name of this client
std::wstring name = narrow_to_wide(player->getName());
-
- std::wstring line = std::wstring(L"<")+name+L"> "+message;
- dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
-
- /*
- Send the message to all other clients
- */
- for(core::map<u16, RemoteClient*>::Iterator
- i = m_clients.getIterator();
- i.atEnd() == false; i++)
+ // Line to send to players
+ std::wstring line;
+ // Whether to send to the player that sent the line
+ bool send_to_sender = false;
+ // Whether to send to other players
+ bool send_to_others = false;
+
+ // Parse commands
+ std::wstring commandprefix = L"/#";
+ if(message.substr(0, commandprefix.size()) == commandprefix)
+ {
+ line += L"Server: ";
+
+ message = message.substr(commandprefix.size());
+ // Get player name as narrow string
+ std::string name_s = player->getName();
+ // Convert message to narrow string
+ std::string message_s = wide_to_narrow(message);
+ // Operator is the single name defined in config.
+ std::string operator_name = g_settings.get("name");
+ bool is_operator = (operator_name != "" &&
+ wide_to_narrow(name) == operator_name);
+ bool valid_command = false;
+ if(message_s == "help")
+ {
+ line += L"-!- Available commands: ";
+ line += L"status ";
+ if(is_operator)
+ {
+ line += L"shutdown setting ";
+ }
+ else
+ {
+ }
+ send_to_sender = true;
+ valid_command = true;
+ }
+ else if(message_s == "status")
+ {
+ line = getStatusString();
+ send_to_sender = true;
+ valid_command = true;
+ }
+ else if(is_operator)
+ {
+ if(message_s == "shutdown")
+ {
+ dstream<<DTIME<<" Server: Operator requested shutdown."
+ <<std::endl;
+ m_shutdown_requested.set(true);
+
+ line += L"*** Server shutting down (operator request)";
+ send_to_sender = true;
+ valid_command = true;
+ }
+ else if(message_s.substr(0,8) == "setting ")
+ {
+ std::string confline = message_s.substr(8);
+ g_settings.parseConfigLine(confline);
+ line += L"-!- Setting changed.";
+ send_to_sender = true;
+ valid_command = true;
+ }
+ }
+
+ if(valid_command == false)
+ {
+ line += L"-!- Invalid command: " + message;
+ send_to_sender = true;
+ }
+ }
+ else
{
- // Get client and check that it is valid
- RemoteClient *client = i.getNode()->getValue();
- assert(client->peer_id == i.getNode()->getKey());
- if(client->serialization_version == SER_FMT_VER_INVALID)
- continue;
+ line += L"<";
+ /*if(is_operator)
+ line += L"@";*/
+ line += name;
+ line += L"> ";
+ line += message;
+ send_to_others = true;
+ }
+
+ if(line != L"")
+ {
+ dstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
- // Don't send if it's the same one
- if(peer_id == client->peer_id)
- continue;
+ /*
+ Send the message to clients
+ */
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd() == false; i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i.getNode()->getValue();
+ assert(client->peer_id == i.getNode()->getKey());
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
- SendChatMessage(client->peer_id, line);
+ // Filter recipient
+ bool sender_selected = (peer_id == client->peer_id);
+ if(sender_selected == true && send_to_sender == false)
+ continue;
+ if(sender_selected == false && send_to_others == false)
+ continue;
+
+ SendChatMessage(client->peer_id, line);
+ }
}
}
else
@@ -2580,6 +2676,7 @@ core::list<PlayerInfo> Server::getPlayerInfo()
return list;
}
+
void Server::peerAdded(con::Peer *peer)
{
DSTACK(__FUNCTION_NAME);
@@ -3020,6 +3117,8 @@ void Server::SendBlocks(float dtime)
JMutexAutoLock envlock(m_env_mutex);
+ //TimeTaker timer("Server::SendBlocks");
+
core::array<PrioritySortedBlockTransfer> queue;
s32 total_sending = 0;
@@ -3087,6 +3186,39 @@ RemoteClient* Server::getClient(u16 peer_id)
return n->getValue();
}
+std::wstring Server::getStatusString()
+{
+ std::wostringstream os(std::ios_base::binary);
+ os<<L"# Server: ";
+ // Uptime
+ os<<L"uptime="<<m_uptime.get();
+ // Information about clients
+ os<<L", clients={";
+ for(core::map<u16, RemoteClient*>::Iterator
+ i = m_clients.getIterator();
+ i.atEnd() == false; i++)
+ {
+ // Get client and check that it is valid
+ RemoteClient *client = i.getNode()->getValue();
+ assert(client->peer_id == i.getNode()->getKey());
+ if(client->serialization_version == SER_FMT_VER_INVALID)
+ continue;
+ // Get player
+ Player *player = m_env.getPlayer(client->peer_id);
+ // Get name of player
+ std::wstring name = L"unknown";
+ if(player != NULL)
+ name = narrow_to_wide(player->getName());
+ // Add name to information string
+ os<<name<<L",";
+ }
+ os<<L"}";
+ if(((ServerMap*)(&m_env.getMap()))->isSavingEnabled() == false)
+ os<<" WARNING: Map saving is disabled."<<std::endl;
+ return os.str();
+}
+
+
void setCreativeInventory(Player *player)
{
player->resetInventory();
@@ -3455,11 +3587,11 @@ void Server::handlePeerChanges()
}
}
-void dedicated_server_loop(Server &server)
+void dedicated_server_loop(Server &server, bool &kill)
{
DSTACK(__FUNCTION_NAME);
- std::cout<<std::endl;
+ std::cout<<DTIME<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<"Running dedicated server"<<std::endl;
std::cout<<"========================"<<std::endl;
@@ -3472,6 +3604,12 @@ void dedicated_server_loop(Server &server)
sleep_ms(30);
server.step(0.030);
+ if(server.getShutdownRequested() || kill)
+ {
+ std::cout<<DTIME<<" dedicated_server_loop(): Quitting."<<std::endl;
+ break;
+ }
+
static int counter = 0;
counter--;
if(counter <= 0)
diff --git a/src/server.h b/src/server.h
index d19a440d7..9582c99dd 100644
--- a/src/server.h
+++ b/src/server.h
@@ -390,15 +390,11 @@ public:
void Receive();
void ProcessData(u8 *data, u32 datasize, u16 peer_id);
- /*void Send(u16 peer_id, u16 channelnum,
- SharedBuffer<u8> data, bool reliable);*/
-
- // Environment and Connection must be locked when called
+ // Environment and Connection must be locked when called
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
- // Environment and Connection must be locked when called
- //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
-
+ //
+
core::list<PlayerInfo> getPlayerInfo();
u32 getDayNightRatio()
@@ -412,7 +408,12 @@ public:
else
return 1000;
}
-
+
+ bool getShutdownRequested()
+ {
+ return m_shutdown_requested.get();
+ }
+
private:
// Virtual methods from con::PeerHandler.
@@ -432,7 +433,10 @@ private:
// When called, connection mutex should be locked
RemoteClient* getClient(u16 peer_id);
-
+
+ // Connection must be locked when called
+ std::wstring getStatusString();
+
/*
Get a player from memory or creates one.
If player is already connected, return NULL
@@ -490,7 +494,7 @@ private:
float m_time_of_day_send_timer;
MutexedVariable<double> m_uptime;
-
+
enum PeerChangeType
{
PEER_ADDED,
@@ -508,14 +512,18 @@ private:
std::string m_mapsavedir;
+ MutexedVariable<bool> m_shutdown_requested;
+
friend class EmergeThread;
friend class RemoteClient;
};
/*
- Runs a simple dedicated server loop
+ Runs a simple dedicated server loop.
+
+ Shuts down when run is set to false.
*/
-void dedicated_server_loop(Server &server);
+void dedicated_server_loop(Server &server, bool &run);
#endif
diff --git a/src/servermain.cpp b/src/servermain.cpp
index 1c301d4f5..254b1f28a 100644
--- a/src/servermain.cpp
+++ b/src/servermain.cpp
@@ -98,7 +98,6 @@ std::ostream *derr_server_ptr = &dstream;
std::ostream *dout_client_ptr = &dstream;
std::ostream *derr_client_ptr = &dstream;
-
/*
gettime.h implementation
*/
@@ -129,6 +128,9 @@ int main(int argc, char *argv[])
DSTACK(__FUNCTION_NAME);
+ porting::signal_handler_init();
+ bool &kill = *porting::signal_handler_killstatus();
+
porting::initializePaths();
initializeMaterialProperties();
@@ -251,6 +253,11 @@ int main(int argc, char *argv[])
srand(time(0));
mysrand(time(0));
+ // Initialize stuff
+
+ init_mapnode();
+ init_mineral();
+
/*
Run unit tests
*/
@@ -260,11 +267,6 @@ int main(int argc, char *argv[])
run_tests();
}
- // Initialize stuff
-
- init_mapnode();
- init_mineral();
-
/*
Check parameters
*/
@@ -308,9 +310,9 @@ int main(int argc, char *argv[])
// Create server
Server server(map_dir.c_str());
server.start(port);
-
+
// Run server
- dedicated_server_loop(server);
+ dedicated_server_loop(server, kill);
} //try
catch(con::PeerNotFoundException &e)
diff --git a/src/test.cpp b/src/test.cpp
index e5b22a978..1de902787 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -192,7 +192,7 @@ struct TestMapNode
// Transparency
n.d = CONTENT_AIR;
assert(n.light_propagates() == true);
- n.d = 0;
+ n.d = CONTENT_STONE;
assert(n.light_propagates() == false);
}
};
diff --git a/src/utility.h b/src/utility.h
index 46277cd42..8c81aba91 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -802,9 +802,15 @@ struct ValueSpec
class Settings
{
public:
+ Settings()
+ {
+ m_mutex.Init();
+ }
void writeLines(std::ostream &os)
{
+ JMutexAutoLock lock(m_mutex);
+
for(core::map<std::string, std::string>::Iterator
i = m_settings.getIterator();
i.atEnd() == false; i++)
@@ -817,6 +823,8 @@ public:
bool parseConfigLine(const std::string &line)
{
+ JMutexAutoLock lock(m_mutex);
+
std::string trimmedline = trim(line);
// Ignore comments
@@ -899,6 +907,8 @@ public:
core::list<std::string> &dst,
core::map<std::string, bool> &updated)
{
+ JMutexAutoLock lock(m_mutex);
+
if(is.eof())
return false;
@@ -981,6 +991,8 @@ public:
}
}
+ JMutexAutoLock lock(m_mutex);
+
// Write stuff back
{
std::ofstream os(filename);
@@ -1087,21 +1099,29 @@ public:
void set(std::string name, std::string value)
{
+ JMutexAutoLock lock(m_mutex);
+
m_settings[name] = value;
}
void setDefault(std::string name, std::string value)
{
+ JMutexAutoLock lock(m_mutex);
+
m_defaults[name] = value;
}
bool exists(std::string name)
{
+ JMutexAutoLock lock(m_mutex);
+
return (m_settings.find(name) || m_defaults.find(name));
}
std::string get(std::string name)
{
+ JMutexAutoLock lock(m_mutex);
+
core::map<std::string, std::string>::Node *n;
n = m_settings.find(name);
if(n == NULL)
@@ -1139,7 +1159,7 @@ public:
bool getBoolAsk(std::string name, std::string question, bool def)
{
// If it is in settings
- if(m_settings.find(name))
+ if(exists(name))
return getBool(name);
std::string s;
@@ -1167,7 +1187,7 @@ public:
u16 getU16Ask(std::string name, std::string question, u16 def)
{
// If it is in settings
- if(m_settings.find(name))
+ if(exists(name))
return getU16(name);
std::string s;
@@ -1238,12 +1258,17 @@ public:
void clear()
{
+ JMutexAutoLock lock(m_mutex);
+
m_settings.clear();
m_defaults.clear();
}
Settings & operator+=(Settings &other)
{
+ JMutexAutoLock lock(m_mutex);
+ JMutexAutoLock lock2(other.m_mutex);
+
if(&other == this)
return *this;
@@ -1267,6 +1292,9 @@ public:
Settings & operator=(Settings &other)
{
+ JMutexAutoLock lock(m_mutex);
+ JMutexAutoLock lock2(other.m_mutex);
+
if(&other == this)
return *this;
@@ -1279,6 +1307,8 @@ public:
private:
core::map<std::string, std::string> m_settings;
core::map<std::string, std::string> m_defaults;
+ // All methods that access m_settings/m_defaults directly should lock this.
+ JMutex m_mutex;
};
/*