use of com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig in project graal by oracle.
the class PolyglotContextImpl method enterThreadChanged.
/**
* Use to enter context if it's guaranteed to be called rarely and configuration flexibility is
* needed. Otherwise use {@link PolyglotEngineImpl#enter(PolyglotContextImpl)}.
*/
@TruffleBoundary
Object[] enterThreadChanged(boolean notifyEnter, boolean enterReverted, boolean pollSafepoint, boolean deactivateSafepoints) {
PolyglotThreadInfo enteredThread = null;
Object[] prev = null;
try {
Thread current = Thread.currentThread();
boolean needsInitialization = false;
synchronized (this) {
PolyglotThreadInfo threadInfo = getCurrentThreadInfo();
if (enterReverted && threadInfo.getEnteredCount() == 0) {
threadLocalActions.notifyThreadActivation(threadInfo, false);
if ((state.isCancelling() || state.isExiting() || state == State.CLOSED_CANCELLED || state == State.CLOSED_EXITED) && !threadInfo.isActive()) {
notifyThreadClosed(threadInfo);
}
if (state.isInterrupting() && !threadInfo.isActive()) {
Thread.interrupted();
notifyAll();
}
}
if (deactivateSafepoints && threadInfo != PolyglotThreadInfo.NULL) {
threadLocalActions.notifyThreadActivation(threadInfo, false);
}
checkClosed();
assert threadInfo != null;
threadInfo = threads.get(current);
if (threadInfo == null) {
threadInfo = createThreadInfo(current);
needsInitialization = true;
}
if (singleThreaded) {
/*
* If this is the only thread, then setting the cached thread info to NULL is no
* performance problem. If there is other thread that is just about to enter, we
* are making sure that it initializes multi-threading if this thread doesn't do
* it.
*/
setCachedThreadInfo(PolyglotThreadInfo.NULL);
}
boolean transitionToMultiThreading = isSingleThreaded() && hasActiveOtherThread(true);
if (transitionToMultiThreading) {
// recheck all thread accesses
checkAllThreadAccesses(Thread.currentThread(), false);
}
if (transitionToMultiThreading) {
/*
* We need to do this early (before initializeMultiThreading) as entering or
* local initialization depends on single thread per context.
*/
engine.singleThreadPerContext.invalidate();
singleThreaded = false;
}
if (needsInitialization) {
threads.put(current, threadInfo);
}
if (needsInitialization) {
/*
* Do not enter the thread before initializing thread locals. Creation of thread
* locals might fail.
*/
initializeThreadLocals(threadInfo);
}
prev = threadInfo.enterInternal();
if (notifyEnter) {
try {
threadInfo.notifyEnter(engine, this);
} catch (Throwable t) {
threadInfo.leaveInternal(prev);
throw t;
}
}
enteredThread = threadInfo;
if (needsInitialization) {
this.threadLocalActions.notifyEnterCreatedThread();
}
// new thread became active so we need to check potential active thread local
// actions and process them.
Set<ThreadLocalAction> activatedActions = null;
if (enteredThread.getEnteredCount() == 1 && !deactivateSafepoints) {
activatedActions = threadLocalActions.notifyThreadActivation(threadInfo, true);
}
if (transitionToMultiThreading) {
// we need to verify that all languages give access
// to all threads in multi-threaded mode.
transitionToMultiThreaded();
}
if (needsInitialization) {
initializeNewThread(current);
}
if (enteredThread.getEnteredCount() == 1 && !pauseThreadLocalActions.isEmpty()) {
for (Iterator<PauseThreadLocalAction> threadLocalActionIterator = pauseThreadLocalActions.iterator(); threadLocalActionIterator.hasNext(); ) {
PauseThreadLocalAction threadLocalAction = threadLocalActionIterator.next();
if (!threadLocalAction.isPause()) {
threadLocalActionIterator.remove();
} else {
if (activatedActions == null || !activatedActions.contains(threadLocalAction)) {
threadLocalActions.submit(new Thread[] { Thread.currentThread() }, PolyglotEngineImpl.ENGINE_ID, threadLocalAction, new HandshakeConfig(true, true, false, false));
}
}
}
}
// never cache last thread on close or when closingThread
setCachedThreadInfo(threadInfo);
}
if (needsInitialization) {
EngineAccessor.INSTRUMENT.notifyThreadStarted(engine, creatorTruffleContext, current);
}
return prev;
} finally {
/*
* We need to always poll the safepoint here in case we already submitted a thread local
* action for this thread. Not polling here would make dependencies of that event wait
* forever.
*/
if (pollSafepoint) {
try {
TruffleSafepoint.pollHere(this.uncachedLocation);
} catch (Throwable t) {
/*
* Just in case a safepoint makes the enter fail we need to leave the context
* again.
*/
if (enteredThread != null) {
this.leaveThreadChanged(prev, notifyEnter, true);
}
throw t;
}
}
}
}
use of com.oracle.truffle.polyglot.PolyglotThreadLocalActions.HandshakeConfig in project graal by oracle.
the class PolyglotContextImpl method pause.
synchronized Future<Void> pause() {
PauseThreadLocalAction pauseAction = new PauseThreadLocalAction(this);
Future<Void> future = threadLocalActions.submit(null, PolyglotEngineImpl.ENGINE_ID, pauseAction, new HandshakeConfig(true, true, false, false));
pauseThreadLocalActions.add(pauseAction);
return new ContextPauseHandle(pauseAction, future);
}
Aggregations