Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-12-24 23:30:26 +01:00
Remove RecordingThreadFactory since it's actually a terrible idea
Dieser Commit ist enthalten in:
Ursprung
2d2258d667
Commit
732caa2d40
@ -9,7 +9,6 @@ import com.velocitypowered.api.event.EventManager;
|
|||||||
import com.velocitypowered.api.event.PostOrder;
|
import com.velocitypowered.api.event.PostOrder;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
import com.velocitypowered.proxy.util.concurrency.RecordingThreadFactory;
|
|
||||||
import net.kyori.event.EventSubscriber;
|
import net.kyori.event.EventSubscriber;
|
||||||
import net.kyori.event.PostResult;
|
import net.kyori.event.PostResult;
|
||||||
import net.kyori.event.SimpleEventBus;
|
import net.kyori.event.SimpleEventBus;
|
||||||
@ -43,14 +42,12 @@ public class VelocityEventManager implements EventManager {
|
|||||||
new ASMEventExecutorFactory<>(new PluginClassLoader(new URL[0])),
|
new ASMEventExecutorFactory<>(new PluginClassLoader(new URL[0])),
|
||||||
new VelocityMethodScanner());
|
new VelocityMethodScanner());
|
||||||
private final ExecutorService service;
|
private final ExecutorService service;
|
||||||
private final RecordingThreadFactory recordingThreadFactory;
|
|
||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
|
|
||||||
public VelocityEventManager(PluginManager pluginManager) {
|
public VelocityEventManager(PluginManager pluginManager) {
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
this.recordingThreadFactory = new RecordingThreadFactory(new ThreadFactoryBuilder()
|
this.service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactoryBuilder()
|
||||||
.setNameFormat("Velocity Event Executor - #%d").setDaemon(true).build());
|
.setNameFormat("Velocity Event Executor - #%d").setDaemon(true).build());
|
||||||
this.service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(), recordingThreadFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -88,17 +85,11 @@ public class VelocityEventManager implements EventManager {
|
|||||||
logger.error("Some errors occurred whilst posting event {}.", event);
|
logger.error("Some errors occurred whilst posting event {}.", event);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Throwable exception : result.exceptions().values()) {
|
for (Throwable exception : result.exceptions().values()) {
|
||||||
logger.error("#{}: \n", i++, exception);
|
logger.error("#{}: \n", ++i, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (recordingThreadFactory.currentlyInFactory()) {
|
|
||||||
// Optimization: fire the event immediately, we are on the event handling thread.
|
|
||||||
runEvent.run();
|
|
||||||
return CompletableFuture.completedFuture(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<E> eventFuture = new CompletableFuture<>();
|
CompletableFuture<E> eventFuture = new CompletableFuture<>();
|
||||||
service.execute(() -> {
|
service.execute(() -> {
|
||||||
runEvent.run();
|
runEvent.run();
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package com.velocitypowered.proxy.util.concurrency;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link ThreadFactory} that records the threads it has created. Once a thread terminates, it is automatically removed
|
|
||||||
* from the recorder.
|
|
||||||
*/
|
|
||||||
public class RecordingThreadFactory implements ThreadFactory {
|
|
||||||
private final ThreadFactory backing;
|
|
||||||
private final Set<Thread> threads = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
|
||||||
|
|
||||||
public RecordingThreadFactory(ThreadFactory backing) {
|
|
||||||
this.backing = Preconditions.checkNotNull(backing, "backing");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Thread newThread(Runnable runnable) {
|
|
||||||
Preconditions.checkNotNull(runnable, "runnable");
|
|
||||||
return backing.newThread(() -> {
|
|
||||||
threads.add(Thread.currentThread());
|
|
||||||
try {
|
|
||||||
runnable.run();
|
|
||||||
} finally {
|
|
||||||
threads.remove(Thread.currentThread());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean currentlyInFactory() {
|
|
||||||
return threads.contains(Thread.currentThread());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
int size() {
|
|
||||||
return threads.size();
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
class VelocitySchedulerTest {
|
class VelocitySchedulerTest {
|
||||||
// TODO: The timings here will be inaccurate on slow systems. Need to find a testing-friendly replacement for Thread.sleep()
|
// TODO: The timings here will be inaccurate on slow systems.
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void buildTask() throws Exception {
|
void buildTask() throws Exception {
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
package com.velocitypowered.proxy.util.concurrency;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
class RecordingThreadFactoryTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void newThread() throws Exception {
|
|
||||||
RecordingThreadFactory factory = new RecordingThreadFactory(Executors.defaultThreadFactory());
|
|
||||||
CountDownLatch started = new CountDownLatch(1);
|
|
||||||
CountDownLatch endThread = new CountDownLatch(1);
|
|
||||||
factory.newThread(() -> {
|
|
||||||
started.countDown();
|
|
||||||
assertTrue(factory.currentlyInFactory());
|
|
||||||
assertEquals(1, factory.size());
|
|
||||||
try {
|
|
||||||
endThread.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
started.await();
|
|
||||||
assertFalse(factory.currentlyInFactory());
|
|
||||||
assertEquals(1, factory.size());
|
|
||||||
endThread.countDown();
|
|
||||||
|
|
||||||
// Wait a little bit to ensure the thread got shut down
|
|
||||||
Thread.sleep(10);
|
|
||||||
assertEquals(0, factory.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void cleanUpAfterExceptionThrown() throws Exception {
|
|
||||||
CountDownLatch started = new CountDownLatch(1);
|
|
||||||
CountDownLatch endThread = new CountDownLatch(1);
|
|
||||||
CountDownLatch hasEnded = new CountDownLatch(1);
|
|
||||||
RecordingThreadFactory factory = new RecordingThreadFactory((ThreadFactory) r -> {
|
|
||||||
Thread t = new Thread(r);
|
|
||||||
t.setUncaughtExceptionHandler((t1, e) -> hasEnded.countDown());
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
factory.newThread(() -> {
|
|
||||||
started.countDown();
|
|
||||||
assertTrue(factory.currentlyInFactory());
|
|
||||||
assertEquals(1, factory.size());
|
|
||||||
try {
|
|
||||||
endThread.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e);
|
|
||||||
}
|
|
||||||
throw new RuntimeException("");
|
|
||||||
}).start();
|
|
||||||
started.await();
|
|
||||||
assertFalse(factory.currentlyInFactory());
|
|
||||||
assertEquals(1, factory.size());
|
|
||||||
endThread.countDown();
|
|
||||||
hasEnded.await();
|
|
||||||
|
|
||||||
// Wait a little bit to ensure the thread got shut down
|
|
||||||
Thread.sleep(10);
|
|
||||||
assertEquals(0, factory.size());
|
|
||||||
}
|
|
||||||
}
|
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren