Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/DisplayDsfExecutor.java')
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/DisplayDsfExecutor.java258
1 files changed, 258 insertions, 0 deletions
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/DisplayDsfExecutor.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/DisplayDsfExecutor.java
new file mode 100644
index 00000000000..46fbbed0c50
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/DisplayDsfExecutor.java
@@ -0,0 +1,258 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.ui.concurrent;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.dsf.concurrent.DefaultDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutable;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * DSF executor which uses the display thread to run the submitted runnables
+ * and callables. The implementation is based on the default DSF executor
+ * which still creates its own thread. However this thread blocks when running
+ * each executable in the display thread.
+ */
+public class DisplayDsfExecutor extends DefaultDsfExecutor
+{
+ /**
+ * Internal mapping of display objects to executors.
+ */
+ private static Map<Display, DisplayDsfExecutor> fExecutors = Collections.synchronizedMap( new HashMap<Display, DisplayDsfExecutor>() );
+
+ /**
+ * Factory method for display executors.
+ * @param display Display to create an executor for.
+ * @return The new (or re-used) executor.
+ */
+ public static DisplayDsfExecutor getDisplayDsfExecutor(Display display) {
+ synchronized (fExecutors) {
+ DisplayDsfExecutor executor = fExecutors.get(display);
+ if (executor == null) {
+ executor = new DisplayDsfExecutor(display);
+ fExecutors.put(display, executor);
+ }
+ return executor;
+ }
+ }
+
+ /**
+ * The display class used by this executor to execute the submitted runnables.
+ */
+ private final Display fDisplay;
+
+ private DisplayDsfExecutor(Display display) {
+ super("Display DSF Executor"); //$NON-NLS-1$
+ fDisplay = display;
+ fDisplay.addListener(SWT.Dispose, new Listener() {
+ public void handleEvent(Event event) {
+ if (event.type == SWT.Dispose) {
+ DisplayDsfExecutor.super.shutdownNow();
+ }
+ }
+ });
+ }
+
+ /**
+ * Override to check if we're in the display thread rather than the helper
+ * thread of the super-class.
+ */
+ @Override
+ public boolean isInExecutorThread() {
+ return Thread.currentThread().equals(fDisplay.getThread());
+ }
+
+ /**
+ * Creates a callable wrapper, which delegates to the display to perform the
+ * operation. The callable blocks the executor thread while each call
+ * is executed in the display thred.
+ * @param <V> Type used in the callable.
+ * @param callable Callable to wrap.
+ * @return Wrapper callable.
+ */
+ private <V> Callable<V> createSWTDispatchCallable(final Callable<V> callable) {
+ // Check if executable wasn't executed already.
+ if (DEBUG_EXECUTOR && callable instanceof DsfExecutable) {
+ assert !((DsfExecutable)callable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
+ ((DsfExecutable)callable).setSubmitted();
+ }
+
+ return new Callable<V>() {
+ @SuppressWarnings("unchecked")
+ public V call() throws Exception {
+ final Object[] v = new Object[1];
+ final Throwable[] e = new Throwable[1];
+
+ try {
+ fDisplay.syncExec(new Runnable() {
+ public void run() {
+ try {
+ v[0] = callable.call();
+ } catch(Throwable exception) {
+ e[0] = exception;
+ }
+ }
+ });
+ } catch (SWTException swtException) {
+ if (swtException.code == SWT.ERROR_DEVICE_DISPOSED) {
+ DisplayDsfExecutor.super.shutdown();
+ }
+ }
+
+ if(e[0] instanceof RuntimeException) {
+ throw (RuntimeException) e[0];
+ } else if (e[0] instanceof Error) {
+ throw (Error) e[0];
+ } else if(e[0] instanceof Exception) {
+ throw (Exception) e[0];
+ }
+
+ return (V) v[0];
+ }
+ };
+ }
+
+ /**
+ * Creates a runnable wrapper, which delegates to the display to perform the
+ * operation. The runnable blocks the executor thread while each call
+ * is executed in the display thred.
+ * @param runnable Runnable to wrap.
+ * @return Wrapper runnable.
+ */
+ private Runnable createSWTDispatchRunnable(final Runnable runnable) {
+
+ // Check if executable wasn't executed already.
+ if (DEBUG_EXECUTOR && runnable instanceof DsfExecutable) {
+ assert !((DsfExecutable)runnable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
+ ((DsfExecutable)runnable).setSubmitted();
+ }
+
+ return new Runnable() {
+ public void run() {
+ try {
+ fDisplay.syncExec(new Runnable() {
+ public void run() {
+ runnable.run();
+ }
+ });
+ } catch (SWTException swtException) {
+ if (swtException.code == SWT.ERROR_DEVICE_DISPOSED) {
+ DisplayDsfExecutor.super.shutdownNow();
+ }
+ }
+ }
+ };
+ }
+
+ @Override
+ public <V> ScheduledFuture<V> schedule(final Callable<V> callable, long delay, TimeUnit unit) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.schedule(createSWTDispatchCallable(callable), delay, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.schedule(createSWTDispatchRunnable(command), delay, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.scheduleAtFixedRate(createSWTDispatchRunnable(command), initialDelay, period, unit);
+ }
+
+ @Override
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.scheduleWithFixedDelay(createSWTDispatchRunnable(command), initialDelay, delay, unit);
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ super.execute(createSWTDispatchRunnable(command));
+ }
+
+ @Override
+ public <T> Future<T> submit(Callable<T> callable) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.submit(createSWTDispatchCallable(callable));
+ }
+
+ @Override
+ public <T> Future<T> submit(Runnable command, T result) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.submit(createSWTDispatchRunnable(command), result);
+ }
+
+ @Override
+ public Future<?> submit(Runnable command) {
+ if (fDisplay.isDisposed()) {
+ if (!super.isShutdown()) super.shutdown();
+ throw new RejectedExecutionException("Display " + fDisplay + " is disposed."); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return super.submit(createSWTDispatchRunnable(command));
+ }
+
+ /**
+ * Override to prevent clients from shutting down. The executor will be
+ * shut down when the underlying display is discovered to be shut down.
+ */
+ @Override
+ public void shutdown() {
+ }
+
+ /**
+ * Override to prevent clients from shutting down. The executor will be
+ * shut down when the underlying display is discovered to be shut down.
+ */
+ @SuppressWarnings({ "cast", "unchecked" })
+ @Override
+ public List<Runnable> shutdownNow() {
+ return (List<Runnable>)Collections.EMPTY_LIST;
+ }
+}

Back to the top