use of com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext in project graal by oracle.
the class MultiThreadedLanguageTest method testAccessTruffleContextFromExclusivePolyglotThread.
@Test
public void testAccessTruffleContextFromExclusivePolyglotThread() throws Throwable {
// don't allow multi-threading in this test as every context
// is used exclusively by one thread.
MultiThreadedLanguage.isThreadAccessAllowed = (req) -> {
return req.singleThreaded;
};
final int iterations = 10;
final int innerIterations = 10;
AtomicReference<Throwable> lastError = new AtomicReference<>();
UncaughtExceptionHandler uncaughtHandler = (run, e) -> lastError.set(e);
Context polyglotContext = Context.newBuilder().allowCreateThread(true).build();
ConcurrentHashMap<LanguageContext, String> seenContexts = new ConcurrentHashMap<>();
eval(polyglotContext, new Function<Env, Object>() {
@SuppressWarnings("hiding")
public Object apply(Env env) {
List<Thread> threads = new ArrayList<>();
List<TruffleContext> contexts = new ArrayList<>();
for (int i = 0; i < iterations; i++) {
TruffleContext context = env.newContextBuilder().build();
Thread thread = env.createThread(() -> {
assertUniqueContext();
List<Thread> innerThreads = new ArrayList<>();
List<TruffleContext> innerContexts = new ArrayList<>();
for (int j = 0; j < innerIterations; j++) {
TruffleContext innerContext = env.newContextBuilder().build();
Thread innerThread = env.createThread(() -> {
assertUniqueContext();
}, innerContext);
innerThread.setUncaughtExceptionHandler(uncaughtHandler);
innerThread.start();
innerThreads.add(innerThread);
innerContexts.add(innerContext);
}
for (Thread innerThread : innerThreads) {
try {
innerThread.join();
} catch (InterruptedException e) {
}
}
for (TruffleContext innerContext : innerContexts) {
innerContext.close();
}
}, context);
thread.setUncaughtExceptionHandler(uncaughtHandler);
thread.start();
threads.add(thread);
contexts.add(context);
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
}
}
for (TruffleContext context : contexts) {
context.close();
}
return null;
}
private LanguageContext assertUniqueContext() {
LanguageContext languageContext = MultiThreadedLanguage.getContext();
Assert.assertNotNull(languageContext);
Assert.assertFalse(seenContexts.containsKey(languageContext));
seenContexts.put(languageContext, "");
return languageContext;
}
});
Assert.assertEquals(221, initializeCount.get());
Assert.assertEquals(initializeCount.get() - 1, disposeCount.get());
Assert.assertEquals(0, initializeMultiThreadingCount.get());
// Test that the same context is available in threads when created with Env.getContext()
MultiThreadedLanguage.isThreadAccessAllowed = (req) -> {
return true;
};
eval(polyglotContext, new Function<Env, Object>() {
@SuppressWarnings("hiding")
public Object apply(Env env) {
List<Thread> threads = new ArrayList<>();
LanguageContext languageContext = MultiThreadedLanguage.getContext();
for (int i = 0; i < iterations; i++) {
Thread thread = env.createThread(() -> {
LanguageContext threadContext = MultiThreadedLanguage.getContext();
assertSame(languageContext, threadContext);
List<Thread> innerThreads = new ArrayList<>();
List<TruffleContext> innerContexts = new ArrayList<>();
for (int j = 0; j < innerIterations; j++) {
Thread innerThread = env.createThread(() -> {
LanguageContext innerThreadContext = MultiThreadedLanguage.getContext();
assertSame(languageContext, innerThreadContext);
}, env.getContext());
innerThread.setUncaughtExceptionHandler(uncaughtHandler);
innerThread.start();
innerThreads.add(innerThread);
}
for (Thread innerThread : innerThreads) {
try {
innerThread.join();
} catch (InterruptedException e) {
}
}
for (TruffleContext innerContext : innerContexts) {
innerContext.close();
}
}, env.getContext());
thread.setUncaughtExceptionHandler(uncaughtHandler);
thread.start();
threads.add(thread);
}
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
}
}
return null;
}
});
if (lastError.get() != null) {
throw lastError.get();
}
polyglotContext.close();
Assert.assertEquals(331, initializeCount.get());
Assert.assertEquals(initializeCount.get(), disposeCount.get());
Assert.assertEquals(1, initializeMultiThreadingCount.get());
}
use of com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext in project graal by oracle.
the class MultiThreadedLanguageTest method testAccessTruffleContextPolyglotThread.
@Test
public void testAccessTruffleContextPolyglotThread() throws Throwable {
MultiThreadedLanguage.isThreadAccessAllowed = (req) -> {
return true;
};
Engine engine = Engine.create();
AtomicReference<Throwable> seenError = new AtomicReference<>();
Context context = Context.newBuilder().allowCreateThread(true).engine(engine).build();
eval(context, new Function<Env, Object>() {
public Object apply(Env env) {
List<Thread> createdThreads = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(10, (r) -> {
Thread t = env.createThread(r);
t.setUncaughtExceptionHandler((thread, e) -> seenError.set(e));
createdThreads.add(t);
return t;
});
TruffleContext innerContext = env.newContextBuilder().build();
List<Future<LanguageContext>> futures = new ArrayList<>();
List<Future<LanguageContext>> innerContextFutures = new ArrayList<>();
for (int i = 0; i < 100; i++) {
innerContextFutures.add(service.submit(() -> {
Object prev = innerContext.enter();
try {
return MultiThreadedLanguage.getContext();
} finally {
innerContext.leave(prev);
}
}));
}
for (int i = 0; i < 100; i++) {
futures.add(service.submit(() -> {
return MultiThreadedLanguage.getContext();
}));
}
try {
for (Future<LanguageContext> future : futures) {
assertSame(MultiThreadedLanguage.getContext(), future.get());
}
LanguageContext innerLanguageContext;
Object prev = innerContext.enter();
innerLanguageContext = MultiThreadedLanguage.getContext();
innerContext.leave(prev);
for (Future<LanguageContext> future : innerContextFutures) {
assertSame(innerLanguageContext, future.get());
}
innerContext.close();
} catch (InterruptedException e1) {
throw new AssertionError(e1);
} catch (ExecutionException e1) {
throw new AssertionError(e1);
}
service.shutdown();
/*
* We need to join all threads as unfortunately the executor service does not
* guarantee that all threads are immediately shutdown.
*/
try {
for (Thread t : createdThreads) {
t.join(1000);
}
} catch (InterruptedException e1) {
throw new AssertionError(e1);
}
return MultiThreadedLanguage.getContext();
}
});
if (seenError.get() != null) {
throw seenError.get();
}
engine.close();
}
use of com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext in project graal by oracle.
the class MultiThreadedLanguageTest method testMultiThreading.
@Test
public void testMultiThreading() throws InterruptedException, ExecutionException {
AtomicReference<ThreadRequest> lastIsAllowedRequest = new AtomicReference<>(null);
MultiThreadedLanguage.isThreadAccessAllowed = (req) -> {
lastIsAllowedRequest.set(req);
return true;
};
final int threadCount = 10;
final int outerLoop = 10;
final int innerLoop = 100;
ExecutorService executor = createExecutor(threadCount);
for (int outerIter = 0; outerIter < outerLoop; outerIter++) {
resetData();
Context context = Context.create(MultiThreadedLanguage.ID);
assertEquals(0, initializeCount.get());
assertNull(lastInitializeRequest.get());
List<Completable<Value>> results = new ArrayList<>();
for (int iteration = 0; iteration < innerLoop; iteration++) {
CountDownLatch latch = iteration == 0 ? new CountDownLatch(threadCount) : null;
Value value = eval(context, (env) -> new Object());
for (int i = 0; i < threadCount; i++) {
results.add(evalAndWait(executor, context, iteration == 0, latch, (ev) -> MultiThreadedLanguage.getContext()));
}
assertUnsupportedOrNoError(value, Value::execute);
assertUnsupportedOrNoError(value, Value::isBoolean);
assertUnsupportedOrNoError(value, Value::isHostObject);
assertUnsupportedOrNoError(value, Value::isNativePointer);
assertUnsupportedOrNoError(value, Value::isNull);
assertUnsupportedOrNoError(value, Value::isNumber);
assertUnsupportedOrNoError(value, Value::isString);
assertUnsupportedOrNoError(value, Value::fitsInByte);
assertUnsupportedOrNoError(value, Value::fitsInDouble);
assertUnsupportedOrNoError(value, Value::fitsInFloat);
assertUnsupportedOrNoError(value, Value::fitsInInt);
assertUnsupportedOrNoError(value, Value::fitsInLong);
assertUnsupportedOrNoError(value, Value::asBoolean);
assertUnsupportedOrNoError(value, Value::asByte);
assertUnsupportedOrNoError(value, Value::asDouble);
assertUnsupportedOrNoError(value, Value::asFloat);
assertUnsupportedOrNoError(value, Value::asHostObject);
assertUnsupportedOrNoError(value, Value::asInt);
assertUnsupportedOrNoError(value, Value::asLong);
assertUnsupportedOrNoError(value, Value::asNativePointer);
assertUnsupportedOrNoError(value, Value::asString);
assertUnsupportedOrNoError(value, Value::getArraySize);
assertUnsupportedOrNoError(value, Value::getMemberKeys);
assertUnsupportedOrNoError(value, Value::getMetaObject);
assertUnsupportedOrNoError(value, (v) -> v.getMember(""));
assertUnsupportedOrNoError(value, (v) -> v.putMember("", null));
assertUnsupportedOrNoError(value, (v) -> v.hasMember(""));
assertUnsupportedOrNoError(value, (v) -> v.canExecute());
assertUnsupportedOrNoError(value, (v) -> v.getArraySize());
assertUnsupportedOrNoError(value, (v) -> v.getArrayElement(0));
assertUnsupportedOrNoError(value, (v) -> v.setArrayElement(0, null));
// we need to wait for them once to ensure every thread is initialized
if (iteration == 0) {
latch.await();
for (Completable<Value> future : results) {
future.complete();
}
}
}
for (Completable<Value> future : results) {
Object languageContext = future.get().asHostObject();
assertSame(MultiThreadedLanguage.langContext, languageContext);
}
assertEquals(threadCount + 1, initializeCount.get());
assertEquals(1, initializeMultiThreadingCount.get());
assertEquals(false, lastIsAllowedRequest.get().singleThreaded);
context.close();
// main thread gets initialized after close as well
assertEquals(false, lastIsAllowedRequest.get().singleThreaded);
assertEquals(1, initializeMultiThreadingCount.get());
assertEquals(threadCount + 1, initializeCount.get());
assertEquals(threadCount + 1, disposeCount.get());
}
assertTrue(executor.shutdownNow().isEmpty());
}
Aggregations