From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: crast Date: Sat, 1 Jun 2013 13:52:30 -0600 Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase Use ConcurrentHashMap to allow thread-safe access methods and very limited synchronized portions to allow much higher concurrency in MetadataStore as well as far less locking, especially on reads diff --git a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java +++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java @@ -0,0 +0,0 @@ import org.apache.commons.lang.Validate; import org.bukkit.plugin.Plugin; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public abstract class MetadataStoreBase { - private Map> metadataMap = new HashMap>(); + private Map> metadataMap = new ConcurrentHashMap>(); /** * Adds a metadata value to an object. Each metadata value is owned by a @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { * @throws IllegalArgumentException If value is null, or the owning plugin * is null */ - public synchronized void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue) { + public void setMetadata(T subject, String metadataKey, MetadataValue newMetadataValue) { Validate.notNull(newMetadataValue, "Value cannot be null"); Plugin owningPlugin = newMetadataValue.getOwningPlugin(); Validate.notNull(owningPlugin, "Plugin cannot be null"); @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { entry = new WeakHashMap(1); metadataMap.put(key, entry); } - entry.put(owningPlugin, newMetadataValue); + synchronized (entry) { + entry.put(owningPlugin, newMetadataValue); + } } /** @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { * requested value. * @see MetadataStore#getMetadata(Object, String) */ - public synchronized List getMetadata(T subject, String metadataKey) { + public List getMetadata(T subject, String metadataKey) { String key = disambiguate(subject, metadataKey); - if (metadataMap.containsKey(key)) { - Collection values = metadataMap.get(key).values(); + Map entry = metadataMap.get(key); + if (entry != null) { + Collection values = entry.values(); return Collections.unmodifiableList(new ArrayList(values)); } else { return Collections.emptyList(); @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { * @param metadataKey the unique metadata key being queried. * @return the existence of the metadataKey within subject. */ - public synchronized boolean hasMetadata(T subject, String metadataKey) { + public boolean hasMetadata(T subject, String metadataKey) { String key = disambiguate(subject, metadataKey); return metadataMap.containsKey(key); } @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { * org.bukkit.plugin.Plugin) * @throws IllegalArgumentException If plugin is null */ - public synchronized void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { + public void removeMetadata(T subject, String metadataKey, Plugin owningPlugin) { Validate.notNull(owningPlugin, "Plugin cannot be null"); String key = disambiguate(subject, metadataKey); Map entry = metadataMap.get(key); if (entry == null) { return; } - - entry.remove(owningPlugin); - if (entry.isEmpty()) { - metadataMap.remove(key); + synchronized (entry) { + entry.remove(owningPlugin); + if (entry.isEmpty()) { + metadataMap.remove(key); + } } } @@ -0,0 +0,0 @@ public abstract class MetadataStoreBase { * @see MetadataStore#invalidateAll(org.bukkit.plugin.Plugin) * @throws IllegalArgumentException If plugin is null */ - public synchronized void invalidateAll(Plugin owningPlugin) { + public void invalidateAll(Plugin owningPlugin) { Validate.notNull(owningPlugin, "Plugin cannot be null"); for (Map values : metadataMap.values()) { if (values.containsKey(owningPlugin)) { --