org.netbeans.modules.openide.util.NbMutexEventProvider Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.openide.util;
import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.openide.util.BaseUtilities;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
import org.openide.util.MutexException;
import org.openide.util.Union2;
import org.openide.util.lookup.Lookups;
import org.openide.util.lookup.ServiceProvider;
import org.openide.util.spi.MutexEventProvider;
import org.openide.util.spi.MutexImplementation;
/**
*
* @author Tomas Zezula
*/
@ServiceProvider(service = MutexEventProvider.class, position = 100)
public class NbMutexEventProvider implements MutexEventProvider {
@Override
public MutexImplementation createMutex() {
return new Event();
}
private static final class Event implements MutexImplementation {
@Override
public boolean isReadAccess() {
return javax.swing.SwingUtilities.isEventDispatchThread();
}
@Override
public boolean isWriteAccess() {
return javax.swing.SwingUtilities.isEventDispatchThread();
}
@Override
public void writeAccess(Runnable runnable) {
doEvent(runnable);
}
@Override
public T writeAccess(Mutex.ExceptionAction action) throws MutexException {
return doEventAccess(action);
}
@Override
public void readAccess(Runnable runnable) {
doEvent(runnable);
}
@Override
public T readAccess(Mutex.ExceptionAction action) throws MutexException {
return doEventAccess(action);
}
@Override
public void postReadRequest(Runnable run) {
doEventRequest(run);
}
@Override
public void postWriteRequest(Runnable run) {
doEventRequest(run);
}
@Override
public String toString() {
return "EVENT - Full JRE"; // NOI18N
}
private static void doEvent(Runnable run) {
if (EventQueue.isDispatchThread()) {
run.run();
} else {
Lookup inherit = Lookup.getDefault();
EventQueue.invokeLater(() -> {
Lookups.executeWith(inherit, run);
});
}
}
/** Methods for access to event queue.
* @param run runabble to post later
*/
private static void doEventRequest(Runnable run) {
Lookup inherit = Lookup.getDefault();
EventQueue.invokeLater(() -> {
Lookups.executeWith(inherit, run);
});
}
/** Methods for access to event queue and waiting for result.
* @param run runnable to post later
*/
private static T doEventAccess(final Mutex.ExceptionAction run)
throws MutexException {
if (isDispatchThread()) {
try {
return run.run();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new MutexException(e);
}
}
final AtomicReference> res = new AtomicReference>();
final AtomicBoolean started = new AtomicBoolean(); // #210991
final AtomicBoolean finished = new AtomicBoolean();
final AtomicBoolean invoked = new AtomicBoolean();
final Lookup inherit = Lookup.getDefault();
try {
class AWTWorker implements Runnable {
@Override
public void run() {
started.set(true);
Lookups.executeWith(inherit, () -> {
try {
res.set(Union2.createFirst(run.run()));
} catch (Exception e) {
res.set(Union2.createSecond(e));
} catch (LinkageError e) {
// #20467
res.set(Union2.createSecond(e));
} catch (StackOverflowError e) {
// #20467
res.set(Union2.createSecond(e));
}
});
finished.set(true);
}
}
AWTWorker w = new AWTWorker();
EventQueue.invokeAndWait(w);
invoked.set(true);
} catch (InterruptedException e) {
res.set(Union2.createSecond(e));
} catch (InvocationTargetException e) {
res.set(Union2.createSecond(e));
}
Union2 _res = res.get();
if (_res == null) {
throw new IllegalStateException("#210991: got neither a result nor an exception; started=" + started + " finished=" + finished + " invoked=" + invoked);
} else if (_res.hasFirst()) {
return _res.first();
} else {
Throwable e = _res.second();
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw notifyException(e);
}
}
}
/** @return true iff current thread is EventDispatchThread */
private static boolean isDispatchThread() {
boolean dispatch = EventQueue.isDispatchThread();
if (!dispatch && (BaseUtilities.getOperatingSystem() == BaseUtilities.OS_SOLARIS)) {
// on solaris the event queue is not always recognized correctly
// => try to guess by name
dispatch = (Thread.currentThread().getClass().getName().indexOf("EventDispatchThread") >= 0); // NOI18N
}
return dispatch;
}
/** Notify exception and returns new MutexException */
private static MutexException notifyException(Throwable t) {
if (t instanceof InvocationTargetException) {
t = unfoldInvocationTargetException((InvocationTargetException) t);
}
if (t instanceof Error) {
annotateEventStack(t);
throw (Error) t;
}
if (t instanceof RuntimeException) {
annotateEventStack(t);
throw (RuntimeException) t;
}
MutexException exc = new MutexException((Exception) t);
exc.initCause(t);
return exc;
}
private static void annotateEventStack(Throwable t) {
//ErrorManager.getDefault().annotate(t, new Exception("Caught here in mutex")); // NOI18N
}
private static Throwable unfoldInvocationTargetException(InvocationTargetException e) {
Throwable ret;
do {
ret = e.getTargetException();
if (ret instanceof InvocationTargetException) {
e = (InvocationTargetException) ret;
} else {
e = null;
}
} while (e != null);
return ret;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy