3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-12-25 07:40:13 +01:00

Try to avoid locking, use an actual concurrent data structure

Dieser Commit ist enthalten in:
Andrew Steinborn 2018-09-18 16:40:51 -04:00
Ursprung 037dceb599
Commit 44b1b82b09
2 geänderte Dateien mit 19 neuen und 67 gelöschten Zeilen

Datei anzeigen

@ -7,13 +7,10 @@ import com.velocitypowered.api.proxy.server.ServerInfo;
import com.velocitypowered.proxy.VelocityServer; import com.velocitypowered.proxy.VelocityServer;
import java.util.*; import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ServerMap { public class ServerMap {
private final VelocityServer server; private final VelocityServer server;
private final Map<String, RegisteredServer> servers = new HashMap<>(); private final Map<String, RegisteredServer> servers = new HashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
public ServerMap(VelocityServer server) { public ServerMap(VelocityServer server) {
this.server = server; this.server = server;
@ -22,47 +19,27 @@ public class ServerMap {
public Optional<RegisteredServer> getServer(String name) { public Optional<RegisteredServer> getServer(String name) {
Preconditions.checkNotNull(name, "server"); Preconditions.checkNotNull(name, "server");
String lowerName = name.toLowerCase(Locale.US); String lowerName = name.toLowerCase(Locale.US);
lock.readLock().lock();
try {
return Optional.ofNullable(servers.get(lowerName)); return Optional.ofNullable(servers.get(lowerName));
} finally {
lock.readLock().unlock();
}
} }
public Collection<RegisteredServer> getAllServers() { public Collection<RegisteredServer> getAllServers() {
lock.readLock().lock();
try {
return ImmutableList.copyOf(servers.values()); return ImmutableList.copyOf(servers.values());
} finally {
lock.readLock().unlock();
}
} }
public RegisteredServer register(ServerInfo serverInfo) { public RegisteredServer register(ServerInfo serverInfo) {
Preconditions.checkNotNull(serverInfo, "serverInfo"); Preconditions.checkNotNull(serverInfo, "serverInfo");
String lowerName = serverInfo.getName().toLowerCase(Locale.US); String lowerName = serverInfo.getName().toLowerCase(Locale.US);
lock.writeLock().lock();
try {
VelocityRegisteredServer rs = new VelocityRegisteredServer(server, serverInfo); VelocityRegisteredServer rs = new VelocityRegisteredServer(server, serverInfo);
Preconditions.checkArgument(servers.putIfAbsent(lowerName, rs) == null, "Server with name %s already registered", serverInfo.getName()); Preconditions.checkArgument(servers.putIfAbsent(lowerName, rs) == null, "Server with name %s already registered", serverInfo.getName());
return rs; return rs;
} finally {
lock.writeLock().unlock();
}
} }
public void unregister(ServerInfo serverInfo) { public void unregister(ServerInfo serverInfo) {
Preconditions.checkNotNull(serverInfo, "serverInfo"); Preconditions.checkNotNull(serverInfo, "serverInfo");
String lowerName = serverInfo.getName().toLowerCase(Locale.US); String lowerName = serverInfo.getName().toLowerCase(Locale.US);
lock.writeLock().lock();
try {
RegisteredServer rs = servers.get(lowerName); RegisteredServer rs = servers.get(lowerName);
Preconditions.checkArgument(rs != null, "Server with name %s is not registered!", serverInfo.getName()); Preconditions.checkArgument(rs != null, "Server with name %s is not registered!", serverInfo.getName());
Preconditions.checkArgument(rs.getServerInfo().equals(serverInfo), "Trying to remove server %s with differing information", serverInfo.getName()); Preconditions.checkArgument(rs.getServerInfo().equals(serverInfo), "Trying to remove server %s with differing information", serverInfo.getName());
servers.remove(lowerName); Preconditions.checkState(servers.remove(lowerName, rs), "Server with name %s replaced whilst unregistering", serverInfo.getName());
} finally {
lock.writeLock().unlock();
}
} }
} }

Datei anzeigen

@ -25,6 +25,7 @@ import io.netty.handler.timeout.ReadTimeoutHandler;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -36,8 +37,7 @@ import static com.velocitypowered.proxy.network.Connections.MINECRAFT_ENCODER;
public class VelocityRegisteredServer implements RegisteredServer { public class VelocityRegisteredServer implements RegisteredServer {
private final VelocityServer server; private final VelocityServer server;
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private final Set<ConnectedPlayer> players = new HashSet<>(); private final Set<ConnectedPlayer> players = ConcurrentHashMap.newKeySet();
private final ReadWriteLock playersLock = new ReentrantReadWriteLock();
public VelocityRegisteredServer(VelocityServer server, ServerInfo serverInfo) { public VelocityRegisteredServer(VelocityServer server, ServerInfo serverInfo) {
this.server = server; this.server = server;
@ -51,12 +51,7 @@ public class VelocityRegisteredServer implements RegisteredServer {
@Override @Override
public Collection<Player> getPlayersConnected() { public Collection<Player> getPlayersConnected() {
playersLock.readLock().lock();
try {
return ImmutableList.copyOf(players); return ImmutableList.copyOf(players);
} finally {
playersLock.readLock().unlock();
}
} }
@Override @Override
@ -94,44 +89,24 @@ public class VelocityRegisteredServer implements RegisteredServer {
} }
public void addPlayer(ConnectedPlayer player) { public void addPlayer(ConnectedPlayer player) {
playersLock.writeLock().lock();
try {
players.add(player); players.add(player);
} finally {
playersLock.writeLock().unlock();
}
} }
public void removePlayer(ConnectedPlayer player) { public void removePlayer(ConnectedPlayer player) {
playersLock.writeLock().lock();
try {
players.remove(player); players.remove(player);
} finally {
playersLock.writeLock().unlock();
}
} }
@Override @Override
public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) { public boolean sendPluginMessage(ChannelIdentifier identifier, byte[] data) {
ServerConnection backendConnection = null;
playersLock.readLock().lock();
try {
for (ConnectedPlayer player : players) { for (ConnectedPlayer player : players) {
if (player.getConnectedServer() != null && player.getConnectedServer().getServerInfo().equals(serverInfo)) { if (player.getConnectedServer() != null && player.getConnectedServer().getServerInfo().equals(serverInfo)) {
backendConnection = player.getConnectedServer(); ServerConnection connection = player.getConnectedServer();
break; return connection.sendPluginMessage(identifier, data);
} }
} }
if (backendConnection == null) {
return false; return false;
} }
} finally {
playersLock.readLock().unlock();
}
return backendConnection.sendPluginMessage(identifier, data);
}
@Override @Override
public String toString() { public String toString() {