Skip to content

Commit 83f7b2b

Browse files
committed
Use StampedLocks for performance reasons
1 parent a27bdf2 commit 83f7b2b

File tree

1 file changed

+88
-68
lines changed

1 file changed

+88
-68
lines changed

worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java

+88-68
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@
5353
import java.util.Map;
5454
import java.util.Map.Entry;
5555
import java.util.concurrent.atomic.AtomicBoolean;
56-
import java.util.concurrent.locks.ReadWriteLock;
57-
import java.util.concurrent.locks.ReentrantReadWriteLock;
56+
import java.util.concurrent.locks.StampedLock;
5857
import javax.annotation.Nullable;
5958

6059
import static com.google.common.base.Preconditions.checkNotNull;
@@ -77,8 +76,8 @@ public class PlatformManager {
7776
private final AtomicBoolean initialized = new AtomicBoolean();
7877
private final AtomicBoolean configured = new AtomicBoolean();
7978

80-
private final ReadWriteLock platformsLock = new ReentrantReadWriteLock();
81-
private final ReadWriteLock preferencesLock = new ReentrantReadWriteLock();
79+
private final StampedLock platformsLock = new StampedLock();
80+
private final StampedLock preferencesLock = new StampedLock();
8281

8382
/**
8483
* Create a new platform manager.
@@ -106,11 +105,11 @@ public void register(Platform platform) {
106105

107106
// Just add the platform to the list of platforms: we'll pick favorites
108107
// once all the platforms have been loaded
109-
platformsLock.writeLock().lock();
108+
long stamp = platformsLock.writeLock();
110109
try {
111110
platforms.add(platform);
112111
} finally {
113-
platformsLock.writeLock().unlock();
112+
platformsLock.unlockWrite(stamp);
114113
}
115114

116115
// Make sure that versions are in sync
@@ -137,40 +136,40 @@ public boolean unregister(Platform platform) {
137136
checkNotNull(platform);
138137

139138
boolean removed;
140-
platformsLock.writeLock().lock();
139+
long platformsStamp = platformsLock.writeLock();
141140

142141
try {
143142
removed = platforms.remove(platform);
143+
} finally {
144+
platformsLock.unlockWrite(platformsStamp);
145+
}
144146

145-
if (removed) {
146-
LOGGER.info("Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
147+
if (removed) {
148+
LOGGER.info("Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
147149

148-
boolean choosePreferred = false;
150+
boolean choosePreferred = false;
149151

150-
preferencesLock.writeLock().lock();
152+
long preferencesStamp = preferencesLock.writeLock();
151153

152-
try {
153-
// Check whether this platform was chosen to be the preferred one
154-
// for any capability and be sure to remove it
155-
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
156-
while (it.hasNext()) {
157-
Entry<Capability, Platform> entry = it.next();
158-
if (entry.getValue().equals(platform)) {
159-
entry.getKey().uninitialize(this, entry.getValue());
160-
it.remove();
161-
choosePreferred = true; // Have to choose new favorites
162-
}
154+
try {
155+
// Check whether this platform was chosen to be the preferred one
156+
// for any capability and be sure to remove it
157+
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
158+
while (it.hasNext()) {
159+
Entry<Capability, Platform> entry = it.next();
160+
if (entry.getValue().equals(platform)) {
161+
entry.getKey().uninitialize(this, entry.getValue());
162+
it.remove();
163+
choosePreferred = true; // Have to choose new favorites
163164
}
164-
} finally {
165-
preferencesLock.writeLock().unlock();
166165
}
166+
} finally {
167+
preferencesLock.unlockWrite(preferencesStamp);
168+
}
167169

168-
if (choosePreferred) {
169-
choosePreferred();
170-
}
170+
if (choosePreferred) {
171+
choosePreferred();
171172
}
172-
} finally {
173-
platformsLock.writeLock().unlock();
174173
}
175174

176175
return removed;
@@ -184,24 +183,33 @@ public boolean unregister(Platform platform) {
184183
* @throws NoCapablePlatformException thrown if no platform is capable
185184
*/
186185
public Platform queryCapability(Capability capability) throws NoCapablePlatformException {
187-
preferencesLock.readLock().lock();
186+
checkNotNull(capability);
187+
188+
long stamp = preferencesLock.tryOptimisticRead();
189+
Platform platform = preferences.get(capability);
190+
boolean hasNoPreferences = platform == null && preferences.isEmpty();
191+
192+
if (!preferencesLock.validate(stamp)) {
193+
stamp = preferencesLock.readLock();
194+
try {
195+
platform = preferences.get(capability);
196+
hasNoPreferences = platform == null && preferences.isEmpty();
197+
} finally {
198+
preferencesLock.unlockRead(stamp);
199+
}
200+
}
188201

189-
try {
190-
Platform platform = preferences.get(checkNotNull(capability));
191-
if (platform != null) {
192-
return platform;
193-
} else {
194-
if (preferences.isEmpty()) {
195-
// Not all platforms registered, this is being called too early!
196-
throw new NoCapablePlatformException(
197-
"Not all platforms have been registered yet!"
198-
+ " Please wait until WorldEdit is initialized."
199-
);
200-
}
201-
throw new NoCapablePlatformException("No platform was found supporting " + capability.name());
202+
if (platform != null) {
203+
return platform;
204+
} else {
205+
if (hasNoPreferences) {
206+
// Not all platforms registered, this is being called too early!
207+
throw new NoCapablePlatformException(
208+
"Not all platforms have been registered yet!"
209+
+ " Please wait until WorldEdit is initialized."
210+
);
202211
}
203-
} finally {
204-
preferencesLock.readLock().unlock();
212+
throw new NoCapablePlatformException("No platform was found supporting " + capability.name());
205213
}
206214
}
207215

@@ -212,31 +220,37 @@ private void choosePreferred() {
212220
for (Capability capability : Capability.values()) {
213221
Platform preferred = findMostPreferred(capability);
214222
if (preferred != null) {
215-
preferencesLock.writeLock().lock();
223+
Platform oldPreferred;
224+
long stamp = preferencesLock.writeLock();
216225
try {
217-
Platform oldPreferred = preferences.put(capability, preferred);
218-
// only (re)initialize if it changed
219-
if (preferred != oldPreferred) {
220-
// uninitialize if needed
221-
if (oldPreferred != null) {
222-
capability.uninitialize(this, oldPreferred);
223-
}
224-
capability.initialize(this, preferred);
225-
}
226+
oldPreferred = preferences.put(capability, preferred);
226227
} finally {
227-
preferencesLock.writeLock().unlock();
228+
preferencesLock.unlockWrite(stamp);
229+
}
230+
// only (re)initialize if it changed
231+
if (preferred != oldPreferred) {
232+
// uninitialize if needed
233+
if (oldPreferred != null) {
234+
capability.uninitialize(this, oldPreferred);
235+
}
236+
capability.initialize(this, preferred);
228237
}
229238
}
230239
}
231240

232-
preferencesLock.readLock().lock();
233-
try {
234-
// Fire configuration event
235-
if (preferences.containsKey(Capability.CONFIGURATION) && configured.compareAndSet(false, true)) {
236-
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
241+
long stamp = preferencesLock.tryOptimisticRead();
242+
boolean hasConfiguration = preferences.containsKey(Capability.CONFIGURATION);
243+
if (!preferencesLock.validate(stamp)) {
244+
stamp = preferencesLock.readLock();
245+
try {
246+
hasConfiguration = preferences.containsKey(Capability.CONFIGURATION);
247+
} finally {
248+
preferencesLock.unlockRead(stamp);
237249
}
238-
} finally {
239-
preferencesLock.readLock().unlock();
250+
}
251+
// Fire configuration event
252+
if (hasConfiguration && configured.compareAndSet(false, true)) {
253+
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
240254
}
241255
}
242256

@@ -270,12 +284,18 @@ private void choosePreferred() {
270284
* @return a list of platforms
271285
*/
272286
public List<Platform> getPlatforms() {
273-
platformsLock.readLock().lock();
274-
try {
275-
return new ArrayList<>(platforms);
276-
} finally {
277-
platformsLock.readLock().unlock();
287+
long stamp = platformsLock.tryOptimisticRead();
288+
List<Platform> platformsCopy = new ArrayList<>(platforms);
289+
if (!platformsLock.validate(stamp)) {
290+
stamp = platformsLock.readLock();
291+
try {
292+
platformsCopy = new ArrayList<>(platforms);
293+
} finally {
294+
platformsLock.unlockRead(stamp);
295+
}
278296
}
297+
298+
return platformsCopy;
279299
}
280300

281301
/**

0 commit comments

Comments
 (0)