aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch
blob: 2fea1f0e3ee8533a84665e0a9ac65a5783f65042 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
From 270a57e64ae5f5a383b35a424dab9a45aa781eaf Mon Sep 17 00:00:00 2001
From: crast <contact@jamescrasta.com>
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 093c144..64c0f0a 100644
--- a/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
+++ b/src/main/java/org/bukkit/metadata/MetadataStoreBase.java
@@ -4,9 +4,10 @@ import org.apache.commons.lang.Validate;
 import org.bukkit.plugin.Plugin;
 
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 public abstract class MetadataStoreBase<T> {
-    private Map<String, Map<Plugin, MetadataValue>> metadataMap = new HashMap<String, Map<Plugin, MetadataValue>>();
+    private Map<String, Map<Plugin, MetadataValue>> metadataMap = new ConcurrentHashMap<String, Map<Plugin, MetadataValue>>();
 
     /**
      * Adds a metadata value to an object. Each metadata value is owned by a
@@ -30,7 +31,7 @@ public abstract class MetadataStoreBase<T> {
      * @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");
@@ -40,7 +41,9 @@ public abstract class MetadataStoreBase<T> {
             entry = new WeakHashMap<Plugin, MetadataValue>(1);
             metadataMap.put(key, entry);
         }
-        entry.put(owningPlugin, newMetadataValue);
+        synchronized (entry) {
+            entry.put(owningPlugin, newMetadataValue);
+        }
     }
 
     /**
@@ -53,10 +56,11 @@ public abstract class MetadataStoreBase<T> {
      *     requested value.
      * @see MetadataStore#getMetadata(Object, String)
      */
-    public synchronized List<MetadataValue> getMetadata(T subject, String metadataKey) {
+    public List<MetadataValue> getMetadata(T subject, String metadataKey) {
         String key = disambiguate(subject, metadataKey);
-        if (metadataMap.containsKey(key)) {
-            Collection<MetadataValue> values = metadataMap.get(key).values();
+        Map<Plugin, MetadataValue> entry = metadataMap.get(key);
+        if (entry != null) {
+            Collection<MetadataValue> values = entry.values();
             return Collections.unmodifiableList(new ArrayList<MetadataValue>(values));
         } else {
             return Collections.emptyList();
@@ -71,7 +75,7 @@ public abstract class MetadataStoreBase<T> {
      * @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);
     }
@@ -87,17 +91,18 @@ public abstract class MetadataStoreBase<T> {
      *     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<Plugin, MetadataValue> 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);
+            }
         }
     }
 
@@ -110,7 +115,7 @@ public abstract class MetadataStoreBase<T> {
      * @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<Plugin, MetadataValue> values : metadataMap.values()) {
             if (values.containsKey(owningPlugin)) {
-- 
2.9.2.windows.1