Skip to content

Commit 7bc16de

Browse files
committed
%time magic #104
eval within eval should be called on the same thread
1 parent f78dd3c commit 7bc16de

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

jjava-kernel/src/main/java/org/dflib/jjava/kernel/execution/JJavaExecutionControl.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
import java.util.Objects;
1111
import java.util.UUID;
1212
import java.util.concurrent.CancellationException;
13+
import java.util.concurrent.CompletableFuture;
1314
import java.util.concurrent.ConcurrentHashMap;
1415
import java.util.concurrent.ExecutionException;
1516
import java.util.concurrent.ExecutorService;
1617
import java.util.concurrent.Executors;
1718
import java.util.concurrent.Future;
19+
import java.util.concurrent.ThreadLocalRandom;
1820
import java.util.concurrent.TimeUnit;
1921
import java.util.concurrent.TimeoutException;
2022
import java.util.concurrent.atomic.AtomicInteger;
@@ -24,12 +26,20 @@
2426
* also logs the actual result of an invocation before being serialized.
2527
*/
2628
public class JJavaExecutionControl extends DirectExecutionControl {
29+
30+
// generate a semi-unique thread name prefix for each JVM run for easier detection of
31+
// JJavaExecutionControl-produced threads
32+
private static final String THREAD_NAME_PREFIX = "jjava-exec-"
33+
+ ThreadLocalRandom.current().ints(6, 'a', 'z' + 1).collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
34+
+ "-";
35+
2736
/**
2837
* A special "class name" for a {@link jdk.jshell.spi.ExecutionControl.UserException} such that it may be
2938
* identified after serialization into an {@link jdk.jshell.EvalException} via {@link
3039
* EvalException#getExceptionClassName()}.
3140
*/
32-
public static final String EXECUTION_TIMEOUT_NAME = "Execution Timeout"; // Has spaces to not collide with a class name
41+
// Has spaces to not collide with a class name
42+
public static final String EXECUTION_TIMEOUT_NAME = "Execution Timeout";
3343

3444
/**
3545
* A special "class name" for a {@link jdk.jshell.spi.ExecutionControl.UserException} such that it may be
@@ -56,7 +66,7 @@ public JJavaExecutionControl(JJavaLoaderDelegate loaderDelegate, long timeoutDur
5666

5767
this.timeoutDuration = timeoutDuration;
5868
this.timeoutUnit = timeoutDuration > 0 ? Objects.requireNonNull(timeoutUnit) : TimeUnit.MILLISECONDS;
59-
this.executor = Executors.newCachedThreadPool(r -> new Thread(r, "JJava-executor-" + EXECUTOR_THREAD_ID.getAndIncrement()));
69+
this.executor = Executors.newCachedThreadPool(r -> new Thread(r, THREAD_NAME_PREFIX + EXECUTOR_THREAD_ID.getAndIncrement()));
6070
}
6171

6272
/**
@@ -121,7 +131,12 @@ public String toString() {
121131

122132
private Object execute(String id, Method doitMethod) throws Exception {
123133

124-
Future<Object> runningTask = executor.submit(() -> doitMethod.invoke(null));
134+
// run on the same thread if an execution was called within another execution
135+
boolean alreadyRunByKernel = Thread.currentThread().getName().startsWith(THREAD_NAME_PREFIX);
136+
Future<Object> runningTask = alreadyRunByKernel
137+
? CompletableFuture.completedFuture(doitMethod.invoke(null))
138+
: executor.submit(() -> doitMethod.invoke(null));
139+
125140
running.put(id, runningTask);
126141

127142
try {

jjava-kernel/src/main/java/org/dflib/jjava/kernel/magics/TimeMagic.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public DisplayData eval(JavaKernel kernel, List<String> args, String body) throw
2828
}
2929

3030
private DisplayData timeAndRunCode(JavaKernel kernel, String code) {
31-
31+
System.out.println("TimeMagic thread: " + Thread.currentThread().getName());
3232
return kernel.evalBuilder(code)
3333
.resolveMagics()
3434
.renderResults()

0 commit comments

Comments
 (0)