mirror of
https://github.com/EngineHub/WorldEdit.git
synced 2025-02-23 13:30:12 +08:00
Use StampedLocks for performance reasons
This commit is contained in:
parent
a27bdf232c
commit
83f7b2b505
@ -53,8 +53,7 @@
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.concurrent.locks.StampedLock;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -77,8 +76,8 @@ public class PlatformManager {
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final AtomicBoolean configured = new AtomicBoolean();
|
||||
|
||||
private final ReadWriteLock platformsLock = new ReentrantReadWriteLock();
|
||||
private final ReadWriteLock preferencesLock = new ReentrantReadWriteLock();
|
||||
private final StampedLock platformsLock = new StampedLock();
|
||||
private final StampedLock preferencesLock = new StampedLock();
|
||||
|
||||
/**
|
||||
* Create a new platform manager.
|
||||
@ -106,11 +105,11 @@ public void register(Platform platform) {
|
||||
|
||||
// Just add the platform to the list of platforms: we'll pick favorites
|
||||
// once all the platforms have been loaded
|
||||
platformsLock.writeLock().lock();
|
||||
long stamp = platformsLock.writeLock();
|
||||
try {
|
||||
platforms.add(platform);
|
||||
} finally {
|
||||
platformsLock.writeLock().unlock();
|
||||
platformsLock.unlockWrite(stamp);
|
||||
}
|
||||
|
||||
// Make sure that versions are in sync
|
||||
@ -137,40 +136,40 @@ public boolean unregister(Platform platform) {
|
||||
checkNotNull(platform);
|
||||
|
||||
boolean removed;
|
||||
platformsLock.writeLock().lock();
|
||||
long platformsStamp = platformsLock.writeLock();
|
||||
|
||||
try {
|
||||
removed = platforms.remove(platform);
|
||||
|
||||
if (removed) {
|
||||
LOGGER.info("Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
|
||||
|
||||
boolean choosePreferred = false;
|
||||
|
||||
preferencesLock.writeLock().lock();
|
||||
|
||||
try {
|
||||
// Check whether this platform was chosen to be the preferred one
|
||||
// for any capability and be sure to remove it
|
||||
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<Capability, Platform> entry = it.next();
|
||||
if (entry.getValue().equals(platform)) {
|
||||
entry.getKey().uninitialize(this, entry.getValue());
|
||||
it.remove();
|
||||
choosePreferred = true; // Have to choose new favorites
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
preferencesLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
if (choosePreferred) {
|
||||
choosePreferred();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
platformsLock.writeLock().unlock();
|
||||
platformsLock.unlockWrite(platformsStamp);
|
||||
}
|
||||
|
||||
if (removed) {
|
||||
LOGGER.info("Unregistering " + platform.getClass().getCanonicalName() + " from WorldEdit");
|
||||
|
||||
boolean choosePreferred = false;
|
||||
|
||||
long preferencesStamp = preferencesLock.writeLock();
|
||||
|
||||
try {
|
||||
// Check whether this platform was chosen to be the preferred one
|
||||
// for any capability and be sure to remove it
|
||||
Iterator<Entry<Capability, Platform>> it = preferences.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<Capability, Platform> entry = it.next();
|
||||
if (entry.getValue().equals(platform)) {
|
||||
entry.getKey().uninitialize(this, entry.getValue());
|
||||
it.remove();
|
||||
choosePreferred = true; // Have to choose new favorites
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
preferencesLock.unlockWrite(preferencesStamp);
|
||||
}
|
||||
|
||||
if (choosePreferred) {
|
||||
choosePreferred();
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
@ -184,24 +183,33 @@ public boolean unregister(Platform platform) {
|
||||
* @throws NoCapablePlatformException thrown if no platform is capable
|
||||
*/
|
||||
public Platform queryCapability(Capability capability) throws NoCapablePlatformException {
|
||||
preferencesLock.readLock().lock();
|
||||
checkNotNull(capability);
|
||||
|
||||
try {
|
||||
Platform platform = preferences.get(checkNotNull(capability));
|
||||
if (platform != null) {
|
||||
return platform;
|
||||
} else {
|
||||
if (preferences.isEmpty()) {
|
||||
// Not all platforms registered, this is being called too early!
|
||||
throw new NoCapablePlatformException(
|
||||
"Not all platforms have been registered yet!"
|
||||
+ " Please wait until WorldEdit is initialized."
|
||||
);
|
||||
}
|
||||
throw new NoCapablePlatformException("No platform was found supporting " + capability.name());
|
||||
long stamp = preferencesLock.tryOptimisticRead();
|
||||
Platform platform = preferences.get(capability);
|
||||
boolean hasNoPreferences = platform == null && preferences.isEmpty();
|
||||
|
||||
if (!preferencesLock.validate(stamp)) {
|
||||
stamp = preferencesLock.readLock();
|
||||
try {
|
||||
platform = preferences.get(capability);
|
||||
hasNoPreferences = platform == null && preferences.isEmpty();
|
||||
} finally {
|
||||
preferencesLock.unlockRead(stamp);
|
||||
}
|
||||
} finally {
|
||||
preferencesLock.readLock().unlock();
|
||||
}
|
||||
|
||||
if (platform != null) {
|
||||
return platform;
|
||||
} else {
|
||||
if (hasNoPreferences) {
|
||||
// Not all platforms registered, this is being called too early!
|
||||
throw new NoCapablePlatformException(
|
||||
"Not all platforms have been registered yet!"
|
||||
+ " Please wait until WorldEdit is initialized."
|
||||
);
|
||||
}
|
||||
throw new NoCapablePlatformException("No platform was found supporting " + capability.name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,31 +220,37 @@ private void choosePreferred() {
|
||||
for (Capability capability : Capability.values()) {
|
||||
Platform preferred = findMostPreferred(capability);
|
||||
if (preferred != null) {
|
||||
preferencesLock.writeLock().lock();
|
||||
Platform oldPreferred;
|
||||
long stamp = preferencesLock.writeLock();
|
||||
try {
|
||||
Platform oldPreferred = preferences.put(capability, preferred);
|
||||
// only (re)initialize if it changed
|
||||
if (preferred != oldPreferred) {
|
||||
// uninitialize if needed
|
||||
if (oldPreferred != null) {
|
||||
capability.uninitialize(this, oldPreferred);
|
||||
}
|
||||
capability.initialize(this, preferred);
|
||||
}
|
||||
oldPreferred = preferences.put(capability, preferred);
|
||||
} finally {
|
||||
preferencesLock.writeLock().unlock();
|
||||
preferencesLock.unlockWrite(stamp);
|
||||
}
|
||||
// only (re)initialize if it changed
|
||||
if (preferred != oldPreferred) {
|
||||
// uninitialize if needed
|
||||
if (oldPreferred != null) {
|
||||
capability.uninitialize(this, oldPreferred);
|
||||
}
|
||||
capability.initialize(this, preferred);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preferencesLock.readLock().lock();
|
||||
try {
|
||||
// Fire configuration event
|
||||
if (preferences.containsKey(Capability.CONFIGURATION) && configured.compareAndSet(false, true)) {
|
||||
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||
long stamp = preferencesLock.tryOptimisticRead();
|
||||
boolean hasConfiguration = preferences.containsKey(Capability.CONFIGURATION);
|
||||
if (!preferencesLock.validate(stamp)) {
|
||||
stamp = preferencesLock.readLock();
|
||||
try {
|
||||
hasConfiguration = preferences.containsKey(Capability.CONFIGURATION);
|
||||
} finally {
|
||||
preferencesLock.unlockRead(stamp);
|
||||
}
|
||||
} finally {
|
||||
preferencesLock.readLock().unlock();
|
||||
}
|
||||
// Fire configuration event
|
||||
if (hasConfiguration && configured.compareAndSet(false, true)) {
|
||||
worldEdit.getEventBus().post(new ConfigurationLoadEvent(queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -270,12 +284,18 @@ private void choosePreferred() {
|
||||
* @return a list of platforms
|
||||
*/
|
||||
public List<Platform> getPlatforms() {
|
||||
platformsLock.readLock().lock();
|
||||
try {
|
||||
return new ArrayList<>(platforms);
|
||||
} finally {
|
||||
platformsLock.readLock().unlock();
|
||||
long stamp = platformsLock.tryOptimisticRead();
|
||||
List<Platform> platformsCopy = new ArrayList<>(platforms);
|
||||
if (!platformsLock.validate(stamp)) {
|
||||
stamp = platformsLock.readLock();
|
||||
try {
|
||||
platformsCopy = new ArrayList<>(platforms);
|
||||
} finally {
|
||||
platformsLock.unlockRead(stamp);
|
||||
}
|
||||
}
|
||||
|
||||
return platformsCopy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user