diff options
author | Uwe Stieber | 2011-11-14 17:19:22 +0000 |
---|---|---|
committer | Uwe Stieber | 2011-11-14 17:58:49 +0000 |
commit | 7648a108647fefb71f48aff164076c60205eedf1 (patch) | |
tree | 28d30fd78868f0776a4b90d01ef88d62970f70cc /target_explorer/plugins | |
parent | 89aa93ebb281f229ac45bfc5fe1ee93dece9cce2 (diff) | |
download | org.eclipse.tcf-7648a108647fefb71f48aff164076c60205eedf1.tar.gz org.eclipse.tcf-7648a108647fefb71f48aff164076c60205eedf1.tar.xz org.eclipse.tcf-7648a108647fefb71f48aff164076c60205eedf1.zip |
Target Explorer: Enable the asynchronous callback collector and handler to customize the callback invocation thread
Diffstat (limited to 'target_explorer/plugins')
11 files changed, 99 insertions, 110 deletions
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF b/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF index 015f2121f..a9dd00f75 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF +++ b/target_explorer/plugins/org.eclipse.tm.te.core/META-INF/MANIFEST.MF @@ -7,7 +7,6 @@ Bundle-Activator: org.eclipse.tm.te.core.activator.CoreBundleActivator Bundle-Vendor: %providerName Require-Bundle: org.eclipse.core.runtime;bundle-version="3.7.0", org.eclipse.tm.te.runtime;bundle-version="1.0.0", - org.eclipse.tm.te.runtime.concurrent;bundle-version="1.0.0", org.eclipse.tm.te.runtime.stepper;bundle-version="1.0.0", org.eclipse.tm.te.runtime.services;bundle-version="1.0.0", org.eclipse.tm.te.runtime.persistence;bundle-version="1.0.0", @@ -23,7 +22,6 @@ Export-Package: org.eclipse.tm.te.core.activator;x-internal:=true, org.eclipse.tm.te.core.connection.interfaces, org.eclipse.tm.te.core.connection.managers, org.eclipse.tm.te.core.connection.strategy, - org.eclipse.tm.te.core.model, org.eclipse.tm.te.core.model.interfaces, org.eclipse.tm.te.core.nls;x-internal:=true, org.eclipse.tm.te.core.utils.text diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableJob.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableJob.java index c6b2536aa..4abd2a781 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableJob.java +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableJob.java @@ -17,7 +17,7 @@ import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.tm.te.core.async.interfaces.IAsyncExecutable; import org.eclipse.tm.te.runtime.callback.Callback; -import org.eclipse.tm.te.runtime.concurrent.util.ExecutorsUtil; +import org.eclipse.tm.te.runtime.interfaces.IConditionTester; import org.eclipse.tm.te.runtime.interfaces.callback.ICallback; import org.eclipse.tm.te.runtime.utils.ProgressHelper; @@ -186,6 +186,16 @@ public abstract class AbstractAsyncExecutableJob extends Job implements IAsyncEx */ protected abstract void internalExecute(final IProgressMonitor monitor, final ICallback callback); + /** + * Hold the execution of {@link #run(IProgressMonitor)} until the asynchronous executable + * has completed the execution and invoked the callback. + * + * @param timeout The timeout in milliseconds. <code>0</code> means wait forever. + * @param conditionTester The condition tester which condition must be fulfilled until + * the execution hold of {@link #run(IProgressMonitor)} can be released. + */ + protected abstract void waitAndExecute(long timeout, IConditionTester conditionTester); + /* (non-Javadoc) * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ @@ -196,7 +206,7 @@ public abstract class AbstractAsyncExecutableJob extends Job implements IAsyncEx ProgressHelper.beginTask(monitor, "", jobTicks); //$NON-NLS-1$ final Callback callback = new Callback(monitor, ProgressHelper.PROGRESS_DONE, getJobCallback()); internalExecute(monitor, callback); - ExecutorsUtil.waitAndExecute(0, callback.getDoneConditionTester(isCancelable() ? monitor : null)); + waitAndExecute(0, callback.getDoneConditionTester(isCancelable() ? monitor : null)); finished = true; if (getRescheduleDelay() >= 0 && Platform.isRunning() && (!isCancelable() || !monitor.isCanceled())) { diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncExecutableStepperJob.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableStepperJob.java index 073fd5cd4..0c12489cf 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncExecutableStepperJob.java +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AbstractAsyncExecutableStepperJob.java @@ -19,12 +19,12 @@ import org.eclipse.tm.te.runtime.interfaces.callback.ICallback; import org.eclipse.tm.te.runtime.utils.ProgressHelper; /** - * Asynchronous executable stepper job. + * Abstract asynchronous executable stepper job. * <p> * The job executes a list of actions. If any action returns with an error, the whole job will be * aborted. */ -public class AsyncExecutableStepperJob extends AbstractAsyncExecutableJob { +public abstract class AbstractAsyncExecutableStepperJob extends AbstractAsyncExecutableJob { private final IAsyncExecutable[] actions; /** @@ -33,7 +33,7 @@ public class AsyncExecutableStepperJob extends AbstractAsyncExecutableJob { * @param name The job name. Must not be <code>null</code> * @param actions The actions to execute. Must not be <code>null</code>. */ - public AsyncExecutableStepperJob(String name, IAsyncExecutable[] actions) { + public AbstractAsyncExecutableStepperJob(String name, IAsyncExecutable[] actions) { super(name); Assert.isNotNull(actions); diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackCollector.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackCollector.java index 92d171073..f0fb15908 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackCollector.java +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackCollector.java @@ -17,7 +17,6 @@ import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.tm.te.core.activator.CoreBundleActivator; import org.eclipse.tm.te.runtime.callback.Callback; -import org.eclipse.tm.te.runtime.concurrent.util.ExecutorsUtil; import org.eclipse.tm.te.runtime.interfaces.callback.ICallback; /** @@ -40,6 +39,23 @@ public class AsyncCallbackCollector extends AsyncCallbackHandler { private boolean isFinished; private boolean initDone; + // The reference to the callback invocation delegate + private ICallbackInvocationDelegate delegate = null; + + /** + * Delegation interfaces used by the asynchronous callback collector to + * invoke the final callback. + */ + public static interface ICallbackInvocationDelegate { + + /** + * Invokes the given runnable. + * + * @param runnable The runnable. Must not be <code>null</code>. + */ + public void invoke(Runnable runnable); + } + /** * Simple target callback handling an asynchronous callback collector parent itself and remove * themselves from the collector after callback has done. @@ -90,21 +106,25 @@ public class AsyncCallbackCollector extends AsyncCallbackHandler { * Constructor. */ public AsyncCallbackCollector() { - this(null); + this(null, null); } /** * Constructor. * * @param callback The final callback to invoke if the collector enters the finished state. + * @param delegate The callback invocation delegate. Must not be <code>null</code> if the callback is not <code>null</code>. */ - public AsyncCallbackCollector(ICallback callback) { + public AsyncCallbackCollector(ICallback callback, ICallbackInvocationDelegate delegate) { super(); + if (callback != null) Assert.isNotNull(delegate); + // We have to add our master callback to the list of callback to avoid that // the collector is running empty to early! addCallback(callback); this.callback = callback; + this.delegate = delegate; // We are not finished yet. isFinished = false; @@ -141,7 +161,8 @@ public class AsyncCallbackCollector extends AsyncCallbackHandler { */ protected void onCollectorFinished() { if (callback != null) { - ExecutorsUtil.execute(new Runnable() { + Assert.isNotNull(delegate); + delegate.invoke(new Runnable() { @Override public void run() { Throwable error = getError(); diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackHandler.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackHandler.java index f854ec591..8ea299ebc 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackHandler.java +++ b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/async/AsyncCallbackHandler.java @@ -16,7 +16,6 @@ import java.util.Map; import java.util.Vector; import org.eclipse.core.runtime.Platform; -import org.eclipse.tm.te.runtime.concurrent.util.ExecutorsUtil; import org.eclipse.tm.te.runtime.interfaces.IConditionTester; import org.eclipse.tm.te.runtime.interfaces.callback.ICallback; @@ -26,7 +25,6 @@ import org.eclipse.tm.te.runtime.interfaces.callback.ICallback; public class AsyncCallbackHandler { private final List<ICallback> callbacks = new Vector<ICallback>(); private final IConditionTester conditionTester; - private boolean timeoutOccurred; private Throwable error; private final static boolean TRACING_ENABLED = Boolean.parseBoolean(Platform.getDebugOption("org.eclipse.tm.te.runtime/trace/callbacks")); //$NON-NLS-1$ @@ -47,7 +45,6 @@ public class AsyncCallbackHandler { */ public AsyncCallbackHandler(IConditionTester tester) { super(); - timeoutOccurred = false; error = null; conditionTester = new AsyncCallbackConditionTester(tester); } @@ -147,11 +144,14 @@ public class AsyncCallbackHandler { } /** - * Returns <code>true</code> if the <code>wait</code> methods have been left because of timeout - * and not because the waiting condition has been fulfilled. + * Returns the condition tester to use for waiting for the callback handler + * until all callbacks have been invoked and the external condition tester + * is fulfilled too. + * + * @return The condition tester instance. */ - public boolean isTimeoutOccurred() { - return timeoutOccurred; + public IConditionTester getConditionTester() { + return conditionTester; } final class AsyncCallbackConditionTester implements IConditionTester { @@ -170,8 +170,7 @@ public class AsyncCallbackHandler { externalTester = tester; } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.eclipse.tm.te.runtime.interfaces.IConditionTester#cleanup() */ @Override @@ -181,8 +180,7 @@ public class AsyncCallbackHandler { } } - /* - * (non-Javadoc) + /* (non-Javadoc) * @see org.eclipse.tm.te.runtime.interfaces.IConditionTester#isConditionFulfilled() */ @Override @@ -191,14 +189,4 @@ public class AsyncCallbackHandler { return isEmpty() || (externalTester != null && externalTester.isConditionFulfilled()); } } - - /** - * Wait for all associated callback's to finish or the specified timeout has been occurred. - * - * @param timeout The timeout in milliseconds. If <code>0</code>, the method waits forever till - * all callback's have been returned. - */ - public final void waitForFinishOrTimeout(long timeout) { - timeoutOccurred = ExecutorsUtil.waitAndExecute(timeout, conditionTester); - } } diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeContainerModelNode.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeContainerModelNode.java deleted file mode 100644 index 73fe10a67..000000000 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeContainerModelNode.java +++ /dev/null @@ -1,28 +0,0 @@ -/*******************************************************************************
- * 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.tm.te.core.model;
-
-import org.eclipse.tm.te.runtime.concurrent.util.ExecutorsUtil;
-import org.eclipse.tm.te.runtime.model.ContainerModelNode;
-
-/**
- * Container model node implementation assuring thread safety by enforcing model operations to
- * happen in the executor thread.
- */
-public class ThreadSafeContainerModelNode extends ContainerModelNode {
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.te.runtime.nodes.PropertiesContainer#checkThreadAccess()
- */
- @Override
- protected boolean checkThreadAccess() {
- return ExecutorsUtil.isExecutorThread();
- }
-}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeModelNode.java b/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeModelNode.java deleted file mode 100644 index 357405372..000000000 --- a/target_explorer/plugins/org.eclipse.tm.te.core/src/org/eclipse/tm/te/core/model/ThreadSafeModelNode.java +++ /dev/null @@ -1,28 +0,0 @@ -/*******************************************************************************
- * 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.tm.te.core.model;
-
-import org.eclipse.tm.te.runtime.concurrent.util.ExecutorsUtil;
-import org.eclipse.tm.te.runtime.model.ModelNode;
-
-/**
- * Model node implementation assuring thread safety by enforcing model operations to happen in the
- * executor thread.
- */
-public class ThreadSafeModelNode extends ModelNode {
-
- /* (non-Javadoc)
- * @see org.eclipse.tm.te.runtime.nodes.PropertiesContainer#checkThreadAccess()
- */
- @Override
- protected boolean checkThreadAccess() {
- return ExecutorsUtil.isExecutorThread();
- }
-}
diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessLauncher.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessLauncher.java index 650691f2e..91d0d1596 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessLauncher.java +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessLauncher.java @@ -128,22 +128,25 @@ public class ProcessLauncher extends PlatformObject implements IProcessLauncher eventListener = null; } + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + // Create the callback collector final AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { @Override protected void internalDone(Object caller, IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ // Close the channel as all disposal is done - if (finChannel != null) { - if (Protocol.isDispatchThread()) finChannel.close(); - else Protocol.invokeAndWait(new Runnable() { - @Override - public void run() { - finChannel.close(); - } - }); - } + if (finChannel != null) finChannel.close(); } - }); + }, delegate); if (streamsListener != null) { // Dispose the streams listener diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessStreamsListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessStreamsListener.java index beb0663ff..fc99fad84 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessStreamsListener.java +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.processes.core/src/org/eclipse/tm/te/tcf/processes/core/launcher/ProcessStreamsListener.java @@ -646,6 +646,16 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces dataReceiver.clear(); } + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + // Create a new collector to catch all runnable stop callback's AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { /* (non-Javadoc) @@ -653,6 +663,7 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces */ @Override protected void internalDone(final Object caller, final IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ // Get the service instance from the parent IStreams svcStreams = getParent().getSvcStreams(); // Unsubscribe the streams listener from the service @@ -666,7 +677,7 @@ public class ProcessStreamsListener implements IStreams.StreamsListener, IProces } }); } - }); + }, delegate); // Loop all runnable's and force them to stop synchronized (runnables) { diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsLauncher.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsLauncher.java index b3b426b18..057adcf31 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsLauncher.java +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsLauncher.java @@ -112,22 +112,25 @@ public class TerminalsLauncher extends PlatformObject implements ITerminalsLaunc eventListener = null; } + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + // Create the callback collector final AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { @Override protected void internalDone(Object caller, IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ // Close the channel as all disposal is done - if (finChannel != null) { - if (Protocol.isDispatchThread()) finChannel.close(); - else Protocol.invokeAndWait(new Runnable() { - @Override - public void run() { - finChannel.close(); - } - }); - } + if (finChannel != null) finChannel.close(); } - }); + }, delegate); if (streamsListener != null) { // Dispose the streams listener diff --git a/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java b/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java index 48fbf400a..4d12ab394 100644 --- a/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java +++ b/target_explorer/plugins/org.eclipse.tm.te.tcf.terminals.core/src/org/eclipse/tm/te/tcf/terminals/core/launcher/TerminalsStreamsListener.java @@ -656,6 +656,16 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm dataReceiver.clear(); } + // Create the callback invocation delegate + AsyncCallbackCollector.ICallbackInvocationDelegate delegate = new AsyncCallbackCollector.ICallbackInvocationDelegate() { + @Override + public void invoke(Runnable runnable) { + Assert.isNotNull(runnable); + if (Protocol.isDispatchThread()) runnable.run(); + else Protocol.invokeLater(runnable); + } + }; + // Create a new collector to catch all runnable stop callback's AsyncCallbackCollector collector = new AsyncCallbackCollector(new Callback() { /* (non-Javadoc) @@ -663,6 +673,7 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm */ @Override protected void internalDone(final Object caller, final IStatus status) { + Assert.isTrue(Protocol.isDispatchThread(), "Illegal Thread Access"); //$NON-NLS-1$ // Get the service instance from the parent IStreams svcStreams = getParent().getSvcStreams(); // Unsubscribe the streams listener from the service @@ -676,7 +687,7 @@ public class TerminalsStreamsListener implements IStreams.StreamsListener, ITerm } }); } - }); + }, delegate); // Loop all runnable's and force them to stop synchronized (runnables) { |