Allow ConfigManager.getConfig... from any thread (copy on write).

This allows fast config getting from any thread, without need to know if
it is the main thread.
This commit is contained in:
asofold 2014-07-16 14:53:03 +02:00
parent 59fca0f43e
commit 96462dab90
2 changed files with 16 additions and 8 deletions

View File

@ -54,7 +54,7 @@ public class ChatConfig extends AsyncCheckConfig {
synchronized (worldsMap) { synchronized (worldsMap) {
if (!worldsMap.containsKey(player.getWorld().getName())) if (!worldsMap.containsKey(player.getWorld().getName()))
worldsMap.put(player.getWorld().getName(), worldsMap.put(player.getWorld().getName(),
new ChatConfig(ConfigManager.getConfigFileSync(player.getWorld().getName()))); new ChatConfig(ConfigManager.getConfigFile(player.getWorld().getName())));
return worldsMap.get(player.getWorld().getName()); return worldsMap.get(player.getWorld().getName());
} }
} }

View File

@ -3,6 +3,7 @@ package fr.neatmonster.nocheatplus.config;
import java.io.File; import java.io.File;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@ -30,7 +31,7 @@ public class ConfigManager {
}; };
/** The map containing the configuration files per world. */ /** The map containing the configuration files per world. */
private static final Map<String, ConfigFile> worldsMap = new HashMap<String, ConfigFile>(); private static Map<String, ConfigFile> worldsMap = new LinkedHashMap<String, ConfigFile>();
private static final WorldConfigProvider<ConfigFile> worldConfigProvider = new WorldConfigProvider<ConfigFile>() { private static final WorldConfigProvider<ConfigFile> worldConfigProvider = new WorldConfigProvider<ConfigFile>() {
@ -118,7 +119,7 @@ public class ConfigManager {
} }
/** /**
* Gets the configuration file. * Gets the configuration file. Can be called from any thread.
* *
* @return the configuration file * @return the configuration file
*/ */
@ -129,13 +130,15 @@ public class ConfigManager {
/** /**
* (Synchronized version). * (Synchronized version).
* @return * @return
* @deprecated getConfigFile() is thread-safe now.
*/ */
@Deprecated
public static synchronized ConfigFile getConfigFileSync() { public static synchronized ConfigFile getConfigFileSync() {
return getConfigFile(); return getConfigFile();
} }
/** /**
* Gets the configuration file. * Gets the configuration file. Can be called from any thread.
* *
* @param worldName * @param worldName
* the world name * the world name
@ -146,14 +149,17 @@ public class ConfigManager {
if (configFile != null){ if (configFile != null){
return configFile; return configFile;
} }
// Expensive only once, for the rest of runtime the file is returned fast. // Expensive only once per world, for the rest of the runtime the file is returned fast.
synchronized(ConfigManager.class){ synchronized(ConfigManager.class){
// Need to check again. // Need to check again.
if (worldsMap.containsKey(worldName)){ if (worldsMap.containsKey(worldName)){
return worldsMap.get(worldName); return worldsMap.get(worldName);
} }
final ConfigFile globalConfig = getConfigFile(); // Copy the whole map with the default configuration set for this world.
worldsMap.put(worldName, globalConfig); final Map<String, ConfigFile> newWorldsMap = new LinkedHashMap<String, ConfigFile>(ConfigManager.worldsMap);
final ConfigFile globalConfig = newWorldsMap.get(null);
newWorldsMap.put(worldName, globalConfig);
ConfigManager.worldsMap = newWorldsMap;
return globalConfig; return globalConfig;
} }
} }
@ -162,13 +168,15 @@ public class ConfigManager {
* (Synchronized version). * (Synchronized version).
* @param worldName * @param worldName
* @return * @return
* @deprecated getConfigFile() is thread-safe now.
*/ */
@Deprecated
public static synchronized ConfigFile getConfigFileSync(final String worldName) { public static synchronized ConfigFile getConfigFileSync(final String worldName) {
return getConfigFile(worldName); return getConfigFile(worldName);
} }
/** /**
* Initializes the configuration manager. * Initializes the configuration manager. Must be called in the main thread.
* *
* @param plugin * @param plugin
* the instance of NoCheatPlus * the instance of NoCheatPlus