Skip to content

Commit 4f062df

Browse files
Add lavaplayer tools that aren't compatible with current commons
1 parent 498c91a commit 4f062df

File tree

4 files changed

+220
-2
lines changed

4 files changed

+220
-2
lines changed

api/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repositories {
88
}
99

1010
dependencies {
11-
implementation("com.sedmelluq:lava-common:1.1.0")
11+
implementation("com.sedmelluq:lava-common:1.1.2")
1212
implementation("org.slf4j:slf4j-api:1.7.25")
1313
}
1414

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.sedmelluq.discord.lavaplayer.tools;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.util.concurrent.ThreadFactory;
7+
import java.util.concurrent.atomic.AtomicInteger;
8+
9+
/**
10+
* Thread factory for daemon threads.
11+
*/
12+
public class DaemonThreadFactory implements ThreadFactory {
13+
private static final Logger log = LoggerFactory.getLogger(DaemonThreadFactory.class);
14+
15+
private static final AtomicInteger poolNumber = new AtomicInteger(1);
16+
private final ThreadGroup group;
17+
private final AtomicInteger threadNumber = new AtomicInteger(1);
18+
private final String namePrefix;
19+
private final Runnable exitCallback;
20+
21+
/**
22+
* @param name Name that will be included in thread names.
23+
*/
24+
public DaemonThreadFactory(String name) {
25+
this(name, null);
26+
}
27+
28+
/**
29+
* @param name Name that will be included in thread names.
30+
* @param exitCallback Runnable to be executed when the thread exits.
31+
*/
32+
public DaemonThreadFactory(String name, Runnable exitCallback) {
33+
SecurityManager securityManager = System.getSecurityManager();
34+
35+
group = (securityManager != null) ? securityManager.getThreadGroup() : Thread.currentThread().getThreadGroup();
36+
namePrefix = "lava-daemon-pool-" + name + "-" + poolNumber.getAndIncrement() + "-thread-";
37+
this.exitCallback = exitCallback;
38+
}
39+
40+
@Override
41+
public Thread newThread(Runnable runnable) {
42+
Thread thread = new Thread(group, getThreadRunnable(runnable), namePrefix + threadNumber.getAndIncrement(), 0);
43+
thread.setDaemon(true);
44+
thread.setPriority(Thread.NORM_PRIORITY);
45+
return thread;
46+
}
47+
48+
private Runnable getThreadRunnable(Runnable target) {
49+
if (exitCallback == null) {
50+
return target;
51+
} else {
52+
return new ExitCallbackRunnable(target);
53+
}
54+
}
55+
56+
private class ExitCallbackRunnable implements Runnable {
57+
private final Runnable original;
58+
59+
private ExitCallbackRunnable(Runnable original) {
60+
this.original = original;
61+
}
62+
63+
@Override
64+
public void run() {
65+
try {
66+
if (original != null) {
67+
original.run();
68+
}
69+
} finally {
70+
wrapExitCallback();
71+
}
72+
}
73+
74+
private void wrapExitCallback() {
75+
boolean wasInterrupted = Thread.interrupted();
76+
77+
try {
78+
exitCallback.run();
79+
} catch (Throwable throwable) {
80+
log.error("Thread exit notification threw an exception.", throwable);
81+
} finally {
82+
if (wasInterrupted) {
83+
Thread.currentThread().interrupt();
84+
}
85+
}
86+
}
87+
}
88+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package com.sedmelluq.discord.lavaplayer.tools;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.util.concurrent.ExecutionException;
7+
import java.util.concurrent.ExecutorService;
8+
import java.util.concurrent.Future;
9+
import java.util.concurrent.LinkedBlockingQueue;
10+
import java.util.concurrent.RejectedExecutionException;
11+
import java.util.concurrent.RejectedExecutionHandler;
12+
import java.util.concurrent.ThreadFactory;
13+
import java.util.concurrent.ThreadPoolExecutor;
14+
import java.util.concurrent.TimeUnit;
15+
import java.util.concurrent.TimeoutException;
16+
17+
/**
18+
* Utility methods for working with executors.
19+
*/
20+
public class ExecutorTools {
21+
private static final Logger log = LoggerFactory.getLogger(ExecutorTools.class);
22+
23+
private static final long WAIT_TIME = 1000L;
24+
25+
/**
26+
* A completed Future<Void> instance.
27+
*/
28+
public static final CompletedVoidFuture COMPLETED_VOID = new CompletedVoidFuture();
29+
30+
/**
31+
* Shut down an executor and log the shutdown result. The executor is given a fixed amount of time to shut down, if it
32+
* does not manage to do it in that time, then this method just returns.
33+
*
34+
* @param executorService Executor service to shut down
35+
* @param description Description of the service to use for logging
36+
*/
37+
public static void shutdownExecutor(ExecutorService executorService, String description) {
38+
if (executorService == null) {
39+
return;
40+
}
41+
42+
log.debug("Shutting down executor {}", description);
43+
44+
executorService.shutdownNow();
45+
46+
try {
47+
if (!executorService.awaitTermination(WAIT_TIME, TimeUnit.MILLISECONDS)) {
48+
log.debug("Executor {} did not shut down in {}", description, WAIT_TIME);
49+
} else {
50+
log.debug("Executor {} successfully shut down", description);
51+
}
52+
} catch (InterruptedException e) {
53+
log.debug("Received an interruption while shutting down executor {}", description);
54+
Thread.currentThread().interrupt();
55+
}
56+
}
57+
58+
/**
59+
* Creates an executor which will use the queue only when maximum number of threads has been reached. The core pool
60+
* size here only means the number of threads that are always alive, it is no longer used to check whether a new
61+
* thread should start or not. The maximum size is otherwise pointless unless you have a bounded queue, which in turn
62+
* would cause tasks to be rejected if it is too small.
63+
*
64+
* @param coreSize Number of threads that are always alive
65+
* @param maximumSize The maximum number of threads in the pool
66+
* @param timeout Non-core thread timeout in milliseconds
67+
* @param threadFactory Thread factory to create pool threads with
68+
* @return An eagerly scaling thread pool executor
69+
*/
70+
public static ThreadPoolExecutor createEagerlyScalingExecutor(int coreSize, int maximumSize, long timeout,
71+
int queueCapacity, ThreadFactory threadFactory) {
72+
73+
ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, maximumSize, timeout, TimeUnit.MILLISECONDS,
74+
new EagerlyScalingTaskQueue(queueCapacity), threadFactory);
75+
76+
executor.setRejectedExecutionHandler(new EagerlyScalingRejectionHandler());
77+
return executor;
78+
}
79+
80+
private static class EagerlyScalingTaskQueue extends LinkedBlockingQueue<Runnable> {
81+
public EagerlyScalingTaskQueue(int capacity) {
82+
super(capacity);
83+
}
84+
85+
@Override
86+
public boolean offer(Runnable runnable) {
87+
return isEmpty() && super.offer(runnable);
88+
}
89+
90+
public boolean offerDirectly(Runnable runnable) {
91+
return super.offer(runnable);
92+
}
93+
}
94+
95+
private static class EagerlyScalingRejectionHandler implements RejectedExecutionHandler {
96+
@Override
97+
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
98+
if (!((EagerlyScalingTaskQueue) executor.getQueue()).offerDirectly(runnable)) {
99+
throw new RejectedExecutionException("Task " + runnable.toString() + " rejected from " + runnable.toString());
100+
}
101+
}
102+
}
103+
104+
private static class CompletedVoidFuture implements Future<Void> {
105+
@Override
106+
public boolean cancel(boolean mayInterruptIfRunning) {
107+
return false;
108+
}
109+
110+
@Override
111+
public boolean isCancelled() {
112+
return false;
113+
}
114+
115+
@Override
116+
public boolean isDone() {
117+
return true;
118+
}
119+
120+
@Override
121+
public Void get() throws InterruptedException, ExecutionException {
122+
return null;
123+
}
124+
125+
@Override
126+
public Void get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
127+
return null;
128+
}
129+
}
130+
}

native/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ tasks.create<Copy>("moveResources") {
2222
from("target/$target/release/")
2323

2424
include {
25-
it.name.endsWith(".so") || it.name.endsWith(".dll") || it.name.endsWith(".dylib")
25+
it.name == "release" || it.name.endsWith(".so") || it.name.endsWith(".dll") || it.name.endsWith(".dylib")
2626
}
2727

2828
into("src/main/resources/natives/$platform")

0 commit comments

Comments
 (0)