1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

Bug 540373: Cleanup: Remove trailing whitespace in Java files

Some Java files were missed, or other cleanups introduced
trailing whitespace. So clean it up with this commit.

Command used:
find .  ! -path "./.git/*" -type f -name *.java  -exec sed -i -E 's/[ \t]+$//' {} +

Change-Id: I18f5e3a3eb5352443c9e753d427bb8d06107b8a4
This commit is contained in:
Jonah Graham 2018-11-23 00:52:15 +00:00
parent b4031b5a8b
commit be35c7327d
20 changed files with 587 additions and 587 deletions

View file

@ -80,7 +80,7 @@ public class GdbDisconnectCommand implements IDisconnectHandler {
request.setEnabled(false); request.setEnabled(false);
} else { } else {
request.setEnabled(getData()); request.setEnabled(getData());
} }
request.done(); request.done();
} }

View file

@ -606,7 +606,7 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000)); shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
IProcess[] launchProcesses = getGDBLaunch().getProcesses(); IProcess[] launchProcesses = getGDBLaunch().getProcesses();
for (IProcess proc : launchProcesses) { for (IProcess proc : launchProcesses) {
if (proc instanceof InferiorRuntimeProcess) { if (proc instanceof InferiorRuntimeProcess) {
assertThat(proc.getAttribute(IGdbDebugConstants.INFERIOR_EXITED_ATTR), is(notNullValue())); assertThat(proc.getAttribute(IGdbDebugConstants.INFERIOR_EXITED_ATTR), is(notNullValue()));

View file

@ -451,7 +451,7 @@ abstract public class AbstractVMProvider implements IVMProvider, IVMEventListene
} }
} }
fNodesListCache = list.toArray(new IVMNode[list.size()]); fNodesListCache = list.toArray(new IVMNode[list.size()]);
return fNodesListCache; return fNodesListCache;
} }

View file

@ -150,7 +150,7 @@ abstract public class ReflectionSequence extends Sequence {
assert executeMethod != null; assert executeMethod != null;
fExecuteMethod = executeMethod; fExecuteMethod = executeMethod;
fRollbackMethod = rollbackMethod; fRollbackMethod = rollbackMethod;
} }

View file

@ -422,7 +422,7 @@ public class CommandCache implements ICommandListener {
// protect against the cache being called in non-session thread, but at // protect against the cache being called in non-session thread, but at
// the same time avoid adding extra dispatch cycles to command processing. // the same time avoid adding extra dispatch cycles to command processing.
if (fSession.getExecutor().isInExecutorThread()) { if (fSession.getExecutor().isInExecutorThread()) {
super.done(); super.done();
} else { } else {
fSession.getExecutor().execute(new DsfRunnable() { fSession.getExecutor().execute(new DsfRunnable() {

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -34,55 +34,55 @@ import org.eclipse.cdt.dsf.concurrent.Transaction;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
/** /**
* A data generator which performs a sum computation on data retrieved from a * A data generator which performs a sum computation on data retrieved from a
* number of other data generators. The data retrieval from other generators * number of other data generators. The data retrieval from other generators
* is performed using ACPM caches and the result is calculated once all caches * is performed using ACPM caches and the result is calculated once all caches
* are valid. * are valid.
* <p> * <p>
* Unlike {@link AsyncSumDataGenerator}, this data generator listens to events * Unlike {@link AsyncSumDataGenerator}, this data generator listens to events
* from the individual the data providers. Theve events are used to * from the individual the data providers. Theve events are used to
* invalidate caches to make sure that they don't return incorrect data. This * invalidate caches to make sure that they don't return incorrect data. This
* generator also sends out events to its clients to notify them to update, or * generator also sends out events to its clients to notify them to update, or
* invalidate their caches. * invalidate their caches.
* </p> * </p>
*/ */
public class ACPMSumDataGenerator public class ACPMSumDataGenerator
implements IDataGenerator, IDataGenerator.Listener implements IDataGenerator, IDataGenerator.Listener
{ {
/** /**
* DSF executor used to serialize data access within this data generator. * DSF executor used to serialize data access within this data generator.
*/ */
final private DsfExecutor fExecutor; final private DsfExecutor fExecutor;
/** /**
* Data generators to retrieve original data to perform calculations on. * Data generators to retrieve original data to perform calculations on.
* The generators are accessed through the cache manager wrappers. * The generators are accessed through the cache manager wrappers.
*/ */
final private DataGeneratorCacheManager[] fDataGeneratorCMs; final private DataGeneratorCacheManager[] fDataGeneratorCMs;
/** /**
* List of listeners for this data generator. * List of listeners for this data generator.
*/ */
final private List<Listener> fListeners = new LinkedList<Listener>(); final private List<Listener> fListeners = new LinkedList<Listener>();
public ACPMSumDataGenerator(DsfExecutor executor, public ACPMSumDataGenerator(DsfExecutor executor,
IDataGenerator[] generators) IDataGenerator[] generators)
{ {
fExecutor = executor; fExecutor = executor;
// Create wrappers for data generators and add ourselves as listener // Create wrappers for data generators and add ourselves as listener
// to their events. // to their events.
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length]; fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
ImmediateInDsfExecutor immediateExecutor = ImmediateInDsfExecutor immediateExecutor =
new ImmediateInDsfExecutor(fExecutor); new ImmediateInDsfExecutor(fExecutor);
for (int i = 0; i < generators.length; i++) { for (int i = 0; i < generators.length; i++) {
fDataGeneratorCMs[i] = new DataGeneratorCacheManager( fDataGeneratorCMs[i] = new DataGeneratorCacheManager(
immediateExecutor, generators[i]); immediateExecutor, generators[i]);
generators[i].addListener(this); generators[i].addListener(this);
} }
} }
@Override @Override
public void getCount(final DataRequestMonitor<Integer> rm) { public void getCount(final DataRequestMonitor<Integer> rm) {
// Artificially delay the retrieval of the sum data to simulate // Artificially delay the retrieval of the sum data to simulate
@ -94,38 +94,38 @@ public class ACPMSumDataGenerator
// code in one place. // code in one place.
new Transaction<Integer>() { new Transaction<Integer>() {
@Override @Override
protected Integer process() protected Integer process()
throws Transaction.InvalidCacheException, throws Transaction.InvalidCacheException,
CoreException CoreException
{ {
return processCount(this); return processCount(this);
} }
}.request(rm); }.request(rm);
} }
}, },
PROCESSING_DELAY, TimeUnit.MILLISECONDS); PROCESSING_DELAY, TimeUnit.MILLISECONDS);
} }
/** /**
* Perform the calculation to get the max count for the given transaction. * Perform the calculation to get the max count for the given transaction.
* @param transaction The ACPM transaction to use for calculation. * @param transaction The ACPM transaction to use for calculation.
* @return Calculated count. * @return Calculated count.
* @throws Transaction.InvalidCacheException {@link Transaction#process} * @throws Transaction.InvalidCacheException {@link Transaction#process}
* @throws CoreException See {@link Transaction#process} * @throws CoreException See {@link Transaction#process}
*/ */
private Integer processCount(Transaction<Integer> transaction) private Integer processCount(Transaction<Integer> transaction)
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
// Assemble all needed count caches into a collection. // Assemble all needed count caches into a collection.
List<ICache<Integer>> countCaches = List<ICache<Integer>> countCaches =
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length); new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) { for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
countCaches.add(dataGeneratorCM.getCount()); countCaches.add(dataGeneratorCM.getCount());
} }
// Validate all count caches at once. This executes needed requests // Validate all count caches at once. This executes needed requests
// in parallel. // in parallel.
transaction.validate(countCaches); transaction.validate(countCaches);
// Calculate the max value and return. // Calculate the max value and return.
int maxCount = 0; int maxCount = 0;
for (ICache<Integer> countCache : countCaches) { for (ICache<Integer> countCache : countCaches) {
@ -135,7 +135,7 @@ public class ACPMSumDataGenerator
} }
@Override @Override
public void getValue(final int index, final DataRequestMonitor<Integer> rm) public void getValue(final int index, final DataRequestMonitor<Integer> rm)
{ {
// Add a processing delay. // Add a processing delay.
fExecutor.schedule( new Runnable() { fExecutor.schedule( new Runnable() {
@ -143,45 +143,45 @@ public class ACPMSumDataGenerator
public void run() { public void run() {
new Transaction<Integer>() { new Transaction<Integer>() {
@Override @Override
protected Integer process() protected Integer process()
throws Transaction.InvalidCacheException, throws Transaction.InvalidCacheException,
CoreException CoreException
{ {
return processValue(this, index); return processValue(this, index);
} }
}.request(rm); }.request(rm);
} }
}, },
PROCESSING_DELAY, TimeUnit.MILLISECONDS); PROCESSING_DELAY, TimeUnit.MILLISECONDS);
} }
/** /**
* Perform the calculation to get the sum of values at given index. * Perform the calculation to get the sum of values at given index.
* @param transaction The ACPM transaction to use for calculation. * @param transaction The ACPM transaction to use for calculation.
* @param index Index of value to calculate. * @param index Index of value to calculate.
* @return Calculated value. * @return Calculated value.
* @throws Transaction.InvalidCacheException {@link Transaction#process} * @throws Transaction.InvalidCacheException {@link Transaction#process}
* @throws CoreException See {@link Transaction#process} * @throws CoreException See {@link Transaction#process}
*/ */
private Integer processValue(Transaction<Integer> transaction, int index) private Integer processValue(Transaction<Integer> transaction, int index)
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
List<ICache<Integer>> valueCaches = List<ICache<Integer>> valueCaches =
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length); new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) { for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
valueCaches.add(dataGeneratorCM.getValue(index)); valueCaches.add(dataGeneratorCM.getValue(index));
} }
// Validate all value caches at once. This executes needed requests // Validate all value caches at once. This executes needed requests
// in parallel. // in parallel.
transaction.validate(valueCaches); transaction.validate(valueCaches);
int sum = 0; int sum = 0;
for (ICache<Integer> valueCache : valueCaches) { for (ICache<Integer> valueCache : valueCaches) {
sum += valueCache.getData(); sum += valueCache.getData();
} }
return sum; return sum;
} }
@Override @Override
public void shutdown(final RequestMonitor rm) { public void shutdown(final RequestMonitor rm) {
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) { for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
@ -220,7 +220,7 @@ public class ACPMSumDataGenerator
@Override @Override
public void countChanged() { public void countChanged() {
// Must access fListeners on executor thread. // Must access fListeners on executor thread.
try { try {
fExecutor.execute( new DsfRunnable() { fExecutor.execute( new DsfRunnable() {
@Override @Override
@ -232,7 +232,7 @@ public class ACPMSumDataGenerator
}); });
} catch (RejectedExecutionException e) {} } catch (RejectedExecutionException e) {}
} }
@Override @Override
public void valuesChanged(final Set<Integer> changed) { public void valuesChanged(final Set<Integer> changed) {
// Must access fListeners on executor thread. // Must access fListeners on executor thread.

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -52,13 +52,13 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Table;
/** /**
* Data viewer based on a table, which reads data from multiple data * Data viewer based on a table, which reads data from multiple data
* providers using ACPM methods and performs a computation on the * providers using ACPM methods and performs a computation on the
* retrieved data. * retrieved data.
* <p> * <p>
* This example builds on the {@link AsyncSumDataViewer} example. It * This example builds on the {@link AsyncSumDataViewer} example. It
* demonstrates using ACPM to solve the data consistency problem when * demonstrates using ACPM to solve the data consistency problem when
* retrieving data from multiple sources asynchronously. * retrieving data from multiple sources asynchronously.
* </p> * </p>
*/ */
@ConfinedToDsfExecutor("fDisplayExecutor") @ConfinedToDsfExecutor("fDisplayExecutor")
@ -66,47 +66,47 @@ public class ACPMSumDataViewer implements ILazyContentProvider
{ {
/** View update frequency interval. */ /** View update frequency interval. */
final private static int UPDATE_INTERVAL = 10000; final private static int UPDATE_INTERVAL = 10000;
/** Executor to use instead of Display.asyncExec(). **/ /** Executor to use instead of Display.asyncExec(). **/
@ThreadSafe @ThreadSafe
final private DsfExecutor fDisplayExecutor; final private DsfExecutor fDisplayExecutor;
/** Executor to use when retrieving data from data providers */ /** Executor to use when retrieving data from data providers */
@ThreadSafe @ThreadSafe
final private ImmediateInDsfExecutor fDataExecutor; final private ImmediateInDsfExecutor fDataExecutor;
// The viewer and generator that this content provider using. // The viewer and generator that this content provider using.
final private TableViewer fViewer; final private TableViewer fViewer;
final private DataGeneratorCacheManager[] fDataGeneratorCMs; final private DataGeneratorCacheManager[] fDataGeneratorCMs;
final private DataGeneratorCacheManager fSumGeneratorCM; final private DataGeneratorCacheManager fSumGeneratorCM;
// Fields used in request cancellation logic. // Fields used in request cancellation logic.
private List<ValueRequestMonitor> fItemDataRequestMonitors = private List<ValueRequestMonitor> fItemDataRequestMonitors =
new LinkedList<ValueRequestMonitor>(); new LinkedList<ValueRequestMonitor>();
private Set<Integer> fIndexesToCancel = new HashSet<Integer>(); private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
private int fCancelCallsPending = 0; private int fCancelCallsPending = 0;
private Future<?> fRefreshFuture; private Future<?> fRefreshFuture;
public ACPMSumDataViewer(TableViewer viewer, public ACPMSumDataViewer(TableViewer viewer,
ImmediateInDsfExecutor dataExecutor, IDataGenerator[] generators, ImmediateInDsfExecutor dataExecutor, IDataGenerator[] generators,
IDataGenerator sumGenerator) IDataGenerator sumGenerator)
{ {
fViewer = viewer; fViewer = viewer;
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor( fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
fViewer.getTable().getDisplay()); fViewer.getTable().getDisplay());
fDataExecutor = dataExecutor; fDataExecutor = dataExecutor;
// Create wrappers for data generators. Don't need to register as // Create wrappers for data generators. Don't need to register as
// listeners to generator events because the cache managers ensure data // listeners to generator events because the cache managers ensure data
// are already registered for them. // are already registered for them.
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length]; fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
for (int i = 0; i < generators.length; i++) { for (int i = 0; i < generators.length; i++) {
fDataGeneratorCMs[i] = fDataGeneratorCMs[i] =
new DataGeneratorCacheManager(fDataExecutor, generators[i]); new DataGeneratorCacheManager(fDataExecutor, generators[i]);
} }
fSumGeneratorCM = fSumGeneratorCM =
new DataGeneratorCacheManager(fDataExecutor, sumGenerator); new DataGeneratorCacheManager(fDataExecutor, sumGenerator);
// Schedule a task to refresh the viewer periodically. // Schedule a task to refresh the viewer periodically.
fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate( fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate(
new Runnable() { new Runnable() {
@ -114,25 +114,25 @@ public class ACPMSumDataViewer implements ILazyContentProvider
public void run() { public void run() {
queryItemCount(); queryItemCount();
} }
}, },
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS); UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
} }
@Override @Override
public void dispose() { public void dispose() {
// Cancel the periodic task of refreshing the view. // Cancel the periodic task of refreshing the view.
fRefreshFuture.cancel(false); fRefreshFuture.cancel(false);
// Need to dispose cache managers that were created in this class. This // Need to dispose cache managers that were created in this class. This
// needs to be done on the cache manager's thread. // needs to be done on the cache manager's thread.
Query<Object> disposeCacheManagersQuery = new Query<Object>() { Query<Object> disposeCacheManagersQuery = new Query<Object>() {
@Override @Override
protected void execute(DataRequestMonitor<Object> rm) { protected void execute(DataRequestMonitor<Object> rm) {
fSumGeneratorCM.dispose(); fSumGeneratorCM.dispose();
for (DataGeneratorCacheManager dataGeneratorCM : for (DataGeneratorCacheManager dataGeneratorCM :
fDataGeneratorCMs) fDataGeneratorCMs)
{ {
dataGeneratorCM.dispose(); dataGeneratorCM.dispose();
} }
rm.setData(new Object()); rm.setData(new Object());
rm.done(); rm.done();
@ -141,10 +141,10 @@ public class ACPMSumDataViewer implements ILazyContentProvider
fDataExecutor.execute(disposeCacheManagersQuery); fDataExecutor.execute(disposeCacheManagersQuery);
try { try {
disposeCacheManagersQuery.get(); disposeCacheManagersQuery.get();
} }
catch (InterruptedException e) {} catch (InterruptedException e) {}
catch (ExecutionException e) {} catch (ExecutionException e) {}
// Cancel any outstanding data requests. // Cancel any outstanding data requests.
for (ValueRequestMonitor rm : fItemDataRequestMonitors) { for (ValueRequestMonitor rm : fItemDataRequestMonitors) {
rm.cancel(); rm.cancel();
@ -167,7 +167,7 @@ public class ACPMSumDataViewer implements ILazyContentProvider
// Request the item for the given index. // Request the item for the given index.
queryValue(index); queryValue(index);
// Invoke a cancel task with a delay. The delay allows multiple cancel // Invoke a cancel task with a delay. The delay allows multiple cancel
// calls to be combined together improving performance of the viewer. // calls to be combined together improving performance of the viewer.
fCancelCallsPending++; fCancelCallsPending++;
fDisplayExecutor.execute( fDisplayExecutor.execute(
@ -176,9 +176,9 @@ public class ACPMSumDataViewer implements ILazyContentProvider
cancelStaleRequests(topIdx, botIdx); cancelStaleRequests(topIdx, botIdx);
}}); }});
} }
/** /**
* Calculates the number of visible items based on the top item index and * Calculates the number of visible items based on the top item index and
* table bounds. * table bounds.
* @param top Index of top item. * @param top Index of top item.
* @return calculated number of items in viewer * @return calculated number of items in viewer
@ -187,19 +187,19 @@ public class ACPMSumDataViewer implements ILazyContentProvider
Table table = fViewer.getTable(); Table table = fViewer.getTable();
int itemCount = table.getItemCount(); int itemCount = table.getItemCount();
return Math.min( return Math.min(
(table.getBounds().height / table.getItemHeight()) + 2, (table.getBounds().height / table.getItemHeight()) + 2,
itemCount - top); itemCount - top);
} }
/** /**
* Retrieve the current count. When a new count is set to viewer, the viewer * Retrieve the current count. When a new count is set to viewer, the viewer
* will refresh all items as well. * will refresh all items as well.
*/ */
private void queryItemCount() { private void queryItemCount() {
// Create the request monitor to collect the count. This request // Create the request monitor to collect the count. This request
// monitor will be completed by the following transaction. // monitor will be completed by the following transaction.
final DataRequestMonitor<Integer> rm = final DataRequestMonitor<Integer> rm =
new DataRequestMonitor<Integer>(fDisplayExecutor, null) new DataRequestMonitor<Integer>(fDisplayExecutor, null)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -209,16 +209,16 @@ public class ACPMSumDataViewer implements ILazyContentProvider
protected void handleRejectedExecutionException() {} // Shutting down, ignore. protected void handleRejectedExecutionException() {} // Shutting down, ignore.
}; };
// Use a transaction, even with a single cache. This will ensure that // Use a transaction, even with a single cache. This will ensure that
// if the cache is reset during processing by an event. The request // if the cache is reset during processing by an event. The request
// for data will be re-issued. // for data will be re-issued.
fDataExecutor.execute(new Runnable() { fDataExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
new Transaction<Integer>() { new Transaction<Integer>() {
@Override @Override
protected Integer process() protected Integer process()
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
return processCount(this); return processCount(this);
} }
@ -226,24 +226,24 @@ public class ACPMSumDataViewer implements ILazyContentProvider
} }
}); });
} }
/** /**
* Perform the count retrieval from the sum data generator. * Perform the count retrieval from the sum data generator.
* @param transaction The ACPM transaction to use for calculation. * @param transaction The ACPM transaction to use for calculation.
* @return Calculated count. * @return Calculated count.
* @throws Transaction.InvalidCacheException {@link Transaction#process} * @throws Transaction.InvalidCacheException {@link Transaction#process}
* @throws CoreException See {@link Transaction#process} * @throws CoreException See {@link Transaction#process}
*/ */
private Integer processCount(Transaction<Integer> transaction) private Integer processCount(Transaction<Integer> transaction)
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
ICache<Integer> countCache = fSumGeneratorCM.getCount(); ICache<Integer> countCache = fSumGeneratorCM.getCount();
transaction.validate(countCache); transaction.validate(countCache);
return countCache.getData(); return countCache.getData();
} }
/** /**
* Set the givne count to the viewer. This will cause the viewer will * Set the givne count to the viewer. This will cause the viewer will
* refresh all items' data as well. * refresh all items' data as well.
* <p>Note: This method must be called in the display thread. </p> * <p>Note: This method must be called in the display thread. </p>
* @param count New count to set to viewer. * @param count New count to set to viewer.
@ -259,8 +259,8 @@ public class ACPMSumDataViewer implements ILazyContentProvider
* Retrieve the current value for given index. * Retrieve the current value for given index.
*/ */
private void queryValue(final int index) { private void queryValue(final int index) {
// Create the request monitor to collect the value. This request // Create the request monitor to collect the value. This request
// monitor will be completed by the following transaction. // monitor will be completed by the following transaction.
final ValueRequestMonitor rm = new ValueRequestMonitor(index) { final ValueRequestMonitor rm = new ValueRequestMonitor(index) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
@ -271,24 +271,24 @@ public class ACPMSumDataViewer implements ILazyContentProvider
} }
@Override @Override
protected void handleRejectedExecutionException() { protected void handleRejectedExecutionException() {
// Shutting down, ignore. // Shutting down, ignore.
} }
}; };
// Save the value request monitor, to cancel it if the view is // Save the value request monitor, to cancel it if the view is
// scrolled. // scrolled.
fItemDataRequestMonitors.add(rm); fItemDataRequestMonitors.add(rm);
// Use a transaction, even with a single cache. This will ensure that // Use a transaction, even with a single cache. This will ensure that
// if the cache is reset during processing by an event. The request // if the cache is reset during processing by an event. The request
// for data will be re-issued. // for data will be re-issued.
fDataExecutor.execute(new Runnable() { fDataExecutor.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
new Transaction<String>() { new Transaction<String>() {
@Override @Override
protected String process() protected String process()
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
return processValue(this, index); return processValue(this, index);
} }
@ -296,9 +296,9 @@ public class ACPMSumDataViewer implements ILazyContentProvider
} }
}); });
} }
/** /**
* Write the view value to the viewer. * Write the view value to the viewer.
* <p>Note: This method must be called in the display thread. </p> * <p>Note: This method must be called in the display thread. </p>
* @param index Index of value to set. * @param index Index of value to set.
* @param value New value. * @param value New value.
@ -308,32 +308,32 @@ public class ACPMSumDataViewer implements ILazyContentProvider
fViewer.replace(value, index); fViewer.replace(value, index);
} }
} }
/** /**
* Perform the calculation compose the string with data provider values * Perform the calculation compose the string with data provider values
* and the sum. This implementation also validates the result. * and the sum. This implementation also validates the result.
* @param transaction The ACPM transaction to use for calculation. * @param transaction The ACPM transaction to use for calculation.
* @param index Index of value to calculate. * @param index Index of value to calculate.
* @return Calculated value. * @return Calculated value.
* @throws Transaction.InvalidCacheException {@link Transaction#process} * @throws Transaction.InvalidCacheException {@link Transaction#process}
* @throws CoreException See {@link Transaction#process} * @throws CoreException See {@link Transaction#process}
*/ */
private String processValue(Transaction<String> transaction, int index) private String processValue(Transaction<String> transaction, int index)
throws Transaction.InvalidCacheException, CoreException throws Transaction.InvalidCacheException, CoreException
{ {
List<ICache<Integer>> valueCaches = List<ICache<Integer>> valueCaches =
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length); new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) { for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
valueCaches.add(dataGeneratorCM.getValue(index)); valueCaches.add(dataGeneratorCM.getValue(index));
} }
// Validate all value caches at once. This executes needed requests // Validate all value caches at once. This executes needed requests
// in parallel. // in parallel.
transaction.validate(valueCaches); transaction.validate(valueCaches);
// TODO: evaluate sum generator cache in parallel with value caches. // TODO: evaluate sum generator cache in parallel with value caches.
ICache<Integer> sumCache = fSumGeneratorCM.getValue(index); ICache<Integer> sumCache = fSumGeneratorCM.getValue(index);
transaction.validate(sumCache); transaction.validate(sumCache);
// Compose the string with values, sum, and validation result. // Compose the string with values, sum, and validation result.
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
int calcSum = 0; int calcSum = 0;
@ -347,23 +347,23 @@ public class ACPMSumDataViewer implements ILazyContentProvider
if (calcSum != sumCache.getData()) { if (calcSum != sumCache.getData()) {
result.append(" !INCORRECT! "); result.append(" !INCORRECT! ");
} }
return result.toString(); return result.toString();
} }
/** /**
* Dedicated class for data item requests. This class holds the index * Dedicated class for data item requests. This class holds the index
* argument so it can be examined when canceling stale requests. * argument so it can be examined when canceling stale requests.
*/ */
private class ValueRequestMonitor extends DataRequestMonitor<String> { private class ValueRequestMonitor extends DataRequestMonitor<String> {
/** Index is used when canceling stale requests. */ /** Index is used when canceling stale requests. */
int fIndex; int fIndex;
ValueRequestMonitor(int index) { ValueRequestMonitor(int index) {
super(fDisplayExecutor, null); super(fDisplayExecutor, null);
fIndex = index; fIndex = index;
} }
@Override @Override
protected void handleRejectedExecutionException() { protected void handleRejectedExecutionException() {
// Shutting down, ignore. // Shutting down, ignore.
@ -373,8 +373,8 @@ public class ACPMSumDataViewer implements ILazyContentProvider
/** /**
* Cancels any outstanding value requests for items which are no longer * Cancels any outstanding value requests for items which are no longer
* visible in the viewer. * visible in the viewer.
* *
* @param topIdx Index of top visible item in viewer. * @param topIdx Index of top visible item in viewer.
* @param botIdx Index of bottom visible item in viewer. * @param botIdx Index of bottom visible item in viewer.
*/ */
private void cancelStaleRequests(int topIdx, int botIdx) { private void cancelStaleRequests(int topIdx, int botIdx) {
@ -386,31 +386,31 @@ public class ACPMSumDataViewer implements ILazyContentProvider
return; return;
} }
// Go through the outstanding requests and cancel any that // Go through the outstanding requests and cancel any that
// are not visible anymore. // are not visible anymore.
for (Iterator<ValueRequestMonitor> itr = for (Iterator<ValueRequestMonitor> itr =
fItemDataRequestMonitors.iterator(); itr.hasNext();) fItemDataRequestMonitors.iterator(); itr.hasNext();)
{ {
ValueRequestMonitor item = itr.next(); ValueRequestMonitor item = itr.next();
if (item.fIndex < topIdx || item.fIndex > botIdx) { if (item.fIndex < topIdx || item.fIndex > botIdx) {
// Set the item to canceled status, so that the data provider // Set the item to canceled status, so that the data provider
// will ignore it. // will ignore it.
item.cancel(); item.cancel();
// Add the item index to list of indexes that were canceled, // Add the item index to list of indexes that were canceled,
// which will be sent to the table widget. // which will be sent to the table widget.
fIndexesToCancel.add(item.fIndex); fIndexesToCancel.add(item.fIndex);
// Remove the item from the outstanding cancel requests. // Remove the item from the outstanding cancel requests.
itr.remove(); itr.remove();
} }
} }
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) { if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
Set<Integer> canceledIdxs = fIndexesToCancel; Set<Integer> canceledIdxs = fIndexesToCancel;
fIndexesToCancel = new HashSet<Integer>(); fIndexesToCancel = new HashSet<Integer>();
// Clear the indexes of the canceled request, so that the // Clear the indexes of the canceled request, so that the
// viewer knows to request them again when needed. // viewer knows to request them again when needed.
// Note: clearing using TableViewer.clear(int) seems very // Note: clearing using TableViewer.clear(int) seems very
// inefficient, it's better to use Table.clear(int[]). // inefficient, it's better to use Table.clear(int[]).
int[] canceledIdxsArray = new int[canceledIdxs.size()]; int[] canceledIdxsArray = new int[canceledIdxs.size()];
@ -421,11 +421,11 @@ public class ACPMSumDataViewer implements ILazyContentProvider
fViewer.getTable().clear(canceledIdxsArray); fViewer.getTable().clear(canceledIdxsArray);
} }
} }
/** /**
* The entry point for the example. * The entry point for the example.
* @param args Program arguments. * @param args Program arguments.
*/ */
public static void main(String[] args) { public static void main(String[] args) {
// Create the shell to hold the viewer. // Create the shell to hold the viewer.
Display display = new Display(); Display display = new Display();
@ -436,23 +436,23 @@ public class ACPMSumDataViewer implements ILazyContentProvider
Font font = new Font(display, "Courier", 10, SWT.NORMAL); Font font = new Font(display, "Courier", 10, SWT.NORMAL);
// Create the table viewer. // Create the table viewer.
TableViewer tableViewer = TableViewer tableViewer =
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL); new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
tableViewer.getControl().setLayoutData(data); tableViewer.getControl().setLayoutData(data);
DsfExecutor executor = new DefaultDsfExecutor("Example executor"); DsfExecutor executor = new DefaultDsfExecutor("Example executor");
// Create the data generator. // Create the data generator.
final IDataGenerator[] generators = new IDataGenerator[5]; final IDataGenerator[] generators = new IDataGenerator[5];
for (int i = 0; i < generators.length; i++) { for (int i = 0; i < generators.length; i++) {
generators[i] = new DataGeneratorWithExecutor(executor); generators[i] = new DataGeneratorWithExecutor(executor);
} }
final IDataGenerator sumGenerator = final IDataGenerator sumGenerator =
new ACPMSumDataGenerator(executor, generators); new ACPMSumDataGenerator(executor, generators);
// Create the content provider which will populate the viewer. // Create the content provider which will populate the viewer.
ACPMSumDataViewer contentProvider = new ACPMSumDataViewer( ACPMSumDataViewer contentProvider = new ACPMSumDataViewer(
tableViewer, new ImmediateInDsfExecutor(executor), tableViewer, new ImmediateInDsfExecutor(executor),
generators, sumGenerator); generators, sumGenerator);
tableViewer.setContentProvider(contentProvider); tableViewer.setContentProvider(contentProvider);
tableViewer.setInput(new Object()); tableViewer.setInput(new Object());
@ -464,7 +464,7 @@ public class ACPMSumDataViewer implements ILazyContentProvider
if (!display.readAndDispatch()) if (!display.readAndDispatch())
display.sleep(); display.sleep();
} }
// The IDataGenerator.shutdown() method is asynchronous, this requires // The IDataGenerator.shutdown() method is asynchronous, this requires
// using a query again in order to wait for its completion. // using a query again in order to wait for its completion.
Query<Object> shutdownQuery = new Query<Object>() { Query<Object> shutdownQuery = new Query<Object>() {
@ -483,10 +483,10 @@ public class ACPMSumDataViewer implements ILazyContentProvider
executor.execute(shutdownQuery); executor.execute(shutdownQuery);
try { try {
shutdownQuery.get(); shutdownQuery.get();
} catch (Exception e) {} } catch (Exception e) {}
// Shut down the display. // Shut down the display.
font.dispose(); font.dispose();
display.dispose(); display.dispose();
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -45,43 +45,43 @@ import org.eclipse.swt.widgets.Table;
/** /**
* Data viewer based on a table, which reads data using asynchronous methods. * Data viewer based on a table, which reads data using asynchronous methods.
* <p> * <p>
* This viewer implements the {@link ILazyContentProvider} interface * This viewer implements the {@link ILazyContentProvider} interface
* which is used by the JFace TableViewer class to populate a Table. This * which is used by the JFace TableViewer class to populate a Table. This
* interface contains separate asynchronous methods for requesting the count * interface contains separate asynchronous methods for requesting the count
* and values for individual indexes, which neatly correspond to the methods * and values for individual indexes, which neatly correspond to the methods
* in {@link IDataGenerator}. As an added optimization, this viewer * in {@link IDataGenerator}. As an added optimization, this viewer
* implementation checks for the range of visible items in the view upon each * implementation checks for the range of visible items in the view upon each
* request, and it cancels old requests which scroll out of view but have not * request, and it cancels old requests which scroll out of view but have not
* been completed yet. However, it is up to the data generator implementation * been completed yet. However, it is up to the data generator implementation
* to check the canceled state of the requests and ignore them. * to check the canceled state of the requests and ignore them.
* </p> * </p>
*/ */
@ConfinedToDsfExecutor("fDisplayExecutor") @ConfinedToDsfExecutor("fDisplayExecutor")
public class AsyncDataViewer public class AsyncDataViewer
implements ILazyContentProvider, IDataGenerator.Listener implements ILazyContentProvider, IDataGenerator.Listener
{ {
// Executor to use instead of Display.asyncExec(). // Executor to use instead of Display.asyncExec().
@ThreadSafe @ThreadSafe
final private DsfExecutor fDisplayExecutor; final private DsfExecutor fDisplayExecutor;
// The viewer and generator that this content provider using. // The viewer and generator that this content provider using.
final private TableViewer fViewer; final private TableViewer fViewer;
final private IDataGenerator fDataGenerator; final private IDataGenerator fDataGenerator;
// Fields used in request cancellation logic. // Fields used in request cancellation logic.
private List<ValueDataRequestMonitor> fItemDataRequestMonitors = private List<ValueDataRequestMonitor> fItemDataRequestMonitors =
new LinkedList<ValueDataRequestMonitor>(); new LinkedList<ValueDataRequestMonitor>();
private Set<Integer> fIndexesToCancel = new HashSet<Integer>(); private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
private int fCancelCallsPending = 0; private int fCancelCallsPending = 0;
public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) { public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) {
fViewer = viewer; fViewer = viewer;
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor( fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
fViewer.getTable().getDisplay()); fViewer.getTable().getDisplay());
fDataGenerator = generator; fDataGenerator = generator;
fDataGenerator.addListener(this); fDataGenerator.addListener(this);
} }
@Override @Override
public void dispose() { public void dispose() {
fDataGenerator.removeListener(this); fDataGenerator.removeListener(this);
@ -102,19 +102,19 @@ public class AsyncDataViewer
// Request the item for the given index. // Request the item for the given index.
queryValue(index); queryValue(index);
// Invoke a cancel task with a delay. The delay allows multiple cancel // Invoke a cancel task with a delay. The delay allows multiple cancel
// calls to be combined together improving performance of the viewer. // calls to be combined together improving performance of the viewer.
fCancelCallsPending++; fCancelCallsPending++;
fDisplayExecutor.schedule( fDisplayExecutor.schedule(
new Runnable() { @Override new Runnable() { @Override
public void run() { public void run() {
cancelStaleRequests(topIdx, botIdx); cancelStaleRequests(topIdx, botIdx);
}}, }},
1, TimeUnit.MILLISECONDS); 1, TimeUnit.MILLISECONDS);
} }
/** /**
* Calculates the number of visible items based on the top item index and * Calculates the number of visible items based on the top item index and
* table bounds. * table bounds.
* @param top Index of top item. * @param top Index of top item.
* @return calculated number of items in viewer * @return calculated number of items in viewer
@ -123,24 +123,24 @@ public class AsyncDataViewer
Table table = fViewer.getTable(); Table table = fViewer.getTable();
int itemCount = table.getItemCount(); int itemCount = table.getItemCount();
return Math.min( return Math.min(
(table.getBounds().height / table.getItemHeight()) + 2, (table.getBounds().height / table.getItemHeight()) + 2,
itemCount - top); itemCount - top);
} }
@Override @Override
@ThreadSafe @ThreadSafe
public void countChanged() { public void countChanged() {
queryItemCount(); queryItemCount();
} }
@Override @Override
@ThreadSafe @ThreadSafe
public void valuesChanged(final Set<Integer> indexes) { public void valuesChanged(final Set<Integer> indexes) {
// Mark the changed items in table viewer as dirty, this will // Mark the changed items in table viewer as dirty, this will
// trigger update requests for these indexes if they are // trigger update requests for these indexes if they are
// visible in the viewer. // visible in the viewer.
final TableViewer tableViewer = fViewer; final TableViewer tableViewer = fViewer;
fDisplayExecutor.execute( new Runnable() { fDisplayExecutor.execute( new Runnable() {
@Override @Override
public void run() { public void run() {
if (!fViewer.getTable().isDisposed()) { if (!fViewer.getTable().isDisposed()) {
@ -150,18 +150,18 @@ public class AsyncDataViewer
} }
}}); }});
} }
/** /**
* Retrieve the up to date count. When a new count is set to viewer, the * Retrieve the up to date count. When a new count is set to viewer, the
* viewer will refresh all items as well. * viewer will refresh all items as well.
*/ */
private void queryItemCount() { private void queryItemCount() {
// Request count from data provider. When the count is returned, we // Request count from data provider. When the count is returned, we
// have to re-dispatch into the display thread to avoid calling // have to re-dispatch into the display thread to avoid calling
// the table widget on the DSF dispatch thread. // the table widget on the DSF dispatch thread.
fIndexesToCancel.clear(); fIndexesToCancel.clear();
fDataGenerator.getCount( fDataGenerator.getCount(
// Use the display executor to construct the request monitor, this // Use the display executor to construct the request monitor, this
// will cause the handleCompleted() method to be automatically // will cause the handleCompleted() method to be automatically
// called on the display thread. // called on the display thread.
new DataRequestMonitor<Integer>(fDisplayExecutor, null) { new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
@ -172,40 +172,40 @@ public class AsyncDataViewer
fViewer.getTable().clearAll(); fViewer.getTable().clearAll();
} }
} }
}); });
} }
/** /**
* Retrieves value of an element at given index. When complete the value * Retrieves value of an element at given index. When complete the value
* is written to the viewer. * is written to the viewer.
* @param index Index of value to retrieve. * @param index Index of value to retrieve.
*/ */
private void queryValue(final int index) { private void queryValue(final int index) {
ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index); ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index);
fItemDataRequestMonitors.add(rm); fItemDataRequestMonitors.add(rm);
fDataGenerator.getValue(index, rm); fDataGenerator.getValue(index, rm);
} }
/** /**
* Dedicated class for data item requests. This class holds the index * Dedicated class for data item requests. This class holds the index
* argument so it can be examined when canceling stale requests. * argument so it can be examined when canceling stale requests.
*/ */
private class ValueDataRequestMonitor extends DataRequestMonitor<Integer> { private class ValueDataRequestMonitor extends DataRequestMonitor<Integer> {
/** Index is used when canceling stale requests. */ /** Index is used when canceling stale requests. */
int fIndex; int fIndex;
ValueDataRequestMonitor(int index) { ValueDataRequestMonitor(int index) {
super(fDisplayExecutor, null); super(fDisplayExecutor, null);
fIndex = index; fIndex = index;
} }
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
fItemDataRequestMonitors.remove(this); fItemDataRequestMonitors.remove(this);
// Check if the request completed successfully, otherwise ignore // Check if the request completed successfully, otherwise ignore
// it. // it.
if (isSuccess()) { if (isSuccess()) {
if (!fViewer.getTable().isDisposed()) { if (!fViewer.getTable().isDisposed()) {
@ -214,7 +214,7 @@ public class AsyncDataViewer
} }
} }
} }
private void cancelStaleRequests(int topIdx, int botIdx) { private void cancelStaleRequests(int topIdx, int botIdx) {
// Decrement the count of outstanding cancel calls. // Decrement the count of outstanding cancel calls.
fCancelCallsPending--; fCancelCallsPending--;
@ -222,32 +222,32 @@ public class AsyncDataViewer
// Must check again, in case disposed while re-dispatching. // Must check again, in case disposed while re-dispatching.
if (fDataGenerator == null || fViewer.getTable().isDisposed()) return; if (fDataGenerator == null || fViewer.getTable().isDisposed()) return;
// Go through the outstanding requests and cancel any that // Go through the outstanding requests and cancel any that
// are not visible anymore. // are not visible anymore.
for (Iterator<ValueDataRequestMonitor> itr = for (Iterator<ValueDataRequestMonitor> itr =
fItemDataRequestMonitors.iterator(); fItemDataRequestMonitors.iterator();
itr.hasNext();) itr.hasNext();)
{ {
ValueDataRequestMonitor item = itr.next(); ValueDataRequestMonitor item = itr.next();
if (item.fIndex < topIdx || item.fIndex > botIdx) { if (item.fIndex < topIdx || item.fIndex > botIdx) {
// Set the item to canceled status, so that the data provider // Set the item to canceled status, so that the data provider
// will ignore it. // will ignore it.
item.cancel(); item.cancel();
// Add the item index to list of indexes that were canceled, // Add the item index to list of indexes that were canceled,
// which will be sent to the table widget. // which will be sent to the table widget.
fIndexesToCancel.add(item.fIndex); fIndexesToCancel.add(item.fIndex);
// Remove the item from the outstanding cancel requests. // Remove the item from the outstanding cancel requests.
itr.remove(); itr.remove();
} }
} }
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) { if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
Set<Integer> canceledIdxs = fIndexesToCancel; Set<Integer> canceledIdxs = fIndexesToCancel;
fIndexesToCancel = new HashSet<Integer>(); fIndexesToCancel = new HashSet<Integer>();
// Clear the indexes of the canceled request, so that the // Clear the indexes of the canceled request, so that the
// viewer knows to request them again when needed. // viewer knows to request them again when needed.
// Note: clearing using TableViewer.clear(int) seems very // Note: clearing using TableViewer.clear(int) seems very
// inefficient, it's better to use Table.clear(int[]). // inefficient, it's better to use Table.clear(int[]).
int[] canceledIdxsArray = new int[canceledIdxs.size()]; int[] canceledIdxsArray = new int[canceledIdxs.size()];
@ -258,8 +258,8 @@ public class AsyncDataViewer
fViewer.getTable().clear(canceledIdxsArray); fViewer.getTable().clear(canceledIdxsArray);
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
// Create the shell to hold the viewer. // Create the shell to hold the viewer.
Display display = new Display(); Display display = new Display();
@ -270,15 +270,15 @@ public class AsyncDataViewer
Font font = new Font(display, "Courier", 10, SWT.NORMAL); Font font = new Font(display, "Courier", 10, SWT.NORMAL);
// Create the table viewer. // Create the table viewer.
TableViewer tableViewer = TableViewer tableViewer =
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL); new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
tableViewer.getControl().setLayoutData(data); tableViewer.getControl().setLayoutData(data);
// Create the data generator. // Create the data generator.
final IDataGenerator generator = new DataGeneratorWithExecutor(); final IDataGenerator generator = new DataGeneratorWithExecutor();
// Create the content provider which will populate the viewer. // Create the content provider which will populate the viewer.
AsyncDataViewer contentProvider = AsyncDataViewer contentProvider =
new AsyncDataViewer(tableViewer, generator); new AsyncDataViewer(tableViewer, generator);
tableViewer.setContentProvider(contentProvider); tableViewer.setContentProvider(contentProvider);
tableViewer.setInput(new Object()); tableViewer.setInput(new Object());
@ -290,7 +290,7 @@ public class AsyncDataViewer
if (!display.readAndDispatch()) if (!display.readAndDispatch())
display.sleep(); display.sleep();
} }
// The IDataGenerator.shutdown() method is asynchronous, this requires // The IDataGenerator.shutdown() method is asynchronous, this requires
// using a query again in order to wait for its completion. // using a query again in order to wait for its completion.
Query<Object> shutdownQuery = new Query<Object>() { Query<Object> shutdownQuery = new Query<Object>() {
@ -302,10 +302,10 @@ public class AsyncDataViewer
ImmediateExecutor.getInstance().execute(shutdownQuery); ImmediateExecutor.getInstance().execute(shutdownQuery);
try { try {
shutdownQuery.get(); shutdownQuery.get();
} catch (Exception e) {} } catch (Exception e) {}
// Shut down the display. // Shut down the display.
font.dispose(); font.dispose();
display.dispose(); display.dispose();
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -27,19 +27,19 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
/** /**
* A data generator which performs a sum computation on data retrieved from a * A data generator which performs a sum computation on data retrieved from a
* number of other data generators. The data retrieval from other generators * number of other data generators. The data retrieval from other generators
* is performed in parallel and the result is calculated once all data is * is performed in parallel and the result is calculated once all data is
* received. * received.
* <p> * <p>
* This calculating generator does not listen to events from the data * This calculating generator does not listen to events from the data
* providers so it relies on the client to re-retrieve data as needed. * providers so it relies on the client to re-retrieve data as needed.
* </p> * </p>
*/ */
public class AsyncSumDataGenerator implements IDataGenerator { public class AsyncSumDataGenerator implements IDataGenerator {
/** /**
* DSF executor used to serialize data access within this data generator. * DSF executor used to serialize data access within this data generator.
*/ */
final private DsfExecutor fExecutor; final private DsfExecutor fExecutor;
@ -48,13 +48,13 @@ public class AsyncSumDataGenerator implements IDataGenerator {
*/ */
final private IDataGenerator[] fDataGenerators; final private IDataGenerator[] fDataGenerators;
public AsyncSumDataGenerator(DsfExecutor executor, public AsyncSumDataGenerator(DsfExecutor executor,
IDataGenerator[] generators) IDataGenerator[] generators)
{ {
fExecutor = executor; fExecutor = executor;
fDataGenerators = generators; fDataGenerators = generators;
} }
@Override @Override
public void getCount(final DataRequestMonitor<Integer> rm) { public void getCount(final DataRequestMonitor<Integer> rm) {
// Artificially delay the retrieval of the sum data to simulate // Artificially delay the retrieval of the sum data to simulate
@ -64,10 +64,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
public void run() { public void run() {
doGetCount(rm); doGetCount(rm);
} }
}, },
PROCESSING_DELAY, TimeUnit.MILLISECONDS); PROCESSING_DELAY, TimeUnit.MILLISECONDS);
} }
/** /**
* Performs the actual count retrieval and calculation. * Performs the actual count retrieval and calculation.
* @param rm Request monitor to complete with data. * @param rm Request monitor to complete with data.
@ -75,10 +75,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
private void doGetCount(final DataRequestMonitor<Integer> rm) { private void doGetCount(final DataRequestMonitor<Integer> rm) {
// Array to store counts retrieved asynchronously // Array to store counts retrieved asynchronously
final int[] counts = new int[fDataGenerators.length]; final int[] counts = new int[fDataGenerators.length];
// Counting request monitor is called once all data is retrieved. // Counting request monitor is called once all data is retrieved.
final CountingRequestMonitor crm = final CountingRequestMonitor crm =
new CountingRequestMonitor(fExecutor, rm) new CountingRequestMonitor(fExecutor, rm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -89,26 +89,26 @@ public class AsyncSumDataGenerator implements IDataGenerator {
rm.done(); rm.done();
}; };
}; };
// Each call to data generator fills in one value in array. // Each call to data generator fills in one value in array.
for (int i = 0; i < fDataGenerators.length; i++) { for (int i = 0; i < fDataGenerators.length; i++) {
final int finalI = i; final int finalI = i;
fDataGenerators[i].getCount( fDataGenerators[i].getCount(
new DataRequestMonitor<Integer>( new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm) ImmediateExecutor.getInstance(), crm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
counts[finalI] = getData(); counts[finalI] = getData();
crm.done(); crm.done();
} }
}); });
} }
crm.setDoneCount(fDataGenerators.length); crm.setDoneCount(fDataGenerators.length);
} }
@Override @Override
public void getValue(final int index, final DataRequestMonitor<Integer> rm) public void getValue(final int index, final DataRequestMonitor<Integer> rm)
{ {
// Artificially delay the retrieval of the sum data to simulate // Artificially delay the retrieval of the sum data to simulate
// real processing time. // real processing time.
@ -117,10 +117,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
public void run() { public void run() {
doGetValue(index, rm); doGetValue(index, rm);
} }
}, },
PROCESSING_DELAY, TimeUnit.MILLISECONDS); PROCESSING_DELAY, TimeUnit.MILLISECONDS);
} }
/** /**
* Performs the actual value retrieval and calculation. * Performs the actual value retrieval and calculation.
* @param rm Request monitor to complete with data. * @param rm Request monitor to complete with data.
@ -128,10 +128,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
private void doGetValue(int index, final DataRequestMonitor<Integer> rm) { private void doGetValue(int index, final DataRequestMonitor<Integer> rm) {
// Array to store counts retrieved asynchronously // Array to store counts retrieved asynchronously
final int[] values = new int[fDataGenerators.length]; final int[] values = new int[fDataGenerators.length];
// Counting request monitor is called once all data is retrieved. // Counting request monitor is called once all data is retrieved.
final CountingRequestMonitor crm = final CountingRequestMonitor crm =
new CountingRequestMonitor(fExecutor, rm) new CountingRequestMonitor(fExecutor, rm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -144,22 +144,22 @@ public class AsyncSumDataGenerator implements IDataGenerator {
rm.done(); rm.done();
}; };
}; };
// Each call to data generator fills in one value in array. // Each call to data generator fills in one value in array.
for (int i = 0; i < fDataGenerators.length; i++) { for (int i = 0; i < fDataGenerators.length; i++) {
final int finalI = i; final int finalI = i;
fDataGenerators[i].getValue( fDataGenerators[i].getValue(
index, index,
new DataRequestMonitor<Integer>( new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm) ImmediateExecutor.getInstance(), crm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
values[finalI] = getData(); values[finalI] = getData();
crm.done(); crm.done();
} }
}); });
} }
crm.setDoneCount(fDataGenerators.length); crm.setDoneCount(fDataGenerators.length);
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -46,20 +46,20 @@ import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Table;
/** /**
* Data viewer based on a table, which reads data from multiple data * Data viewer based on a table, which reads data from multiple data
* providers using asynchronous methods and performs a compultation * providers using asynchronous methods and performs a compultation
* on the retrieved data. * on the retrieved data.
* <p> * <p>
* This example builds on the {@link AsyncDataViewer} example and * This example builds on the {@link AsyncDataViewer} example and
* demonstrates the pitfalls of retrieving data from multiple sources * demonstrates the pitfalls of retrieving data from multiple sources
* asynchronously: The data is retrieved separate from a set of providers * asynchronously: The data is retrieved separate from a set of providers
* as well as from a data provider that sums the values from the other * as well as from a data provider that sums the values from the other
* providers. The viewer then performs a check to ensure consistency of * providers. The viewer then performs a check to ensure consistency of
* retrieved data. If the retrieved data is inconsistent an "INCORRECT" * retrieved data. If the retrieved data is inconsistent an "INCORRECT"
* label is added in the viewer. * label is added in the viewer.
* </p> * </p>
* <p> * <p>
* This viewer is updated periodically every 10 seconds, instead of being * This viewer is updated periodically every 10 seconds, instead of being
* updated with every change in every data provider, which would overwhelm * updated with every change in every data provider, which would overwhelm
* the viewer. * the viewer.
* </p> * </p>
@ -69,25 +69,25 @@ public class AsyncSumDataViewer implements ILazyContentProvider
{ {
/** View update frequency interval. */ /** View update frequency interval. */
final private static int UPDATE_INTERVAL = 10000; final private static int UPDATE_INTERVAL = 10000;
/** Executor to use instead of Display.asyncExec(). **/ /** Executor to use instead of Display.asyncExec(). **/
@ThreadSafe @ThreadSafe
final private DsfExecutor fDisplayExecutor; final private DsfExecutor fDisplayExecutor;
// The viewer and generator that this content provider using. // The viewer and generator that this content provider using.
final private TableViewer fViewer; final private TableViewer fViewer;
final private IDataGenerator[] fDataGenerators; final private IDataGenerator[] fDataGenerators;
final private IDataGenerator fSumGenerator; final private IDataGenerator fSumGenerator;
// Fields used in request cancellation logic. // Fields used in request cancellation logic.
private List<ValueCountingRequestMonitor> fItemDataRequestMonitors = private List<ValueCountingRequestMonitor> fItemDataRequestMonitors =
new LinkedList<ValueCountingRequestMonitor>(); new LinkedList<ValueCountingRequestMonitor>();
private Set<Integer> fIndexesToCancel = new HashSet<Integer>(); private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
private int fCancelCallsPending = 0; private int fCancelCallsPending = 0;
private Future<?> fRefreshFuture; private Future<?> fRefreshFuture;
public AsyncSumDataViewer(TableViewer viewer, public AsyncSumDataViewer(TableViewer viewer,
IDataGenerator[] generators, IDataGenerator sumGenerator) IDataGenerator[] generators, IDataGenerator sumGenerator)
{ {
fViewer = viewer; fViewer = viewer;
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor( fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
@ -102,15 +102,15 @@ public class AsyncSumDataViewer implements ILazyContentProvider
public void run() { public void run() {
queryItemCount(); queryItemCount();
} }
}, },
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS); UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
} }
@Override @Override
public void dispose() { public void dispose() {
// Cancel the periodic task of refreshing the view. // Cancel the periodic task of refreshing the view.
fRefreshFuture.cancel(false); fRefreshFuture.cancel(false);
// Cancel any outstanding data requests. // Cancel any outstanding data requests.
for (ValueCountingRequestMonitor rm : fItemDataRequestMonitors) { for (ValueCountingRequestMonitor rm : fItemDataRequestMonitors) {
rm.cancel(); rm.cancel();
@ -133,7 +133,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
// Request the item for the given index. // Request the item for the given index.
queryValue(index); queryValue(index);
// Invoke a cancel task with a delay. The delay allows multiple cancel // Invoke a cancel task with a delay. The delay allows multiple cancel
// calls to be combined together improving performance of the viewer. // calls to be combined together improving performance of the viewer.
fCancelCallsPending++; fCancelCallsPending++;
fDisplayExecutor.execute( fDisplayExecutor.execute(
@ -142,9 +142,9 @@ public class AsyncSumDataViewer implements ILazyContentProvider
cancelStaleRequests(topIdx, botIdx); cancelStaleRequests(topIdx, botIdx);
}}); }});
} }
/** /**
* Calculates the number of visible items based on the top item index and * Calculates the number of visible items based on the top item index and
* table bounds. * table bounds.
* @param top Index of top item. * @param top Index of top item.
* @return calculated number of items in viewer * @return calculated number of items in viewer
@ -153,19 +153,19 @@ public class AsyncSumDataViewer implements ILazyContentProvider
Table table = fViewer.getTable(); Table table = fViewer.getTable();
int itemCount = table.getItemCount(); int itemCount = table.getItemCount();
return Math.min( return Math.min(
(table.getBounds().height / table.getItemHeight()) + 2, (table.getBounds().height / table.getItemHeight()) + 2,
itemCount - top); itemCount - top);
} }
/** /**
* Retrieve the up to date count. * Retrieve the up to date count.
*/ */
private void queryItemCount() { private void queryItemCount() {
// Note:The count is retrieved from the sum generator only, the sum // Note:The count is retrieved from the sum generator only, the sum
// generator is responsible for calculating the count based on // generator is responsible for calculating the count based on
// individual data providers' counts. // individual data providers' counts.
fIndexesToCancel.clear(); fIndexesToCancel.clear();
fSumGenerator.getCount( fSumGenerator.getCount(
new DataRequestMonitor<Integer>(fDisplayExecutor, null) { new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -174,12 +174,12 @@ public class AsyncSumDataViewer implements ILazyContentProvider
@Override @Override
protected void handleRejectedExecutionException() { protected void handleRejectedExecutionException() {
// Shutting down, ignore. // Shutting down, ignore.
} }
}); });
} }
/** /**
* Set the givne count to the viewer. This will cause the viewer will * Set the givne count to the viewer. This will cause the viewer will
* refresh all items' data as well. * refresh all items' data as well.
* @param count New count to set to viewer. * @param count New count to set to viewer.
*/ */
@ -189,28 +189,28 @@ public class AsyncSumDataViewer implements ILazyContentProvider
fViewer.getTable().clearAll(); fViewer.getTable().clearAll();
} }
} }
/** /**
* Retrieves value of an element at given index. When complete the value * Retrieves value of an element at given index. When complete the value
* is written to the viewer. * is written to the viewer.
* @param index Index of value to retrieve. * @param index Index of value to retrieve.
*/ */
private void queryValue(final int index) { private void queryValue(final int index) {
// Values retrieved asynchronously from providers are stored in local // Values retrieved asynchronously from providers are stored in local
// arrays. // arrays.
final int[] values = new int[fDataGenerators.length]; final int[] values = new int[fDataGenerators.length];
final int[] sum = new int[1]; final int[] sum = new int[1];
// Counting request monitor is invoked when the required number of // Counting request monitor is invoked when the required number of
// value requests is completed. // value requests is completed.
final ValueCountingRequestMonitor crm = final ValueCountingRequestMonitor crm =
new ValueCountingRequestMonitor(index) new ValueCountingRequestMonitor(index)
{ {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
fItemDataRequestMonitors.remove(this); fItemDataRequestMonitors.remove(this);
// Check if the request completed successfully, otherwise // Check if the request completed successfully, otherwise
// ignore it. // ignore it.
if (isSuccess()) { if (isSuccess()) {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
@ -229,45 +229,45 @@ public class AsyncSumDataViewer implements ILazyContentProvider
} }
}; };
}; };
// Request data from each data generator. // Request data from each data generator.
for (int i = 0; i < fDataGenerators.length; i++) { for (int i = 0; i < fDataGenerators.length; i++) {
final int finalI = i; final int finalI = i;
fDataGenerators[i].getValue( fDataGenerators[i].getValue(
index, index,
// Use the display executor to construct the request monitor, // Use the display executor to construct the request monitor,
// this will cause the handleCompleted() method to be // this will cause the handleCompleted() method to be
// automatically called on the display thread. // automatically called on the display thread.
new DataRequestMonitor<Integer>( new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm) ImmediateExecutor.getInstance(), crm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
values[finalI] = getData(); values[finalI] = getData();
crm.done(); crm.done();
} }
}); });
} }
// Separately request data from the sum data generator. // Separately request data from the sum data generator.
fSumGenerator.getValue( fSumGenerator.getValue(
index, index,
new DataRequestMonitor<Integer>( new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm) ImmediateExecutor.getInstance(), crm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
sum[0] = getData(); sum[0] = getData();
crm.done(); crm.done();
} }
}); });
crm.setDoneCount(fDataGenerators.length + 1); crm.setDoneCount(fDataGenerators.length + 1);
fItemDataRequestMonitors.add(crm); fItemDataRequestMonitors.add(crm);
} }
/** /**
* Write the view value to the viewer. * Write the view value to the viewer.
* <p>Note: This method must be called in the display thread. </p> * <p>Note: This method must be called in the display thread. </p>
* @param index Index of value to set. * @param index Index of value to set.
* @param value New value. * @param value New value.
@ -277,20 +277,20 @@ public class AsyncSumDataViewer implements ILazyContentProvider
fViewer.replace(value, index); fViewer.replace(value, index);
} }
} }
/** /**
* Dedicated class for data item requests. This class holds the index * Dedicated class for data item requests. This class holds the index
* argument so it can be examined when canceling stale requests. * argument so it can be examined when canceling stale requests.
*/ */
private class ValueCountingRequestMonitor extends CountingRequestMonitor { private class ValueCountingRequestMonitor extends CountingRequestMonitor {
/** Index is used when canceling stale requests. */ /** Index is used when canceling stale requests. */
int fIndex; int fIndex;
ValueCountingRequestMonitor(int index) { ValueCountingRequestMonitor(int index) {
super(fDisplayExecutor, null); super(fDisplayExecutor, null);
fIndex = index; fIndex = index;
} }
@Override @Override
protected void handleRejectedExecutionException() { protected void handleRejectedExecutionException() {
// Shutting down, ignore. // Shutting down, ignore.
@ -300,8 +300,8 @@ public class AsyncSumDataViewer implements ILazyContentProvider
/** /**
* Cancels any outstanding value requests for items which are no longer * Cancels any outstanding value requests for items which are no longer
* visible in the viewer. * visible in the viewer.
* *
* @param topIdx Index of top visible item in viewer. * @param topIdx Index of top visible item in viewer.
* @param botIdx Index of bottom visible item in viewer. * @param botIdx Index of bottom visible item in viewer.
*/ */
private void cancelStaleRequests(int topIdx, int botIdx) { private void cancelStaleRequests(int topIdx, int botIdx) {
@ -311,31 +311,31 @@ public class AsyncSumDataViewer implements ILazyContentProvider
// Must check again, in case disposed while re-dispatching. // Must check again, in case disposed while re-dispatching.
if (fDataGenerators == null || fViewer.getTable().isDisposed()) return; if (fDataGenerators == null || fViewer.getTable().isDisposed()) return;
// Go through the outstanding requests and cancel any that // Go through the outstanding requests and cancel any that
// are not visible anymore. // are not visible anymore.
for (Iterator<ValueCountingRequestMonitor> itr = for (Iterator<ValueCountingRequestMonitor> itr =
fItemDataRequestMonitors.iterator(); itr.hasNext();) fItemDataRequestMonitors.iterator(); itr.hasNext();)
{ {
ValueCountingRequestMonitor item = itr.next(); ValueCountingRequestMonitor item = itr.next();
if (item.fIndex < topIdx || item.fIndex > botIdx) { if (item.fIndex < topIdx || item.fIndex > botIdx) {
// Set the item to canceled status, so that the data provider // Set the item to canceled status, so that the data provider
// will ignore it. // will ignore it.
item.cancel(); item.cancel();
// Add the item index to list of indexes that were canceled, // Add the item index to list of indexes that were canceled,
// which will be sent to the table widget. // which will be sent to the table widget.
fIndexesToCancel.add(item.fIndex); fIndexesToCancel.add(item.fIndex);
// Remove the item from the outstanding cancel requests. // Remove the item from the outstanding cancel requests.
itr.remove(); itr.remove();
} }
} }
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) { if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
Set<Integer> canceledIdxs = fIndexesToCancel; Set<Integer> canceledIdxs = fIndexesToCancel;
fIndexesToCancel = new HashSet<Integer>(); fIndexesToCancel = new HashSet<Integer>();
// Clear the indexes of the canceled request, so that the // Clear the indexes of the canceled request, so that the
// viewer knows to request them again when needed. // viewer knows to request them again when needed.
// Note: clearing using TableViewer.clear(int) seems very // Note: clearing using TableViewer.clear(int) seems very
// inefficient, it's better to use Table.clear(int[]). // inefficient, it's better to use Table.clear(int[]).
int[] canceledIdxsArray = new int[canceledIdxs.size()]; int[] canceledIdxsArray = new int[canceledIdxs.size()];
@ -346,7 +346,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
fViewer.getTable().clear(canceledIdxsArray); fViewer.getTable().clear(canceledIdxsArray);
} }
} }
/** /**
* The entry point for the example. * The entry point for the example.
* @param args Program arguments. * @param args Program arguments.
@ -361,24 +361,24 @@ public class AsyncSumDataViewer implements ILazyContentProvider
Font font = new Font(display, "Courier", 10, SWT.NORMAL); Font font = new Font(display, "Courier", 10, SWT.NORMAL);
// Create the table viewer. // Create the table viewer.
TableViewer tableViewer = TableViewer tableViewer =
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL); new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
tableViewer.getControl().setLayoutData(data); tableViewer.getControl().setLayoutData(data);
// Single executor (and single thread) is used by all data generators, // Single executor (and single thread) is used by all data generators,
// including the sum generator. // including the sum generator.
DsfExecutor executor = new DefaultDsfExecutor("Example executor"); DsfExecutor executor = new DefaultDsfExecutor("Example executor");
// Create the data generator. // Create the data generator.
final IDataGenerator[] generators = new IDataGenerator[5]; final IDataGenerator[] generators = new IDataGenerator[5];
for (int i = 0; i < generators.length; i++) { for (int i = 0; i < generators.length; i++) {
generators[i] = new DataGeneratorWithExecutor(executor); generators[i] = new DataGeneratorWithExecutor(executor);
} }
final IDataGenerator sumGenerator = final IDataGenerator sumGenerator =
new AsyncSumDataGenerator(executor, generators); new AsyncSumDataGenerator(executor, generators);
// Create the content provider which will populate the viewer. // Create the content provider which will populate the viewer.
AsyncSumDataViewer contentProvider = AsyncSumDataViewer contentProvider =
new AsyncSumDataViewer(tableViewer, generators, sumGenerator); new AsyncSumDataViewer(tableViewer, generators, sumGenerator);
tableViewer.setContentProvider(contentProvider); tableViewer.setContentProvider(contentProvider);
tableViewer.setInput(new Object()); tableViewer.setInput(new Object());
@ -390,7 +390,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
if (!display.readAndDispatch()) if (!display.readAndDispatch())
display.sleep(); display.sleep();
} }
// The IDataGenerator.shutdown() method is asynchronous, this requires // The IDataGenerator.shutdown() method is asynchronous, this requires
// using a query again in order to wait for its completion. // using a query again in order to wait for its completion.
Query<Object> shutdownQuery = new Query<Object>() { Query<Object> shutdownQuery = new Query<Object>() {
@ -409,10 +409,10 @@ public class AsyncSumDataViewer implements ILazyContentProvider
executor.execute(shutdownQuery); executor.execute(shutdownQuery);
try { try {
shutdownQuery.get(); shutdownQuery.get();
} catch (Exception e) {} } catch (Exception e) {}
// Shut down the display. // Shut down the display.
font.dispose(); font.dispose();
display.dispose(); display.dispose();
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -30,7 +30,7 @@ import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Status;
/** /**
* A wrapper class for the {@link IDataGenerator} interface, which returns * A wrapper class for the {@link IDataGenerator} interface, which returns
* ACPM cache objects to use for data retrieval instead of calling * ACPM cache objects to use for data retrieval instead of calling
* {@link IDataGenerator} asynchronous methods directly. * {@link IDataGenerator} asynchronous methods directly.
*/ */
@ -38,23 +38,23 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
/** Cache class for retrieving the data generator's count. */ /** Cache class for retrieving the data generator's count. */
private class CountCache extends RequestCache<Integer> { private class CountCache extends RequestCache<Integer> {
public CountCache() { public CountCache() {
super(fExecutor); super(fExecutor);
} }
@Override @Override
protected void retrieve(DataRequestMonitor<Integer> rm) { protected void retrieve(DataRequestMonitor<Integer> rm) {
fDataGenerator.getCount(rm); fDataGenerator.getCount(rm);
} }
/** /**
* Reset the cache when the count is changed. * Reset the cache when the count is changed.
*/ */
public void countChanged() { public void countChanged() {
// Make sure that if clients are currently waiting for a count, // Make sure that if clients are currently waiting for a count,
// they are notified of the update (their request monitors will be // they are notified of the update (their request monitors will be
// completed with an error). They shoudl then re-request data // completed with an error). They shoudl then re-request data
// from provider again. // from provider again.
setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Count changed")); setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Count changed"));
} }
@ -63,17 +63,17 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
/** Cache class for retrieving the data generator's values. */ /** Cache class for retrieving the data generator's values. */
private class ValueCache extends RequestCache<Integer> { private class ValueCache extends RequestCache<Integer> {
private int fIndex; private int fIndex;
public ValueCache(int index) { public ValueCache(int index) {
super(fExecutor); super(fExecutor);
fIndex = index; fIndex = index;
} }
@Override @Override
protected void retrieve(org.eclipse.cdt.dsf.concurrent.DataRequestMonitor<Integer> rm) { protected void retrieve(org.eclipse.cdt.dsf.concurrent.DataRequestMonitor<Integer> rm) {
fDataGenerator.getValue(fIndex, rm); fDataGenerator.getValue(fIndex, rm);
}; };
/** /**
* @see CountCache#countChanged() * @see CountCache#countChanged()
*/ */
@ -83,26 +83,26 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
} }
/** /**
* Executor used to synchronize data access in this cache manager. * Executor used to synchronize data access in this cache manager.
* It has to be the same executor that is used by the data generators in * It has to be the same executor that is used by the data generators in
* order to guarantee data consistency. * order to guarantee data consistency.
*/ */
private ImmediateInDsfExecutor fExecutor; private ImmediateInDsfExecutor fExecutor;
/** /**
* Data generator that this cache manager is a wrapper for. * Data generator that this cache manager is a wrapper for.
*/ */
private IDataGenerator fDataGenerator; private IDataGenerator fDataGenerator;
/** Cache for data generator's count */ /** Cache for data generator's count */
private CountCache fCountCache; private CountCache fCountCache;
/** /**
* Map of caches for retrieving values. Each value index has a separate * Map of caches for retrieving values. Each value index has a separate
* cache value object. * cache value object.
*/ */
private Map<Integer, ValueCache> fValueCaches = new HashMap<Integer, ValueCache>(); private Map<Integer, ValueCache> fValueCaches = new HashMap<Integer, ValueCache>();
public DataGeneratorCacheManager(ImmediateInDsfExecutor executor, IDataGenerator dataGenerator) { public DataGeneratorCacheManager(ImmediateInDsfExecutor executor, IDataGenerator dataGenerator) {
fExecutor = executor; fExecutor = executor;
fDataGenerator = dataGenerator; fDataGenerator = dataGenerator;
@ -112,14 +112,14 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
public void dispose() { public void dispose() {
fDataGenerator.removeListener(this); fDataGenerator.removeListener(this);
} }
/** /**
* Returns the data generator that this cache manager wraps. * Returns the data generator that this cache manager wraps.
*/ */
public IDataGenerator getDataGenerator() { public IDataGenerator getDataGenerator() {
return fDataGenerator; return fDataGenerator;
} }
/** /**
* Returns the cache for data generator count. * Returns the cache for data generator count.
*/ */
@ -132,7 +132,7 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
/** /**
* Returns the cache for a value at given index. * Returns the cache for a value at given index.
* *
* @param index Index of value to return. * @param index Index of value to return.
* @return Cache object for given value. * @return Cache object for given value.
*/ */
@ -142,10 +142,10 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
value = new ValueCache(index); value = new ValueCache(index);
fValueCaches.put(index, value); fValueCaches.put(index, value);
} }
return value; return value;
} }
@Override @Override
public void countChanged() { public void countChanged() {
// Reset the count cache and all the value caches. // Reset the count cache and all the value caches.
@ -156,7 +156,7 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
value.valueChanged(); value.valueChanged();
} }
} }
@Override @Override
public void valuesChanged(Set<Integer> indexes) { public void valuesChanged(Set<Integer> indexes) {
// Reset selected value caches. // Reset selected value caches.

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -53,7 +53,7 @@ import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
* </p> * </p>
*/ */
//#ifdef exercises //#ifdef exercises
//TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) //TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
//indicating allowed thread access to this class/method/member //indicating allowed thread access to this class/method/member
//#else //#else
//#@ThreadSafe //#@ThreadSafe
@ -70,10 +70,10 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
//#endif //#endif
abstract class Request { abstract class Request {
final RequestMonitor fRequestMonitor; final RequestMonitor fRequestMonitor;
Request(RequestMonitor rm) { Request(RequestMonitor rm) {
fRequestMonitor = rm; fRequestMonitor = rm;
rm.addCancelListener(new RequestMonitor.ICanceledListener() { rm.addCancelListener(new RequestMonitor.ICanceledListener() {
@Override @Override
public void requestCanceled(RequestMonitor rm) { public void requestCanceled(RequestMonitor rm) {
@ -87,49 +87,49 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
}); });
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @Immutable //# @Immutable
//#endif //#endif
class CountRequest extends Request { class CountRequest extends Request {
CountRequest(DataRequestMonitor<Integer> rm) { CountRequest(DataRequestMonitor<Integer> rm) {
super(rm); super(rm);
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @Immutable //# @Immutable
//#endif //#endif
class ItemRequest extends Request { class ItemRequest extends Request {
final int fIndex; final int fIndex;
ItemRequest(int index, DataRequestMonitor<Integer> rm) { ItemRequest(int index, DataRequestMonitor<Integer> rm) {
super(rm); super(rm);
fIndex = index; fIndex = index;
} }
} }
// The executor used to access all internal data of the generator. // The executor used to access all internal data of the generator.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
// Hint: If a member does not have an annotation, the programmer can assume // Hint: If a member does not have an annotation, the programmer can assume
// that the concurrency rule that applies to the class also applies to this // that the concurrency rule that applies to the class also applies to this
// member. // member.
//#endif //#endif
private DsfExecutor fExecutor; private DsfExecutor fExecutor;
// Main request queue of the data generator. The getValue(), getCount(), // Main request queue of the data generator. The getValue(), getCount(),
// and shutdown() methods write into the queue, while the serviceQueue() // and shutdown() methods write into the queue, while the serviceQueue()
// method reads from it. // method reads from it.
// The executor used to access all internal data of the generator. // The executor used to access all internal data of the generator.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
@ -139,7 +139,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
// List of listeners is not synchronized, it also has to be accessed // List of listeners is not synchronized, it also has to be accessed
// using the executor. // using the executor.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
@ -148,38 +148,38 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
// Current number of elements in this generator. // Current number of elements in this generator.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private int fCount = MIN_COUNT; private int fCount = MIN_COUNT;
// Counter used to determine when to reset the element count. // Counter used to determine when to reset the element count.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private int fCountResetTrigger = 0; private int fCountResetTrigger = 0;
// Elements which were modified since the last reset. // Elements which were modified since the last reset.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private Map<Integer, Integer> fChangedValues = private Map<Integer, Integer> fChangedValues =
new HashMap<Integer, Integer>(); new HashMap<Integer, Integer>();
public DataGeneratorWithExecutor() { public DataGeneratorWithExecutor() {
// Create the executor // Create the executor
this(new DefaultDsfExecutor("Supplier Executor")); this(new DefaultDsfExecutor("Supplier Executor"));
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
public DataGeneratorWithExecutor(DsfExecutor executor) { public DataGeneratorWithExecutor(DsfExecutor executor) {
@ -194,13 +194,13 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
randomChanges(); randomChanges();
} }
}, },
rand.nextInt(RANDOM_CHANGE_INTERVAL), rand.nextInt(RANDOM_CHANGE_INTERVAL),
RANDOM_CHANGE_INTERVAL, //Add a 10% variance to the interval. RANDOM_CHANGE_INTERVAL, //Add a 10% variance to the interval.
TimeUnit.MILLISECONDS); TimeUnit.MILLISECONDS);
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
@Override @Override
@ -212,26 +212,26 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
// Empty the queue of requests and fail them. // Empty the queue of requests and fail them.
for (Request request : fQueue) { for (Request request : fQueue) {
request.fRequestMonitor.setStatus(new Status( request.fRequestMonitor.setStatus(new Status(
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
request.fRequestMonitor.done(); request.fRequestMonitor.done();
} }
fQueue.clear(); fQueue.clear();
// Kill executor. // Kill executor.
fExecutor.shutdown(); fExecutor.shutdown();
rm.done(); rm.done();
} }
}); });
} catch (RejectedExecutionException e) { } catch (RejectedExecutionException e) {
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
@Override @Override
@ -246,18 +246,18 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
}); });
} catch (RejectedExecutionException e) { } catch (RejectedExecutionException e) {
rm.setStatus(new Status( rm.setStatus(new Status(
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
@Override @Override
public void getValue(final int index, final DataRequestMonitor<Integer> rm) { public void getValue(final int index, final DataRequestMonitor<Integer> rm) {
try { try {
fExecutor.execute( new DsfRunnable() { fExecutor.execute( new DsfRunnable() {
@Override @Override
@ -267,14 +267,14 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
} }
}); });
} catch (RejectedExecutionException e) { } catch (RejectedExecutionException e) {
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
@Override @Override
@ -290,7 +290,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#endif //#endif
@Override @Override
@ -307,7 +307,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
// Main processing function of this generator. // Main processing function of this generator.
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
@ -319,8 +319,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
public void run() { public void run() {
doServiceQueue(); doServiceQueue();
} }
}, },
PROCESSING_DELAY, TimeUnit.MILLISECONDS); PROCESSING_DELAY, TimeUnit.MILLISECONDS);
} }
//#ifdef exercises //#ifdef exercises
@ -332,9 +332,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
private void doServiceQueue() { private void doServiceQueue() {
//#ifdef exercises //#ifdef exercises
// TODO Exercise 3 - Add logic to discard cancelled requests from queue. // TODO Exercise 3 - Add logic to discard cancelled requests from queue.
// Hint: Since serviceQueue() is called using the executor, and the // Hint: Since serviceQueue() is called using the executor, and the
// fQueue list can only be modified when running in the executor // fQueue list can only be modified when running in the executor
// thread. This method can safely iterate and modify fQueue without // thread. This method can safely iterate and modify fQueue without
// risk of race conditions or concurrent modification exceptions. // risk of race conditions or concurrent modification exceptions.
//#else //#else
//# for (Iterator<Request> requestItr = fQueue.iterator(); requestItr.hasNext();) { //# for (Iterator<Request> requestItr = fQueue.iterator(); requestItr.hasNext();) {
@ -347,9 +347,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
//# } //# }
//# } //# }
//#endif //#endif
while (fQueue.size() != 0) { while (fQueue.size() != 0) {
// If there are requests to service, remove one from the queue and // If there are requests to service, remove one from the queue and
// schedule a runnable to process the request after a processing // schedule a runnable to process the request after a processing
// delay. // delay.
Request request = fQueue.remove(0); Request request = fQueue.remove(0);
@ -357,55 +357,55 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
processCountRequest((CountRequest)request); processCountRequest((CountRequest)request);
} else if (request instanceof ItemRequest) { } else if (request instanceof ItemRequest) {
processItemRequest((ItemRequest)request); processItemRequest((ItemRequest)request);
} }
} }
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private void processCountRequest(CountRequest request) { private void processCountRequest(CountRequest request) {
@SuppressWarnings("unchecked") // Suppress warning about lost type info. @SuppressWarnings("unchecked") // Suppress warning about lost type info.
DataRequestMonitor<Integer> rm = DataRequestMonitor<Integer> rm =
(DataRequestMonitor<Integer>)request.fRequestMonitor; (DataRequestMonitor<Integer>)request.fRequestMonitor;
rm.setData(fCount); rm.setData(fCount);
rm.done(); rm.done();
} }
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private void processItemRequest(ItemRequest request) { private void processItemRequest(ItemRequest request) {
@SuppressWarnings("unchecked") // Suppress warning about lost type info. @SuppressWarnings("unchecked") // Suppress warning about lost type info.
DataRequestMonitor<Integer> rm = DataRequestMonitor<Integer> rm =
(DataRequestMonitor<Integer>)request.fRequestMonitor; (DataRequestMonitor<Integer>)request.fRequestMonitor;
if (fChangedValues.containsKey(request.fIndex)) { if (fChangedValues.containsKey(request.fIndex)) {
rm.setData(fChangedValues.get(request.fIndex)); rm.setData(fChangedValues.get(request.fIndex));
} else { } else {
rm.setData(request.fIndex); rm.setData(request.fIndex);
} }
rm.done(); rm.done();
} }
/** /**
* This method simulates changes in the supplier's data set. * This method simulates changes in the supplier's data set.
*/ */
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
//#endif //#endif
private void randomChanges() { private void randomChanges() {
// Once every number of changes, reset the count, the rest of the // Once every number of changes, reset the count, the rest of the
// times just change certain values. // times just change certain values.
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0){ if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0){
randomCountReset(); randomCountReset();
@ -413,12 +413,12 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
randomDataChange(); randomDataChange();
} }
} }
/** /**
* Calculates new size for provider's data set. * Calculates new size for provider's data set.
*/ */
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
@ -430,18 +430,18 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
// Reset the changed values. // Reset the changed values.
fChangedValues.clear(); fChangedValues.clear();
// Notify listeners // Notify listeners
for (Listener listener : fListeners) { for (Listener listener : fListeners) {
listener.countChanged(); listener.countChanged();
} }
} }
/** /**
* Invalidates a random range of indexes. * Invalidates a random range of indexes.
*/ */
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//# @ConfinedToDsfExecutor("fExecutor") //# @ConfinedToDsfExecutor("fExecutor")
@ -454,15 +454,15 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
int randomIndex = random.nextInt(fCount); int randomIndex = random.nextInt(fCount);
int randomValue = random.nextInt(fCount); int randomValue = random.nextInt(fCount);
changed.put(randomIndex, randomValue); changed.put(randomIndex, randomValue);
} }
// Add the indexes to an overall set of changed indexes. // Add the indexes to an overall set of changed indexes.
fChangedValues.putAll(changed); fChangedValues.putAll(changed);
// Notify listeners // Notify listeners
for (Object listener : fListeners) { for (Object listener : fListeners) {
((Listener)listener).valuesChanged(changed.keySet()); ((Listener)listener).valuesChanged(changed.keySet());
} }
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -36,78 +36,78 @@ import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
/** /**
* Thread-based implementation of the data generator. * Thread-based implementation of the data generator.
* <p> * <p>
* This generator is based around a queue of client requests and a thread which * This generator is based around a queue of client requests and a thread which
* reads the requests from the queue and processes them. The distinguishing * reads the requests from the queue and processes them. The distinguishing
* feature of this generator is that it uses a a blocking queue as the main * feature of this generator is that it uses a a blocking queue as the main
* synchronization object. However, fListeners, fShutdown, and fChangedIndexes * synchronization object. However, fListeners, fShutdown, and fChangedIndexes
* fields also need to be thread-safe and so they implement their own * fields also need to be thread-safe and so they implement their own
* synchronization. * synchronization.
* </p> * </p>
*/ */
public class DataGeneratorWithThread extends Thread public class DataGeneratorWithThread extends Thread
implements IDataGenerator implements IDataGenerator
{ {
// Request objects are used to serialize the interface calls into objects // Request objects are used to serialize the interface calls into objects
// which can then be pushed into a queue. // which can then be pushed into a queue.
abstract class Request { abstract class Request {
final RequestMonitor fRequestMonitor; final RequestMonitor fRequestMonitor;
Request(RequestMonitor rm) { Request(RequestMonitor rm) {
fRequestMonitor = rm; fRequestMonitor = rm;
} }
} }
class CountRequest extends Request { class CountRequest extends Request {
CountRequest(DataRequestMonitor<Integer> rm) { CountRequest(DataRequestMonitor<Integer> rm) {
super(rm);
}
}
class ItemRequest extends Request {
final int fIndex;
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
super(rm);
fIndex = index;
}
}
class ShutdownRequest extends Request {
ShutdownRequest(RequestMonitor rm) {
super(rm); super(rm);
} }
} }
// Main request queue of the data generator. The getValue(), getCount(), class ItemRequest extends Request {
// and shutdown() methods write into the queue, while the run() method final int fIndex;
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
super(rm);
fIndex = index;
}
}
class ShutdownRequest extends Request {
ShutdownRequest(RequestMonitor rm) {
super(rm);
}
}
// Main request queue of the data generator. The getValue(), getCount(),
// and shutdown() methods write into the queue, while the run() method
// reads from it. // reads from it.
private final BlockingQueue<Request> fQueue = private final BlockingQueue<Request> fQueue =
new LinkedBlockingQueue<Request>(); new LinkedBlockingQueue<Request>();
// ListenerList class provides thread safety. // ListenerList class provides thread safety.
private ListenerList<Listener> fListeners = new ListenerList<>(); private ListenerList<Listener> fListeners = new ListenerList<>();
// Current number of elements in this generator. // Current number of elements in this generator.
private int fCount = MIN_COUNT; private int fCount = MIN_COUNT;
// Counter used to determine when to reset the element count. // Counter used to determine when to reset the element count.
private int fCountResetTrigger = 0; private int fCountResetTrigger = 0;
// Elements which were modified since the last reset. // Elements which were modified since the last reset.
private Map<Integer, Integer> fChangedValues = private Map<Integer, Integer> fChangedValues =
Collections.synchronizedMap(new HashMap<Integer, Integer>()); Collections.synchronizedMap(new HashMap<Integer, Integer>());
// Used to determine when to make changes in data. // Used to determine when to make changes in data.
private long fLastChangeTime = System.currentTimeMillis(); private long fLastChangeTime = System.currentTimeMillis();
// Flag indicating when the generator has been shut down. // Flag indicating when the generator has been shut down.
private AtomicBoolean fShutdown = new AtomicBoolean(false); private AtomicBoolean fShutdown = new AtomicBoolean(false);
public DataGeneratorWithThread() { public DataGeneratorWithThread() {
// Immediately kick off the request processing thread. // Immediately kick off the request processing thread.
start(); start();
} }
@Override @Override
public void shutdown(RequestMonitor rm) { public void shutdown(RequestMonitor rm) {
// Mark the generator as shut down. After the fShutdown flag is set, // Mark the generator as shut down. After the fShutdown flag is set,
@ -115,11 +115,11 @@ public class DataGeneratorWithThread extends Thread
if (!fShutdown.getAndSet(true)) { if (!fShutdown.getAndSet(true)) {
fQueue.add(new ShutdownRequest(rm)); fQueue.add(new ShutdownRequest(rm));
} else { } else {
// //
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
@Override @Override
@ -127,22 +127,22 @@ public class DataGeneratorWithThread extends Thread
if (!fShutdown.get()) { if (!fShutdown.get()) {
fQueue.add(new CountRequest(rm)); fQueue.add(new CountRequest(rm));
} else { } else {
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
@Override @Override
public void getValue(int index, DataRequestMonitor<Integer> rm) { public void getValue(int index, DataRequestMonitor<Integer> rm) {
if (!fShutdown.get()) { if (!fShutdown.get()) {
fQueue.add(new ItemRequest(index, rm)); fQueue.add(new ItemRequest(index, rm));
} else { } else {
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
"Supplier shut down")); "Supplier shut down"));
rm.done(); rm.done();
} }
} }
@Override @Override
public void addListener(Listener listener) { public void addListener(Listener listener) {
@ -153,25 +153,25 @@ public class DataGeneratorWithThread extends Thread
public void removeListener(Listener listener) { public void removeListener(Listener listener) {
fListeners.remove(listener); fListeners.remove(listener);
} }
@Override @Override
public void run() { public void run() {
try { try {
while(true) { while(true) {
// Get the next request from the queue. The time-out // Get the next request from the queue. The time-out
// ensures that that the random changes get processed. // ensures that that the random changes get processed.
final Request request = fQueue.poll(100, TimeUnit.MILLISECONDS); final Request request = fQueue.poll(100, TimeUnit.MILLISECONDS);
// If a request was dequeued, process it. // If a request was dequeued, process it.
if (request != null) { if (request != null) {
// Simulate a processing delay. // Simulate a processing delay.
if (request instanceof CountRequest) { if (request instanceof CountRequest) {
processCountRequest((CountRequest)request); processCountRequest((CountRequest)request);
} else if (request instanceof ItemRequest) { } else if (request instanceof ItemRequest) {
processItemRequest((ItemRequest)request); processItemRequest((ItemRequest)request);
} else if (request instanceof ShutdownRequest) { } else if (request instanceof ShutdownRequest) {
// If shutting down, just break out of the while(true) // If shutting down, just break out of the while(true)
// loop and thread will exit. // loop and thread will exit.
request.fRequestMonitor.done(); request.fRequestMonitor.done();
break; break;
@ -179,27 +179,27 @@ public class DataGeneratorWithThread extends Thread
} else { } else {
Thread.sleep(PROCESSING_DELAY); Thread.sleep(PROCESSING_DELAY);
} }
// Simulate data changes. // Simulate data changes.
randomChanges(); randomChanges();
} }
} }
catch (InterruptedException x) {} catch (InterruptedException x) {}
} }
private void processCountRequest(CountRequest request) { private void processCountRequest(CountRequest request) {
@SuppressWarnings("unchecked") // Suppress warning about lost type info. @SuppressWarnings("unchecked") // Suppress warning about lost type info.
DataRequestMonitor<Integer> rm = DataRequestMonitor<Integer> rm =
(DataRequestMonitor<Integer>)request.fRequestMonitor; (DataRequestMonitor<Integer>)request.fRequestMonitor;
rm.setData(fCount); rm.setData(fCount);
rm.done(); rm.done();
} }
private void processItemRequest(ItemRequest request) { private void processItemRequest(ItemRequest request) {
@SuppressWarnings("unchecked") // Suppress warning about lost type info. @SuppressWarnings("unchecked") // Suppress warning about lost type info.
DataRequestMonitor<Integer> rm = DataRequestMonitor<Integer> rm =
(DataRequestMonitor<Integer>)request.fRequestMonitor; (DataRequestMonitor<Integer>)request.fRequestMonitor;
if (fChangedValues.containsKey(request.fIndex)) { if (fChangedValues.containsKey(request.fIndex)) {
rm.setData(fChangedValues.get(request.fIndex)); rm.setData(fChangedValues.get(request.fIndex));
@ -207,17 +207,17 @@ public class DataGeneratorWithThread extends Thread
rm.setData(request.fIndex); rm.setData(request.fIndex);
} }
rm.done(); rm.done();
} }
private void randomChanges() { private void randomChanges() {
// Check if enough time is elapsed. // Check if enough time is elapsed.
if (System.currentTimeMillis() > if (System.currentTimeMillis() >
fLastChangeTime + RANDOM_CHANGE_INTERVAL) fLastChangeTime + RANDOM_CHANGE_INTERVAL)
{ {
fLastChangeTime = System.currentTimeMillis(); fLastChangeTime = System.currentTimeMillis();
// Once every number of changes, reset the count, the rest of the // Once every number of changes, reset the count, the rest of the
// times just change certain values. // times just change certain values.
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0) { if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0) {
randomCountReset(); randomCountReset();
@ -226,7 +226,7 @@ public class DataGeneratorWithThread extends Thread
} }
} }
} }
private void randomCountReset() { private void randomCountReset() {
// Calculate the new count. // Calculate the new count.
Random random = new java.util.Random(); Random random = new java.util.Random();
@ -234,13 +234,13 @@ public class DataGeneratorWithThread extends Thread
// Reset the changed values. // Reset the changed values.
fChangedValues.clear(); fChangedValues.clear();
// Notify listeners // Notify listeners
for (Object listener : fListeners.getListeners()) { for (Object listener : fListeners.getListeners()) {
((Listener)listener).countChanged(); ((Listener)listener).countChanged();
} }
} }
private void randomDataChange() { private void randomDataChange() {
// Calculate the indexes to change. // Calculate the indexes to change.
Random random = new java.util.Random(); Random random = new java.util.Random();
@ -249,16 +249,16 @@ public class DataGeneratorWithThread extends Thread
int randomIndex = random.nextInt(fCount); int randomIndex = random.nextInt(fCount);
int randomValue = random.nextInt(fCount); int randomValue = random.nextInt(fCount);
changed.put(randomIndex, randomValue); changed.put(randomIndex, randomValue);
} }
// Add the indexes to an overall set of changed indexes. // Add the indexes to an overall set of changed indexes.
fChangedValues.putAll(changed); fChangedValues.putAll(changed);
// Notify listeners // Notify listeners
for (Object listener : fListeners.getListeners()) { for (Object listener : fListeners.getListeners()) {
((Listener)listener).valuesChanged(changed.keySet()); ((Listener)listener).valuesChanged(changed.keySet());
} }
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -26,14 +26,14 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
//#endif //#endif
/** /**
* Data generator is simple source of data used to populate the example table * Data generator is simple source of data used to populate the example table
* view. It contains two asynchronous methods for retrieving the data * view. It contains two asynchronous methods for retrieving the data
* parameters: the count and the value for a given index. It also allows the * parameters: the count and the value for a given index. It also allows the
* view to receive events indicating when the data supplied by the generator * view to receive events indicating when the data supplied by the generator
* is changed. * is changed.
*/ */
//#ifdef exercises //#ifdef exercises
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor) // TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
// indicating allowed thread access to this class/method/member // indicating allowed thread access to this class/method/member
//#else //#else
//#@ThreadSafe //#@ThreadSafe
@ -42,7 +42,7 @@ public interface IDataGenerator {
// Constants which control the data generator behavior. // Constants which control the data generator behavior.
// Changing the count range can stress the scalability of the system, while // Changing the count range can stress the scalability of the system, while
// changing of the process delay and random change interval can stress // changing of the process delay and random change interval can stress
// its performance. // its performance.
final static int MIN_COUNT = 50; final static int MIN_COUNT = 50;
final static int MAX_COUNT = 100; final static int MAX_COUNT = 100;
@ -51,7 +51,7 @@ public interface IDataGenerator {
final static int RANDOM_COUNT_CHANGE_INTERVALS = 5; final static int RANDOM_COUNT_CHANGE_INTERVALS = 5;
final static int RANDOM_CHANGE_SET_PERCENTAGE = 10; final static int RANDOM_CHANGE_SET_PERCENTAGE = 10;
// Listener interface that the view needs to implement to react // Listener interface that the view needs to implement to react
// to the changes in data. // to the changes in data.
public interface Listener { public interface Listener {
@ -61,10 +61,10 @@ public interface IDataGenerator {
// Data access methods. // Data access methods.
void getCount(DataRequestMonitor<Integer> rm); void getCount(DataRequestMonitor<Integer> rm);
void getValue(int index, DataRequestMonitor<Integer> rm); void getValue(int index, DataRequestMonitor<Integer> rm);
// Method used to shutdown the data generator including any threads that // Method used to shutdown the data generator including any threads that
// it may use. // it may use.
void shutdown(RequestMonitor rm); void shutdown(RequestMonitor rm);
// Methods for registering change listeners. // Methods for registering change listeners.

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -38,67 +38,67 @@ import org.eclipse.swt.widgets.Shell;
/** /**
* Data viewer based on a table, which reads data using synchronous methods. * Data viewer based on a table, which reads data using synchronous methods.
* <p> * <p>
* This viewer implements the {@link IStructuredContentProvider} interface * This viewer implements the {@link IStructuredContentProvider} interface
* which is used by the JFace TableViewer class to populate a Table. This * which is used by the JFace TableViewer class to populate a Table. This
* interface contains one principal methods for reading data {@link #getElements(Object)}, * interface contains one principal methods for reading data {@link #getElements(Object)},
* which synchronously returns an array of elements. In order to implement * which synchronously returns an array of elements. In order to implement
* this method using the asynchronous data generator, this provider uses the * this method using the asynchronous data generator, this provider uses the
* {@link Query} object. * {@link Query} object.
* </p> * </p>
*/ */
public class SyncDataViewer public class SyncDataViewer
implements IStructuredContentProvider, IDataGenerator.Listener implements IStructuredContentProvider, IDataGenerator.Listener
{ {
// The viewer and generator that this content provider using. // The viewer and generator that this content provider using.
final private TableViewer fViewer; final private TableViewer fViewer;
final private IDataGenerator fDataGenerator; final private IDataGenerator fDataGenerator;
public SyncDataViewer(TableViewer viewer, IDataGenerator generator) { public SyncDataViewer(TableViewer viewer, IDataGenerator generator) {
fViewer = viewer; fViewer = viewer;
fDataGenerator = generator; fDataGenerator = generator;
fDataGenerator.addListener(this); fDataGenerator.addListener(this);
} }
@Override @Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// Not used // Not used
} }
@Override @Override
public Object[] getElements(Object inputElement) { public Object[] getElements(Object inputElement) {
// Create the query object for reading data count. // Create the query object for reading data count.
Query<Integer> countQuery = new Query<Integer>() { Query<Integer> countQuery = new Query<Integer>() {
@Override @Override
protected void execute(DataRequestMonitor<Integer> rm) { protected void execute(DataRequestMonitor<Integer> rm) {
fDataGenerator.getCount(rm); fDataGenerator.getCount(rm);
} }
}; };
// Submit the query to be executed. A query implements a runnable // Submit the query to be executed. A query implements a runnable
// interface and it has to be executed in order to do its work. // interface and it has to be executed in order to do its work.
ImmediateExecutor.getInstance().execute(countQuery); ImmediateExecutor.getInstance().execute(countQuery);
int count = 0; int count = 0;
// Block until the query completes, which will happen when the request // Block until the query completes, which will happen when the request
// monitor of the execute() method is marked done. // monitor of the execute() method is marked done.
try { try {
count = countQuery.get(); count = countQuery.get();
} catch (Exception e) { } catch (Exception e) {
// InterruptedException and ExecutionException can be thrown here. // InterruptedException and ExecutionException can be thrown here.
// ExecutionException containing a CoreException will be thrown // ExecutionException containing a CoreException will be thrown
// if an error status is set to the Query's request monitor. // if an error status is set to the Query's request monitor.
return new Object[0]; return new Object[0];
} }
final int finalCount = count; final int finalCount = count;
Query<List<Integer>> valueQuery = new Query<List<Integer>>() { Query<List<Integer>> valueQuery = new Query<List<Integer>>() {
@Override @Override
protected void execute(final DataRequestMonitor<List<Integer>> rm) { protected void execute(final DataRequestMonitor<List<Integer>> rm) {
final Integer[] retVal = new Integer[finalCount]; final Integer[] retVal = new Integer[finalCount];
final CountingRequestMonitor crm = new CountingRequestMonitor( final CountingRequestMonitor crm = new CountingRequestMonitor(
ImmediateExecutor.getInstance(), rm) ImmediateExecutor.getInstance(), rm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -109,9 +109,9 @@ public class SyncDataViewer
for (int i = 0; i < finalCount; i++) { for (int i = 0; i < finalCount; i++) {
final int finalI = i; final int finalI = i;
fDataGenerator.getValue( fDataGenerator.getValue(
i, i,
new DataRequestMonitor<Integer>( new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm) ImmediateExecutor.getInstance(), crm)
{ {
@Override @Override
protected void handleSuccess() { protected void handleSuccess() {
@ -126,7 +126,7 @@ public class SyncDataViewer
ImmediateExecutor.getInstance().execute(valueQuery); ImmediateExecutor.getInstance().execute(valueQuery);
try { try {
return valueQuery.get().toArray(new Integer[0]); return valueQuery.get().toArray(new Integer[0]);
} catch (Exception e) { } catch (Exception e) {
} }
return new Object[0]; return new Object[0];
} }
@ -141,23 +141,23 @@ public class SyncDataViewer
// For any event from the generator, refresh the whole viewer. // For any event from the generator, refresh the whole viewer.
refreshViewer(); refreshViewer();
} }
@Override @Override
public void valuesChanged(Set<Integer> indexes) { public void valuesChanged(Set<Integer> indexes) {
// For any event from the generator, refresh the whole viewer. // For any event from the generator, refresh the whole viewer.
refreshViewer(); refreshViewer();
} }
private void refreshViewer() { private void refreshViewer() {
//#ifdef exercises //#ifdef exercises
// TODO Exercise 5 - Add a call to getElements() to force a deadlock. // TODO Exercise 5 - Add a call to getElements() to force a deadlock.
//#else //#else
//# getElements(null); //# getElements(null);
//#endif //#endif
// This method may be called on any thread, switch to the display // This method may be called on any thread, switch to the display
// thread before calling the viewer. // thread before calling the viewer.
Display display = fViewer.getControl().getDisplay(); Display display = fViewer.getControl().getDisplay();
display.asyncExec( new Runnable() { display.asyncExec( new Runnable() {
@Override @Override
public void run() { public void run() {
@ -167,7 +167,7 @@ public class SyncDataViewer
} }
}); });
} }
/** /**
* The entry point for the example. * The entry point for the example.
* @param args Program arguments. * @param args Program arguments.
@ -190,11 +190,11 @@ public class SyncDataViewer
// TODO Exercise 5 - Use the DataGeneratorWithExecutor() instead. // TODO Exercise 5 - Use the DataGeneratorWithExecutor() instead.
final IDataGenerator generator = new DataGeneratorWithThread(); final IDataGenerator generator = new DataGeneratorWithThread();
//#else //#else
//# final IDataGenerator generator = new DataGeneratorWithExecutor(); //# final IDataGenerator generator = new DataGeneratorWithExecutor();
//#endif //#endif
// Create the content provider which will populate the viewer. // Create the content provider which will populate the viewer.
SyncDataViewer contentProvider = SyncDataViewer contentProvider =
new SyncDataViewer(tableViewer, generator); new SyncDataViewer(tableViewer, generator);
tableViewer.setContentProvider(contentProvider); tableViewer.setContentProvider(contentProvider);
tableViewer.setInput(new Object()); tableViewer.setInput(new Object());
@ -206,7 +206,7 @@ public class SyncDataViewer
if (!display.readAndDispatch()) if (!display.readAndDispatch())
display.sleep(); display.sleep();
} }
// The IDataGenerator.shutdown() method is asynchronous, this requires // The IDataGenerator.shutdown() method is asynchronous, this requires
// using a query again in order to wait for its completion. // using a query again in order to wait for its completion.
Query<Object> shutdownQuery = new Query<Object>() { Query<Object> shutdownQuery = new Query<Object>() {
@ -219,10 +219,10 @@ public class SyncDataViewer
try { try {
shutdownQuery.get(); shutdownQuery.get();
} catch (Exception e) {} } catch (Exception e) {}
// Shut down the display. // Shut down the display.
font.dispose(); font.dispose();
display.dispose(); display.dispose();
} }
} }

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -23,14 +23,14 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
/** /**
* Example of using a DataRequestMonitor to retrieve a result from an * Example of using a DataRequestMonitor to retrieve a result from an
* asynchronous method. * asynchronous method.
*/ */
public class Async2Plus2 { public class Async2Plus2 {
public static void main(String[] args) { public static void main(String[] args) {
Executor executor = ImmediateExecutor.getInstance(); Executor executor = ImmediateExecutor.getInstance();
DataRequestMonitor<Integer> rm = DataRequestMonitor<Integer> rm =
new DataRequestMonitor<Integer>(executor, null) { new DataRequestMonitor<Integer>(executor, null) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -24,11 +24,11 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
/** /**
* "Hello world" example which uses an asynchronous method to print out * "Hello world" example which uses an asynchronous method to print out
* the result. * the result.
* <p> * <p>
* The main method uses an immediate executor, which executes runnables * The main method uses an immediate executor, which executes runnables
* as soon as they are submitted, in creating its request monitor. * as soon as they are submitted, in creating its request monitor.
* *
*/ */
public class AsyncHelloWorld { public class AsyncHelloWorld {
@ -42,10 +42,10 @@ public class AsyncHelloWorld {
System.out.println("Hello world"); System.out.println("Hello world");
//#ifdef exercises //#ifdef exercises
// TODO Exercise 1: - Call the second async. "Hello world 2" method. // TODO Exercise 1: - Call the second async. "Hello world 2" method.
// Hint: Calling an asynchronous method requires passing to it a // Hint: Calling an asynchronous method requires passing to it a
// request monitor. A new request monitor can be constructed with // request monitor. A new request monitor can be constructed with
// a parent RequestMonitor as an argument argument. The parent gets // a parent RequestMonitor as an argument argument. The parent gets
// completed automatically when the lower level request monitor is // completed automatically when the lower level request monitor is
// completed. // completed.
rm.done(); rm.done();
//#else //#else
@ -53,9 +53,9 @@ public class AsyncHelloWorld {
//# asyncHelloWorld2(rm2); //# asyncHelloWorld2(rm2);
//#endif //#endif
} }
//#ifdef exercises //#ifdef exercises
// TODO: Exercise 1 - Add a second async. "Hello world 2" method. // TODO: Exercise 1 - Add a second async. "Hello world 2" method.
//#else //#else
//# static void asyncHelloWorld2(RequestMonitor rm) { //# static void asyncHelloWorld2(RequestMonitor rm) {
//# System.out.println("Hello world 2"); //# System.out.println("Hello world 2");

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/ * https://www.eclipse.org/legal/epl-2.0/
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
* *
* Contributors: * Contributors:
* Wind River Systems - initial API and implementation * Wind River Systems - initial API and implementation
*******************************************************************************/ *******************************************************************************/
@ -28,8 +28,8 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
/** /**
* Example of using a CountingRequestMonitor to wait for multiple * Example of using a CountingRequestMonitor to wait for multiple
* asynchronous calls to complete. * asynchronous calls to complete.
*/ */
public class AsyncQuicksort { public class AsyncQuicksort {
@ -40,7 +40,7 @@ public class AsyncQuicksort {
System.out.println("To sort: " + Arrays.toString(array)); System.out.println("To sort: " + Arrays.toString(array));
asyncQuicksort( asyncQuicksort(
array, 0, array.length - 1, array, 0, array.length - 1,
new RequestMonitor(fgExecutor, null) { new RequestMonitor(fgExecutor, null) {
@Override @Override
protected void handleCompleted() { protected void handleCompleted() {
@ -49,8 +49,8 @@ public class AsyncQuicksort {
}); });
} }
static void asyncQuicksort(final int[] array, final int left, static void asyncQuicksort(final int[] array, final int left,
final int right, final RequestMonitor rm) final int right, final RequestMonitor rm)
{ {
if (right > left) { if (right > left) {
int pivot = left; int pivot = left;
@ -68,13 +68,13 @@ public class AsyncQuicksort {
countingRm.setDoneCount(2); countingRm.setDoneCount(2);
//#else //#else
//# asyncPartition( //# asyncPartition(
//# array, left, right, pivot, //# array, left, right, pivot,
//# new DataRequestMonitor<Integer>(fgExecutor, rm) { //# new DataRequestMonitor<Integer>(fgExecutor, rm) {
//# @Override //# @Override
//# protected void handleCompleted() { //# protected void handleCompleted() {
//# int newPivot = getData(); //# int newPivot = getData();
//# printArray(array, left, right, newPivot); //# printArray(array, left, right, newPivot);
//# //#
//# CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm); //# CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm);
//# asyncQuicksort(array, left, newPivot - 1, countingRm); //# asyncQuicksort(array, left, newPivot - 1, countingRm);
//# asyncQuicksort(array, newPivot + 1, right, countingRm); //# asyncQuicksort(array, newPivot + 1, right, countingRm);
@ -89,7 +89,7 @@ public class AsyncQuicksort {
//#ifdef exercises //#ifdef exercises
// TODO Exercise 2 - Convert partition to an asynchronous method. // TODO Exercise 2 - Convert partition to an asynchronous method.
// Hint: a DataRequestMonitor<Integer> should be used to carry the // Hint: a DataRequestMonitor<Integer> should be used to carry the
// return value to the caller. // return value to the caller.
static int partition(int[] array, int left, int right, int pivot) static int partition(int[] array, int left, int right, int pivot)
//#else //#else
@ -97,8 +97,8 @@ public class AsyncQuicksort {
//#endif //#endif
{ {
int pivotValue = array[pivot]; int pivotValue = array[pivot];
array[pivot] = array[right]; array[pivot] = array[right];
array[right] = pivotValue; array[right] = pivotValue;
int store = left; int store = left;
for (int i = left; i < right; i++) { for (int i = left; i < right; i++) {
if (array[i] <= pivotValue) { if (array[i] <= pivotValue) {
@ -112,7 +112,7 @@ public class AsyncQuicksort {
array[store] = pivotValue; array[store] = pivotValue;
//#ifdef exercises //#ifdef exercises
// TODO: Request Monitors Exercise 2 - Return the data to caller using // TODO: Request Monitors Exercise 2 - Return the data to caller using
// a request monitor. // a request monitor.
return store; return store;
//#else //#else

View file

@ -616,7 +616,7 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
if (location != null) { if (location != null) {
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager() String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager()
.performStringSubstitution(location); .performStringSubstitution(location);
if (!expandedLocation.isEmpty()) { if (!expandedLocation.isEmpty()) {
return new Path(expandedLocation); return new Path(expandedLocation);
} }

View file

@ -659,7 +659,7 @@ public class MemoryBrowser extends ViewPart
} }
label += ' ' + renderingType; label += ' ' + renderingType;
// Allow the memory block to customize the label. The platform's // Allow the memory block to customize the label. The platform's
// Memory view support this (it was done in the call to // Memory view support this (it was done in the call to