Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent')
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/Executors.java141
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/activator/CoreBundleActivator.java71
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/event/ExecutorThreadNotificationListener.java35
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/AbstractDelegatingExecutorService.java212
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/SingleThreadedExecutorService.java188
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/factories/SingleThreadThreadFactory.java72
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutor.java21
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutorUtilDelegate.java38
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/INestableExecutor.java37
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/ISingleThreadedExecutor.java38
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.java33
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.properties6
-rw-r--r--target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/util/ExecutorsUtil.java404
13 files changed, 1296 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/Executors.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/Executors.java
new file mode 100644
index 000000000..2344035b1
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/Executors.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.IExecutor;
+import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+
+
+/**
+ * Class is providing the entry points to create or query the executor service
+ * instances.
+ */
+public final class Executors {
+
+ /**
+ * Execution service extension point manager.
+ */
+ protected static class ExecutorServiceExtensionPointManager extends AbstractExtensionPointManager<IExecutor> {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
+ */
+ @Override
+ protected String getExtensionPointId() {
+ return "org.eclipse.tcf.te.runtime.concurrent.executorServices"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
+ */
+ @Override
+ protected String getConfigurationElementName() {
+ return "executorService"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list of all contributed executors.
+ *
+ * @return The list of contributed executors, or an empty array.
+ */
+ public IExecutor[] getExecutors() {
+ List<IExecutor> contributions = new ArrayList<IExecutor>();
+ Collection<ExecutableExtensionProxy<IExecutor>> proxies = getExtensions().values();
+ for (ExecutableExtensionProxy<IExecutor> proxy : proxies)
+ if (proxy.getInstance() != null
+ && !contributions.contains(proxy.getInstance()))
+ contributions.add(proxy.getInstance());
+
+ return contributions.toArray(new IExecutor[contributions.size()]);
+ }
+
+ /**
+ * Returns the executor identified by its unique id. If no executor with
+ * the specified id is registered, <code>null</code> is returned.
+ *
+ * @param id
+ * The unique id of the executor. Must not be
+ * <code>null</code>
+ * @param newInstance
+ * Specify <code>true</code> to get a new executor service
+ * instance, <code>false</code> otherwise.
+ *
+ * @return The executor instance or <code>null</code>.
+ */
+ public IExecutor getExecutor(String id, boolean newInstance) {
+ Assert.isNotNull(id);
+
+ IExecutor executorService = null;
+ if (getExtensions().containsKey(id)) {
+ ExecutableExtensionProxy<IExecutor> proxy = getExtensions().get(id);
+ // Get the extension instance
+ executorService = newInstance ? proxy.newInstance() : proxy.getInstance();
+ }
+
+ return executorService;
+ }
+ }
+
+ // Reference to the executor service extension point manager
+ private final static ExecutorServiceExtensionPointManager EXTENSION_POINT_MANAGER = new ExecutorServiceExtensionPointManager();
+
+ /**
+ * Constructor.
+ * <p>
+ * <b>Note:</b> The class cannot be instantiated.
+ */
+ private Executors() {
+ }
+
+ /**
+ * Creates an instance of the executor registered with the specified id. If
+ * no executor is registered under the given id, the method will return
+ * <code>null</code>.
+ *
+ * @param id
+ * The id of the executor. Must not be <code>null</code>.
+ * @return The new executor instance or <code>null</code>.
+ */
+ public static IExecutor newExecutor(String id) {
+ Assert.isNotNull(id);
+ return EXTENSION_POINT_MANAGER.getExecutor(id, true);
+ }
+
+ /**
+ * Returns the shared instance of the executor registered with the specified
+ * id. If the shared instance hasn't been created yet, the instance will be
+ * created and saved. Subsequent calls to this method with the same id will
+ * return always the same executor instance. If no executor is registered
+ * under the given id, the method will return <code>null</code>.
+ *
+ * @param id
+ * The id of the executor. Must not be <code>null</code>.
+ * @return The new executor instance or <code>null</code>.
+ */
+ public static IExecutor getSharedExecutor(String id) {
+ Assert.isNotNull(id);
+ return EXTENSION_POINT_MANAGER.getExecutor(id, false);
+ }
+
+ /**
+ * Returns the shared instances of all registered executors.
+ *
+ * @return All executor instances or an empty array.
+ */
+ public static IExecutor[] getAllSharedExecutors() {
+ return EXTENSION_POINT_MANAGER.getExecutors();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/activator/CoreBundleActivator.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/activator/CoreBundleActivator.java
new file mode 100644
index 000000000..fe896a055
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/activator/CoreBundleActivator.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.activator;
+
+import org.eclipse.tcf.te.runtime.tracing.TraceHandler;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class CoreBundleActivator implements BundleActivator {
+ // The bundle context
+ private static BundleContext context;
+ // The trace handler instance
+ private static TraceHandler traceHandler;
+
+ /**
+ * Returns the bundle context
+ *
+ * @return the bundle context
+ */
+ public static BundleContext getContext() {
+ return context;
+ }
+
+ /**
+ * Convenience method which returns the unique identifier of this plugin.
+ */
+ public static String getUniqueIdentifier() {
+ if (getContext() != null && getContext().getBundle() != null) {
+ return getContext().getBundle().getSymbolicName();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the bundles trace handler.
+ *
+ * @return The bundles trace handler.
+ */
+ public static TraceHandler getTraceHandler() {
+ if (traceHandler == null) {
+ traceHandler = new TraceHandler(getUniqueIdentifier());
+ }
+ return traceHandler;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = bundleContext;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext bundleContext) throws Exception {
+ CoreBundleActivator.context = null;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/event/ExecutorThreadNotificationListener.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/event/ExecutorThreadNotificationListener.java
new file mode 100644
index 000000000..74229359f
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/event/ExecutorThreadNotificationListener.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.event;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.tcf.te.runtime.concurrent.util.ExecutorsUtil;
+import org.eclipse.tcf.te.runtime.interfaces.events.IEventFireDelegate;
+import org.eclipse.tcf.te.runtime.interfaces.events.IEventListener;
+
+/**
+ * Abstract notification listener implementation executing the
+ * notifications within the shared executor thread.
+ */
+public abstract class ExecutorThreadNotificationListener extends PlatformObject implements IEventListener, IEventFireDelegate {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.interfaces.events.IEventFireDelegate#fire(java.lang.Runnable)
+ */
+ @Override
+ public final void fire(Runnable runnable) {
+ // Force notification into the executor thread.
+ //
+ // Note: The executor thread is not identical with the display thread!
+ // Use ExecutorsUtil.executeInUI(runnable) to execute the runnable
+ // within the display thread.
+ ExecutorsUtil.execute(runnable);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/AbstractDelegatingExecutorService.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/AbstractDelegatingExecutorService.java
new file mode 100644
index 000000000..e5df0a65f
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/AbstractDelegatingExecutorService.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.executors;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tcf.te.runtime.concurrent.activator.CoreBundleActivator;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.IExecutor;
+import org.eclipse.tcf.te.runtime.concurrent.nls.Messages;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtension;
+
+/**
+ * Abstract delegating execution service implementation.
+ */
+public abstract class AbstractDelegatingExecutorService extends ExecutableExtension implements IExecutor, ExecutorService {
+ // The executor service to delegate the API calls to
+ private ExecutorService delegate;
+
+ // The thread pool name prefix
+ private String threadPoolNamePrefix;
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.ExecutableExtension#doSetInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ super.doSetInitializationData(config, propertyName, data);
+
+ if (config != null && data instanceof Map<?, ?>) {
+ Map<?, ?> params = (Map<?, ?>) data;
+ // Initialize the thread pool name prefix field by reading the
+ // "threadPoolNamePrefix" extension attribute if present.
+ threadPoolNamePrefix = (String) params.get("threadPoolNamePrefix"); //$NON-NLS-1$
+ if (threadPoolNamePrefix == null || threadPoolNamePrefix.trim().length() == 0) {
+ threadPoolNamePrefix = ""; //$NON-NLS-1$
+ }
+ }
+
+ // Create the executor service delegate
+ this.delegate = createExecutorServiceDelegate();
+ Assert.isNotNull(delegate);
+ }
+
+ /**
+ * Returns the thread pool name prefix if specified by the extension.
+ *
+ * @return The thread pool name prefix or an empty string.
+ */
+ public String getThreadPoolNamePrefix() {
+ return threadPoolNamePrefix != null ? threadPoolNamePrefix : ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Invoked by the constructor exactly once to create the executor service
+ * delegate instance.
+ *
+ * @return The executor service instance and never <code>null</code>.
+ */
+ protected abstract ExecutorService createExecutorServiceDelegate();
+
+ /**
+ * Returns the executor service delegate instance.
+ *
+ * @return The executor service delegate instance.
+ */
+ protected final ExecutorService getExecutorServiceDelegate() {
+ return delegate;
+ }
+
+ /**
+ * Log the given exception as error to the error log.
+ *
+ * @param e
+ * The exception or <code>null</code>.
+ */
+ protected void logException(Throwable e) {
+ if (e != null) {
+ IStatus status = new Status(
+ IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ NLS.bind(Messages.AbstractDelegatingExecutorService_unhandledException,
+ e.getLocalizedMessage()), e);
+ Platform.getLog(CoreBundleActivator.getContext().getBundle()).log(status);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.Executor#execute(java.lang.Runnable)
+ */
+ @Override
+ public void execute(Runnable command) {
+ delegate.execute(command);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#shutdown()
+ */
+ @Override
+ public void shutdown() {
+ delegate.shutdown();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#shutdownNow()
+ */
+ @Override
+ public List<Runnable> shutdownNow() {
+ return delegate.shutdownNow();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#isShutdown()
+ */
+ @Override
+ public boolean isShutdown() {
+ return delegate.isShutdown();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#isTerminated()
+ */
+ @Override
+ public boolean isTerminated() {
+ return delegate.isTerminated();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#awaitTermination(long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ return delegate.awaitTermination(timeout, unit);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#submit(java.util.concurrent.Callable)
+ */
+ @Override
+ public <T> Future<T> submit(Callable<T> task) {
+ return delegate.submit(task);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#submit(java.lang.Runnable, java.lang.Object)
+ */
+ @Override
+ public <T> Future<T> submit(Runnable task, T result) {
+ return delegate.submit(task, result);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#submit(java.lang.Runnable)
+ */
+ @Override
+ public Future<?> submit(Runnable task) {
+ return delegate.submit(task);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#invokeAll(java.util.Collection)
+ */
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
+ return delegate.invokeAll(tasks);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#invokeAll(java.util.Collection, long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
+ return delegate.invokeAll(tasks, timeout, unit);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#invokeAny(java.util.Collection)
+ */
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
+ return delegate.invokeAny(tasks);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ExecutorService#invokeAny(java.util.Collection, long, java.util.concurrent.TimeUnit)
+ */
+ @Override
+ public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ return delegate.invokeAny(tasks, timeout, unit);
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/SingleThreadedExecutorService.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/SingleThreadedExecutorService.java
new file mode 100644
index 000000000..a2f21c3b5
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/executors/SingleThreadedExecutorService.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.executors;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.tcf.te.runtime.concurrent.factories.SingleThreadThreadFactory;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.ISingleThreadedExecutor;
+
+/**
+ * A single threaded executor service implementation.
+ */
+public class SingleThreadedExecutorService extends AbstractDelegatingExecutorService implements ISingleThreadedExecutor, INestableExecutor {
+
+ /**
+ * A single threaded executor implementation.
+ */
+ protected class SingleThreadedExecutor extends ThreadPoolExecutor implements INestableExecutor {
+ // The current nesting depth
+ private final AtomicInteger currentNestingDepth = new AtomicInteger(0);
+
+ /**
+ * Constructor.
+ *
+ * @param threadFactory
+ * The thread factory instance. Must not be <code>null</code>.
+ *
+ * @throws NullPointerException
+ * if threadFactory is <code>null</code>.
+ */
+ public SingleThreadedExecutor(ThreadFactory threadFactory) {
+ this(threadFactory, new LinkedBlockingQueue<Runnable>());
+ }
+
+ /**
+ * Constructor.
+ * <p>
+ * Private constructor to catch the work queue instance passed into the
+ * {@link ThreadPoolExecutor} constructor.
+ *
+ * @param threadFactory
+ * The thread factory instance. Must not be <code>null</code>.
+ * @param workQueue
+ * The work queue instance. Must not be <code>null</code>.
+ */
+ private SingleThreadedExecutor(ThreadFactory threadFactory, BlockingQueue<Runnable> workQueue) {
+ super(1, 1, 0L, TimeUnit.NANOSECONDS, workQueue, threadFactory);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor#getMaxDepth()
+ */
+ @Override
+ public int getMaxDepth() {
+ return 1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor#readAndExecute()
+ */
+ @Override
+ public boolean readAndExecute() {
+ // Method is callable from the executor thread only
+ if (!isExecutorThread()) {
+ throw new IllegalStateException("Must be called from within the executor thread!"); //$NON-NLS-1$
+ }
+
+ BlockingQueue<Runnable> queue = getQueue();
+
+ // If the work queue is empty, there is nothing to do
+ if (!queue.isEmpty()) {
+ // Work queue not empty, check if we reached the maximum nesting
+ // depth
+ if (currentNestingDepth.get() >= getMaxDepth()) {
+ throw new IllegalStateException("Maximum nesting depth exceeded!"); //$NON-NLS-1$
+ }
+
+ // Get the next work item to do
+ Runnable runnable = null;
+ try {
+ // Double check that the queue is not empty, we desire to
+ // avoid
+ // blocking here!
+ if (!queue.isEmpty()) {
+ runnable = queue.take();
+ }
+ } catch (InterruptedException e) { /* ignored on purpose */ }
+
+ if (runnable != null) {
+ // Increase the nesting depth
+ currentNestingDepth.incrementAndGet();
+ try {
+ // Execute the runnable
+ runnable.run();
+ } finally {
+ // Decrease nesting depth
+ currentNestingDepth.decrementAndGet();
+ }
+ }
+ }
+
+ return !queue.isEmpty();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.concurrent.ThreadPoolExecutor#afterExecute(java.lang.Runnable, java.lang.Throwable)
+ */
+ @Override
+ protected void afterExecute(Runnable r, Throwable t) {
+ super.afterExecute(r, t);
+ if (t != null)
+ logException(t);
+ }
+ }
+
+ // Internal reference to the one shot thread factory instance
+ private SingleThreadThreadFactory threadFactory;
+
+ /**
+ * Constructor.
+ */
+ public SingleThreadedExecutorService() {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.executors.AbstractDelegatingExecutorService#createExecutorServiceDelegate()
+ */
+ @Override
+ protected ExecutorService createExecutorServiceDelegate() {
+ threadFactory = new SingleThreadThreadFactory(getThreadPoolNamePrefix());
+ return new SingleThreadedExecutor(threadFactory);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.ISingleThreadedExecutor#isExecutorThread()
+ */
+ @Override
+ public final boolean isExecutorThread() {
+ return isExecutorThread(Thread.currentThread());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.ISingleThreadedExecutor#isExecutorThread(java.lang.Thread)
+ */
+ @Override
+ public final boolean isExecutorThread(Thread thread) {
+ if (thread != null && threadFactory != null) {
+ return thread.equals(threadFactory.getThread());
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor#getMaxDepth()
+ */
+ @Override
+ public int getMaxDepth() {
+ if (!(getExecutorServiceDelegate() instanceof INestableExecutor)) {
+ throw new UnsupportedOperationException("Executor service delegate must implement INestableExecutor"); //$NON-NLS-1$
+ }
+ return ((INestableExecutor) getExecutorServiceDelegate()).getMaxDepth();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor#readAndExecute()
+ */
+ @Override
+ public boolean readAndExecute() {
+ if (!(getExecutorServiceDelegate() instanceof INestableExecutor)) {
+ throw new UnsupportedOperationException("Executor service delegate must implement INestableExecutor"); //$NON-NLS-1$
+ }
+ return ((INestableExecutor) getExecutorServiceDelegate()).readAndExecute();
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/factories/SingleThreadThreadFactory.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/factories/SingleThreadThreadFactory.java
new file mode 100644
index 000000000..3cf533f25
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/factories/SingleThreadThreadFactory.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.factories;
+
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * A thread factory implementation creating a single thread only.
+ */
+public class SingleThreadThreadFactory implements ThreadFactory {
+ private final ThreadGroup threadGroup;
+ private final String threadName;
+ private Thread thread;
+
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
+
+ /**
+ * Constructor.
+ *
+ * @param namePrefix
+ * The name prefix to name the created threads. Must not be
+ * <code>null</code>.
+ */
+ public SingleThreadThreadFactory(String namePrefix) {
+ Assert.isNotNull(namePrefix);
+
+ // Determine the thread group. Use the security manager if available.
+ this.threadGroup = (System.getSecurityManager() != null) ? System.getSecurityManager().getThreadGroup() : Thread.currentThread().getThreadGroup();
+ // Set the thread name prefix
+ this.threadName = ("".equals(namePrefix.trim()) ? "Executor" : namePrefix) + " - " + threadNumber.getAndIncrement(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
+ */
+ @Override
+ public Thread newThread(Runnable r) {
+ // The thread can be created on once. If called a second time,
+ // this factory cannot create any additional threads.
+ if (thread != null) return null;
+
+ // Create the thread with the desired name and the current thread number
+ thread = new Thread(threadGroup, r, threadName);
+ thread.setDaemon(false);
+ thread.setPriority(Thread.NORM_PRIORITY);
+
+ // Return the thread
+ return thread;
+ }
+
+ /**
+ * Returns the single created thread instance or <code>null</code> if
+ * {@link #newThread(Runnable)} have not been called yet.
+ *
+ * @return The single created thread instance or <code>null</code>.
+ */
+ public Thread getThread() {
+ return thread;
+ }
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutor.java
new file mode 100644
index 000000000..9311c5537
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutor.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.interfaces;
+
+import java.util.concurrent.Executor;
+
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+/**
+ * Execution interface declaration.
+ */
+public interface IExecutor extends Executor, IExecutableExtension {
+
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutorUtilDelegate.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutorUtilDelegate.java
new file mode 100644
index 000000000..7292f40da
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/IExecutorUtilDelegate.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.interfaces;
+
+import org.eclipse.tcf.te.runtime.interfaces.extensions.IExecutableExtension;
+
+/**
+ * Executor utility delegate interface declaration.
+ */
+public interface IExecutorUtilDelegate extends IExecutableExtension {
+
+ /**
+ * Returns if or if not the current thread is an executor thread handled by
+ * this executor utility wait and dispatch delegate.
+ *
+ * @return <code>True</code> if the current thread is handled,
+ * <code>false</code> otherwise.
+ */
+ public boolean isHandledExecutorThread();
+
+ /**
+ * Reads an event from the handled executors event queue, dispatches it
+ * appropriately, and returns <code>true</code> if there is potentially more
+ * work to do, or <code>false</code> if the caller can sleep until another
+ * event is placed on the event queue.
+ *
+ * @return <code>True</code> if there is potentially more work to do,
+ * <code>false</code> otherwise.
+ */
+ public boolean readAndDispatch();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/INestableExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/INestableExecutor.java
new file mode 100644
index 000000000..af7171f9e
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/INestableExecutor.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.interfaces;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Nestable execution interface declaration.
+ */
+public interface INestableExecutor extends Executor {
+
+ /**
+ * Returns the maximum allowed nesting depth. If this methods returns an
+ * integer value <= 0, nesting is disabled.
+ *
+ * @return The maximum allowed nesting depth or 0 to disable nesting.
+ */
+ public int getMaxDepth();
+
+ /**
+ * Reads the next command from the task queue and execute it if the maximum
+ * allowed nesting depth has not been exceeded. If the maximum nesting depth
+ * has been reached, the method will throw an {@link IllegalStateException}.
+ *
+ * @return <code>True</code> if there is potentially more work to do, or
+ * <code>false</code> if the caller can sleep until another event is
+ * placed on the task queue.
+ */
+ public boolean readAndExecute();
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/ISingleThreadedExecutor.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/ISingleThreadedExecutor.java
new file mode 100644
index 000000000..5ce6ab275
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/interfaces/ISingleThreadedExecutor.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.interfaces;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Single threaded execution service interface declaration.
+ */
+public interface ISingleThreadedExecutor extends Executor {
+
+ /**
+ * Returns if or if not the current thread is identical to the executor
+ * thread.
+ *
+ * @return <code>True</code> if the current thread is the executor thread,
+ * <code>false</code> otherwise.
+ */
+ public boolean isExecutorThread();
+
+ /**
+ * Returns if or if not the given thread is identical to the executor
+ * thread.
+ *
+ * @param thread
+ * The thread or <code>null</code>.
+ * @return <code>True</code> if the current thread is the executor thread,
+ * <code>false</code> otherwise.
+ */
+ public boolean isExecutorThread(Thread thread);
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.java
new file mode 100644
index 000000000..652586645
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.nls;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Target Explorer Concurrent Runtime plugin externalized strings management.
+ */
+public class Messages extends NLS {
+
+ // The plug-in resource bundle name
+ private static final String BUNDLE_NAME = "org.eclipse.tcf.te.runtime.concurrent.nls.Messages"; //$NON-NLS-1$
+
+ /**
+ * Static constructor.
+ */
+ static {
+ // Load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ // **** Declare externalized string id's down here *****
+
+ public static String AbstractDelegatingExecutorService_unhandledException;
+}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.properties b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.properties
new file mode 100644
index 000000000..6e7b09de1
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/nls/Messages.properties
@@ -0,0 +1,6 @@
+#
+# org.eclipse.tcf.te.runtime.concurrent
+# Externalized Strings.
+#
+
+AbstractDelegatingExecutorService_unhandledException=Unhandled exception caught in executor: {0}
diff --git a/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/util/ExecutorsUtil.java b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/util/ExecutorsUtil.java
new file mode 100644
index 000000000..f07026c03
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tcf.te.runtime.concurrent/src/org/eclipse/tcf/te/runtime/concurrent/util/ExecutorsUtil.java
@@ -0,0 +1,404 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, Inc. 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.tcf.te.runtime.concurrent.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.tcf.te.runtime.concurrent.Executors;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.IExecutorUtilDelegate;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.INestableExecutor;
+import org.eclipse.tcf.te.runtime.concurrent.interfaces.ISingleThreadedExecutor;
+import org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager;
+import org.eclipse.tcf.te.runtime.extensions.ExecutableExtensionProxy;
+import org.eclipse.tcf.te.runtime.interfaces.IConditionTester;
+
+
+/**
+ * Utility class to provide helper methods to execute tasks at
+ * a executor service asynchronous and synchronous.
+ */
+public final class ExecutorsUtil {
+
+ /**
+ * Execution utility wait and dispatch utility extension point manager.
+ */
+ protected static class ExecutorUtilDelegateExtensionPointManager extends AbstractExtensionPointManager<IExecutorUtilDelegate> {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getExtensionPointId()
+ */
+ @Override
+ protected String getExtensionPointId() {
+ return "org.eclipse.tcf.te.runtime.concurrent.executorUtilDelegates"; //$NON-NLS-1$
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tcf.te.runtime.extensions.AbstractExtensionPointManager#getConfigurationElementName()
+ */
+ @Override
+ protected String getConfigurationElementName() {
+ return "executorUtilDelegate"; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the list of all contributed executor utility delegates.
+ *
+ * @return The list of contributed executor utility delegates, or an
+ * empty array.
+ */
+ public IExecutorUtilDelegate[] getExecutorUtilDelegates() {
+ List<IExecutorUtilDelegate> contributions = new ArrayList<IExecutorUtilDelegate>();
+ Collection<ExecutableExtensionProxy<IExecutorUtilDelegate>> proxies = getExtensions().values();
+ for (ExecutableExtensionProxy<IExecutorUtilDelegate> proxy : proxies) {
+ if (proxy.getInstance() != null&& !contributions.contains(proxy.getInstance())) {
+ contributions.add(proxy.getInstance());
+ }
+ }
+
+ return contributions.toArray(new IExecutorUtilDelegate[contributions.size()]);
+ }
+
+ /**
+ * Returns the executor utility delegate identified by its unique id. If
+ * no executor utility delegate with the specified id is registered,
+ * <code>null</code> is returned.
+ *
+ * @param id
+ * The unique id of the executor utility delegate. Must not
+ * be <code>null</code>
+ * @param newInstance
+ * Specify <code>true</code> to get a new executor utility
+ * delegate instance, <code>false</code> otherwise.
+ *
+ * @return The executor instance or <code>null</code>.
+ */
+ public IExecutorUtilDelegate getExecutorUtilDelegate(String id, boolean newInstance) {
+ Assert.isNotNull(id);
+
+ IExecutorUtilDelegate executorUtilDelegate = null;
+ if (getExtensions().containsKey(id)) {
+ ExecutableExtensionProxy<IExecutorUtilDelegate> proxy = getExtensions().get(id);
+ // Get the extension instance
+ executorUtilDelegate = newInstance ? proxy.newInstance() : proxy.getInstance();
+ }
+
+ return executorUtilDelegate;
+ }
+ }
+
+ // Reference to the executor service extension point manager
+ private final static ExecutorUtilDelegateExtensionPointManager EXTENSION_POINT_MANAGER = new ExecutorUtilDelegateExtensionPointManager();
+
+ // Reference to the used executor service.
+ private final static ISingleThreadedExecutor EXECUTOR;
+ // Reference to the used UI executor service (might be null if not available)
+ private final static ISingleThreadedExecutor UI_EXECUTOR;
+
+ /**
+ * Static constructor.
+ */
+ static {
+ EXECUTOR = (ISingleThreadedExecutor) Executors.getSharedExecutor("org.eclipse.tcf.te.runtime.concurrent.executors.singleThreaded"); //$NON-NLS-1$
+ Assert.isNotNull(EXECUTOR);
+ UI_EXECUTOR = (ISingleThreadedExecutor) Executors.getSharedExecutor("org.eclipse.tcf.te.ui.executors.SWTDisplay"); //$NON-NLS-1$
+ }
+
+ /**
+ * Shutdown the executor service used.
+ */
+ public static void shutdown() {
+ if (EXECUTOR instanceof ExecutorService) {
+ ((ExecutorService) EXECUTOR).shutdown();
+ }
+ if (UI_EXECUTOR instanceof ExecutorService) {
+ ((ExecutorService) UI_EXECUTOR).shutdown();
+ }
+ }
+
+ /**
+ * Checks if the current thread is identical with the executor thread.
+ *
+ * @return <code>True</code> if the current thread is the executor thread,
+ * <code>false</code> otherwise.
+ */
+ public static boolean isExecutorThread() {
+ return EXECUTOR != null ? EXECUTOR.isExecutorThread() : false;
+ }
+
+ /**
+ * Checks if the current thread is identical with the UI executor thread.
+ *
+ * @return <code>True</code> if the current thread is the UI executor
+ * thread, <code>false</code> otherwise.
+ */
+ public static boolean isUIExecutorThread() {
+ return UI_EXECUTOR != null ? UI_EXECUTOR.isExecutorThread() : false;
+ }
+
+ /**
+ * Schedule the given {@link Runnable} for invocation within the used
+ * executor thread.
+ *
+ * @param runnable
+ * The <code>java.lang.Runnable</code> to execute within the
+ * executor thread.
+ */
+ public static void execute(Runnable runnable) {
+ if (runnable != null) {
+ if (EXECUTOR instanceof ExecutorService) {
+ if (!((ExecutorService) EXECUTOR).isShutdown()
+ && !((ExecutorService) EXECUTOR).isTerminated()) {
+ EXECUTOR.execute(runnable);
+ }
+ } else {
+ EXECUTOR.execute(runnable);
+ }
+ }
+ }
+
+
+ /**
+ * Schedule the given {@link Runnable} for invocation within the used
+ * executor thread and blocks the caller until the runnable got executed.
+ * <p>
+ * <b>Note:</b> The method is using {@link #wait()} to block the calling
+ * thread. Therefore the method cannot be called from within
+ * the executor thread itself.
+ *
+ * @param runnable
+ * The <code>java.lang.Runnable</code> to execute within the
+ * executor thread.
+ */
+ public static void executeWait(final Runnable runnable) {
+ Assert.isTrue(!EXECUTOR.isExecutorThread());
+ if (runnable == null) return;
+
+ final AtomicBoolean invoked = new AtomicBoolean(false);
+
+ // Wrap the original runnable in another runnable
+ // to notify ourself
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ runnable.run();
+ } finally {
+ invoked.set(true);
+ synchronized(runnable) {
+ runnable.notifyAll();
+ }
+ }
+ }
+ };
+
+ if (EXECUTOR instanceof ExecutorService) {
+ if (!((ExecutorService) EXECUTOR).isShutdown()
+ && !((ExecutorService) EXECUTOR).isTerminated()) {
+ EXECUTOR.execute(r);
+ }
+ } else {
+ EXECUTOR.execute(r);
+ }
+
+ synchronized(runnable) {
+ try {
+ if (!invoked.get()) runnable.wait();
+ } catch (InterruptedException e) {
+ /* ignored on purpose */
+ }
+ }
+ }
+
+ /**
+ * Schedule the given {@link Runnable} to run the current platform display
+ * thread and blocks the caller until the runnable got executed.
+ *
+ * @param runnable
+ * The <code>java.lang.Runnable</code> to execute within the
+ * UI thread.
+ */
+ public static void executeInUI(Runnable runnable) {
+ if (runnable != null) {
+ if (UI_EXECUTOR instanceof ExecutorService) {
+ if (!((ExecutorService) UI_EXECUTOR).isShutdown()
+ && !((ExecutorService) UI_EXECUTOR).isTerminated()) {
+ UI_EXECUTOR.execute(runnable);
+ }
+ } else {
+ if (UI_EXECUTOR != null) {
+ UI_EXECUTOR.execute(runnable);
+ }
+ }
+ }
+ }
+
+ /**
+ * Schedule the given {@link Runnable} to run the current platform display
+ * thread and blocks the caller until the runnable got executed.
+ *
+ * @param runnable
+ * The <code>java.lang.Runnable</code> to execute within the
+ * UI thread.
+ */
+ public static void executeInUIWait(final Runnable runnable) {
+ if (runnable == null) return;
+
+ final AtomicBoolean invoked = new AtomicBoolean(false);
+
+ // Wrap the original runnable in another runnable
+ // to set the invoked flag
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ runnable.run();
+ } finally {
+ invoked.set(true);
+ }
+ }
+ };
+
+ if (UI_EXECUTOR instanceof ExecutorService) {
+ if (!((ExecutorService) UI_EXECUTOR).isShutdown()
+ && !((ExecutorService) UI_EXECUTOR).isTerminated()) {
+ UI_EXECUTOR.execute(r);
+ }
+ } else {
+ if (UI_EXECUTOR != null) {
+ UI_EXECUTOR.execute(r);
+ } else {
+ invoked.set(true);
+ }
+ }
+
+ waitAndExecute(0, new IConditionTester() {
+ @Override
+ public boolean isConditionFulfilled() {
+ return invoked.get();
+ }
+ @Override
+ public void cleanup() {
+ }
+ });
+ }
+
+ /**
+ * Waits either for the given condition tester to signal that the condition,
+ * the caller want's to wait for, has been completely fulfilled or till the
+ * timeout runs out. If the specified condition tester is <code>null</code>,
+ * the method will always wait till the timeout occurs. In case
+ * <code>timeout == 0</code> and <code>conditionTester == null</code>, the
+ * method returns immediately with the return value <code>true</code>!
+ *
+ * @param timeout
+ * The timeout to wait in milliseconds. <code>0</code> means
+ * infinite wait time!
+ * @param conditionTester
+ * The condition tester to use for checking the interrupt
+ * condition.
+ *
+ * @return <code>false</code> if the exit reason if that the waiting
+ * condition has been fulfilled, <code>true</code> if the exit
+ * reason is the timeout!
+ */
+ public static boolean waitAndExecute(final long timeout, final IConditionTester conditionTester) {
+ // both parameter are null, return immediately!
+ if (conditionTester == null && timeout == 0)
+ return true;
+
+ // we assume that the exit reason will be the timeout
+ boolean exitReason = true;
+
+ // Remember the executors utility delegate down the road. As long
+ // we don't leave the waitAndExecute method, the thread cannot change.
+ IExecutorUtilDelegate lastDelegate = null;
+
+ // Remember the start time to calculate the timeout
+ final long startTime = System.currentTimeMillis();
+ // keep going till either the condition tester or the timeout will
+ // break the loop!
+ while (true) {
+ if (conditionTester != null && conditionTester.isConditionFulfilled()) {
+ // the exit reason is the condition tester!
+ exitReason = false;
+ break;
+ }
+ if (timeout != 0 && ((System.currentTimeMillis() - startTime) >= timeout)) {
+ // timeout occurred, just break the loop
+ break;
+ }
+ // none of the break conditions are fulfilled, so wait a little bit
+ // before testing again.
+ if (isExecutorThread()) {
+ // We are in the executor thread. Keep the command dispatching running.
+ if (EXECUTOR instanceof INestableExecutor) {
+ ((INestableExecutor) EXECUTOR).readAndExecute();
+ Thread.yield();
+ } else {
+ throw new IllegalStateException("waitAndExecute called from within a non-nestable executor service!"); //$NON-NLS-1$
+ }
+ }
+ // Check if we are in the UI executor thread
+ else if (isUIExecutorThread()) {
+ // We are in the executor thread. Keep the command dispatching
+ // running.
+ if (UI_EXECUTOR instanceof INestableExecutor) {
+ ((INestableExecutor) UI_EXECUTOR).readAndExecute();
+ Thread.yield();
+ } else {
+ throw new IllegalStateException("waitAndExecute called from within a non-nestable UI executor service!"); //$NON-NLS-1$
+ }
+ }
+ // Check if we have a delegate contribution which is handling
+ // the current thread.
+ else {
+ boolean foundHandlingDelegate = false;
+
+ if (lastDelegate == null) {
+ // Get all registered delegates
+ IExecutorUtilDelegate[] delegates = EXTENSION_POINT_MANAGER.getExecutorUtilDelegates();
+ for (IExecutorUtilDelegate delegate : delegates) {
+ // Does the delegate handles the current thread?
+ if (delegate.isHandledExecutorThread()) {
+ foundHandlingDelegate = true;
+ lastDelegate = delegate;
+ // Read and dispatch one event
+ delegate.readAndDispatch();
+ break;
+ }
+ }
+ } else {
+ foundHandlingDelegate = true;
+ // Read and dispatch one event
+ lastDelegate.readAndDispatch();
+ }
+
+ if (!foundHandlingDelegate) {
+ // Not in any executor thread, put the current thread to sleep
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) { /* ignored on purpose */ }
+ }
+ }
+ }
+
+ // give the condition tester the chance to cleanup
+ if (conditionTester != null) {
+ conditionTester.cleanup();
+ }
+
+ return exitReason;
+ }
+}

Back to the top