Search in sources :

Example 1 with LanguageContext

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());
}
Also used : ThreadRequest(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.ThreadRequest) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) PolyglotException(org.graalvm.polyglot.PolyglotException) Env(com.oracle.truffle.api.TruffleLanguage.Env) TimeoutException(java.util.concurrent.TimeoutException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Assert.assertSame(org.junit.Assert.assertSame) HashSet(java.util.HashSet) Future(java.util.concurrent.Future) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) After(org.junit.After) Assert.fail(org.junit.Assert.fail) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) Assert.assertNotNull(org.junit.Assert.assertNotNull) Semaphore(java.util.concurrent.Semaphore) Value(org.graalvm.polyglot.Value) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Assert.assertTrue(org.junit.Assert.assertTrue) Set(java.util.Set) Test(org.junit.Test) Executors(java.util.concurrent.Executors) TruffleContext(com.oracle.truffle.api.TruffleContext) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Assert.assertNull(org.junit.Assert.assertNull) Engine(org.graalvm.polyglot.Engine) Entry(java.util.Map.Entry) Context(org.graalvm.polyglot.Context) Assert(org.junit.Assert) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) TruffleContext(com.oracle.truffle.api.TruffleContext) Context(org.graalvm.polyglot.Context) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) TruffleContext(com.oracle.truffle.api.TruffleContext) AtomicReference(java.util.concurrent.atomic.AtomicReference) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) Env(com.oracle.truffle.api.TruffleLanguage.Env) ArrayList(java.util.ArrayList) List(java.util.List) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Test(org.junit.Test)

Example 2 with LanguageContext

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();
}
Also used : TruffleContext(com.oracle.truffle.api.TruffleContext) Context(org.graalvm.polyglot.Context) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) ThreadRequest(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.ThreadRequest) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) PolyglotException(org.graalvm.polyglot.PolyglotException) Env(com.oracle.truffle.api.TruffleLanguage.Env) TimeoutException(java.util.concurrent.TimeoutException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Assert.assertSame(org.junit.Assert.assertSame) HashSet(java.util.HashSet) Future(java.util.concurrent.Future) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) After(org.junit.After) Assert.fail(org.junit.Assert.fail) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) Assert.assertNotNull(org.junit.Assert.assertNotNull) Semaphore(java.util.concurrent.Semaphore) Value(org.graalvm.polyglot.Value) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Assert.assertTrue(org.junit.Assert.assertTrue) Set(java.util.Set) Test(org.junit.Test) Executors(java.util.concurrent.Executors) TruffleContext(com.oracle.truffle.api.TruffleContext) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Assert.assertNull(org.junit.Assert.assertNull) Engine(org.graalvm.polyglot.Engine) Entry(java.util.Map.Entry) Context(org.graalvm.polyglot.Context) Assert(org.junit.Assert) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) TruffleContext(com.oracle.truffle.api.TruffleContext) AtomicReference(java.util.concurrent.atomic.AtomicReference) Env(com.oracle.truffle.api.TruffleLanguage.Env) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) ArrayList(java.util.ArrayList) List(java.util.List) ExecutionException(java.util.concurrent.ExecutionException) Engine(org.graalvm.polyglot.Engine) Test(org.junit.Test)

Example 3 with LanguageContext

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());
}
Also used : ThreadRequest(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.ThreadRequest) TruffleContext(com.oracle.truffle.api.TruffleContext) Context(org.graalvm.polyglot.Context) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) ThreadRequest(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.ThreadRequest) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) PolyglotException(org.graalvm.polyglot.PolyglotException) Env(com.oracle.truffle.api.TruffleLanguage.Env) TimeoutException(java.util.concurrent.TimeoutException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) ArrayList(java.util.ArrayList) Assert.assertSame(org.junit.Assert.assertSame) HashSet(java.util.HashSet) Future(java.util.concurrent.Future) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) After(org.junit.After) Assert.fail(org.junit.Assert.fail) ExecutorService(java.util.concurrent.ExecutorService) Before(org.junit.Before) Assert.assertNotNull(org.junit.Assert.assertNotNull) Semaphore(java.util.concurrent.Semaphore) Value(org.graalvm.polyglot.Value) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Assert.assertTrue(org.junit.Assert.assertTrue) Set(java.util.Set) Test(org.junit.Test) Executors(java.util.concurrent.Executors) TruffleContext(com.oracle.truffle.api.TruffleContext) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Consumer(java.util.function.Consumer) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) Assert.assertNull(org.junit.Assert.assertNull) Engine(org.graalvm.polyglot.Engine) Entry(java.util.Map.Entry) Context(org.graalvm.polyglot.Context) Assert(org.junit.Assert) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) LanguageContext(com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext) ArrayList(java.util.ArrayList) AtomicReference(java.util.concurrent.atomic.AtomicReference) CountDownLatch(java.util.concurrent.CountDownLatch) ExecutorService(java.util.concurrent.ExecutorService) Value(org.graalvm.polyglot.Value) Test(org.junit.Test)

Aggregations

TruffleContext (com.oracle.truffle.api.TruffleContext)3 Env (com.oracle.truffle.api.TruffleLanguage.Env)3 LanguageContext (com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.LanguageContext)3 ThreadRequest (com.oracle.truffle.api.test.polyglot.MultiThreadedLanguage.ThreadRequest)3 UncaughtExceptionHandler (java.lang.Thread.UncaughtExceptionHandler)3 ArrayList (java.util.ArrayList)3 Collections (java.util.Collections)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 List (java.util.List)3 Map (java.util.Map)3 Entry (java.util.Map.Entry)3 Set (java.util.Set)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 CountDownLatch (java.util.concurrent.CountDownLatch)3 ExecutionException (java.util.concurrent.ExecutionException)3 ExecutorService (java.util.concurrent.ExecutorService)3 Executors (java.util.concurrent.Executors)3 Future (java.util.concurrent.Future)3 Semaphore (java.util.concurrent.Semaphore)3