1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-21 21:52:10 +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);
} else {
request.setEnabled(getData());
}
request.done();
}

View file

@ -606,7 +606,7 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
IProcess[] launchProcesses = getGDBLaunch().getProcesses();
for (IProcess proc : launchProcesses) {
if (proc instanceof InferiorRuntimeProcess) {
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()]);
return fNodesListCache;
}

View file

@ -150,7 +150,7 @@ abstract public class ReflectionSequence extends Sequence {
assert executeMethod != null;
fExecuteMethod = executeMethod;
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
// the same time avoid adding extra dispatch cycles to command processing.
if (fSession.getExecutor().isInExecutorThread()) {
super.done();
} else {
fSession.getExecutor().execute(new DsfRunnable() {

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* 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;
/**
* A data generator which performs a sum computation on data retrieved from a
* number of other data generators. The data retrieval from other generators
* is performed in parallel and the result is calculated once all data is
* received.
* A data generator which performs a sum computation on data retrieved from a
* number of other data generators. The data retrieval from other generators
* is performed in parallel and the result is calculated once all data is
* received.
* <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.
* </p>
* </p>
*/
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;
@ -48,13 +48,13 @@ public class AsyncSumDataGenerator implements IDataGenerator {
*/
final private IDataGenerator[] fDataGenerators;
public AsyncSumDataGenerator(DsfExecutor executor,
IDataGenerator[] generators)
public AsyncSumDataGenerator(DsfExecutor executor,
IDataGenerator[] generators)
{
fExecutor = executor;
fDataGenerators = generators;
}
}
@Override
public void getCount(final DataRequestMonitor<Integer> rm) {
// Artificially delay the retrieval of the sum data to simulate
@ -64,10 +64,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
public void run() {
doGetCount(rm);
}
},
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
},
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
}
/**
* Performs the actual count retrieval and calculation.
* @param rm Request monitor to complete with data.
@ -75,10 +75,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
private void doGetCount(final DataRequestMonitor<Integer> rm) {
// Array to store counts retrieved asynchronously
final int[] counts = new int[fDataGenerators.length];
// Counting request monitor is called once all data is retrieved.
final CountingRequestMonitor crm =
new CountingRequestMonitor(fExecutor, rm)
new CountingRequestMonitor(fExecutor, rm)
{
@Override
protected void handleSuccess() {
@ -89,26 +89,26 @@ public class AsyncSumDataGenerator implements IDataGenerator {
rm.done();
};
};
// Each call to data generator fills in one value in array.
for (int i = 0; i < fDataGenerators.length; i++) {
final int finalI = i;
fDataGenerators[i].getCount(
fDataGenerators[i].getCount(
new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm)
ImmediateExecutor.getInstance(), crm)
{
@Override
protected void handleSuccess() {
counts[finalI] = getData();
crm.done();
}
});
}
});
}
crm.setDoneCount(fDataGenerators.length);
}
@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
// real processing time.
@ -117,10 +117,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
public void run() {
doGetValue(index, rm);
}
},
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
},
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
}
/**
* Performs the actual value retrieval and calculation.
* @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) {
// Array to store counts retrieved asynchronously
final int[] values = new int[fDataGenerators.length];
// Counting request monitor is called once all data is retrieved.
final CountingRequestMonitor crm =
new CountingRequestMonitor(fExecutor, rm)
final CountingRequestMonitor crm =
new CountingRequestMonitor(fExecutor, rm)
{
@Override
protected void handleSuccess() {
@ -144,22 +144,22 @@ public class AsyncSumDataGenerator implements IDataGenerator {
rm.done();
};
};
// Each call to data generator fills in one value in array.
for (int i = 0; i < fDataGenerators.length; i++) {
final int finalI = i;
fDataGenerators[i].getValue(
index,
index,
new DataRequestMonitor<Integer>(
ImmediateExecutor.getInstance(), crm)
ImmediateExecutor.getInstance(), crm)
{
@Override
protected void handleSuccess() {
values[finalI] = getData();
values[finalI] = getData();
crm.done();
}
});
}
});
}
crm.setDoneCount(fDataGenerators.length);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
@ -26,14 +26,14 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
//#endif
/**
* Data generator is simple source of data used to populate the example table
* view. It contains two asynchronous methods for retrieving the data
* 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
* is changed.
* Data generator is simple source of data used to populate the example table
* view. It contains two asynchronous methods for retrieving the data
* 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
* is changed.
*/
//#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
//#else
//#@ThreadSafe
@ -42,7 +42,7 @@ public interface IDataGenerator {
// Constants which control the data generator behavior.
// 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.
final static int MIN_COUNT = 50;
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_CHANGE_SET_PERCENTAGE = 10;
// Listener interface that the view needs to implement to react
// to the changes in data.
public interface Listener {
@ -61,10 +61,10 @@ public interface IDataGenerator {
// Data access methods.
void getCount(DataRequestMonitor<Integer> rm);
void getValue(int index, DataRequestMonitor<Integer> rm);
// Method used to shutdown the data generator including any threads that
// it may use.
void getValue(int index, DataRequestMonitor<Integer> rm);
// Method used to shutdown the data generator including any threads that
// it may use.
void shutdown(RequestMonitor rm);
// Methods for registering change listeners.

View file

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

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* 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;
/**
* Example of using a DataRequestMonitor to retrieve a result from an
* Example of using a DataRequestMonitor to retrieve a result from an
* asynchronous method.
*/
public class Async2Plus2 {
public static void main(String[] args) {
Executor executor = ImmediateExecutor.getInstance();
DataRequestMonitor<Integer> rm =
DataRequestMonitor<Integer> rm =
new DataRequestMonitor<Integer>(executor, null) {
@Override
protected void handleCompleted() {

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* 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
* the result.
* the result.
* <p>
* 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 {
@ -42,10 +42,10 @@ public class AsyncHelloWorld {
System.out.println("Hello world");
//#ifdef exercises
// TODO Exercise 1: - Call the second async. "Hello world 2" method.
// Hint: Calling an asynchronous method requires passing to it a
// request monitor. A new request monitor can be constructed with
// a parent RequestMonitor as an argument argument. The parent gets
// completed automatically when the lower level request monitor is
// Hint: Calling an asynchronous method requires passing to it a
// request monitor. A new request monitor can be constructed with
// a parent RequestMonitor as an argument argument. The parent gets
// completed automatically when the lower level request monitor is
// completed.
rm.done();
//#else
@ -53,9 +53,9 @@ public class AsyncHelloWorld {
//# asyncHelloWorld2(rm2);
//#endif
}
//#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
//# static void asyncHelloWorld2(RequestMonitor rm) {
//# System.out.println("Hello world 2");

View file

@ -7,7 +7,7 @@
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
*
* Contributors:
* 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;
/**
* Example of using a CountingRequestMonitor to wait for multiple
* asynchronous calls to complete.
* Example of using a CountingRequestMonitor to wait for multiple
* asynchronous calls to complete.
*/
public class AsyncQuicksort {
@ -40,7 +40,7 @@ public class AsyncQuicksort {
System.out.println("To sort: " + Arrays.toString(array));
asyncQuicksort(
array, 0, array.length - 1,
array, 0, array.length - 1,
new RequestMonitor(fgExecutor, null) {
@Override
protected void handleCompleted() {
@ -49,8 +49,8 @@ public class AsyncQuicksort {
});
}
static void asyncQuicksort(final int[] array, final int left,
final int right, final RequestMonitor rm)
static void asyncQuicksort(final int[] array, final int left,
final int right, final RequestMonitor rm)
{
if (right > left) {
int pivot = left;
@ -68,13 +68,13 @@ public class AsyncQuicksort {
countingRm.setDoneCount(2);
//#else
//# asyncPartition(
//# array, left, right, pivot,
//# array, left, right, pivot,
//# new DataRequestMonitor<Integer>(fgExecutor, rm) {
//# @Override
//# protected void handleCompleted() {
//# int newPivot = getData();
//# printArray(array, left, right, newPivot);
//#
//#
//# CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm);
//# asyncQuicksort(array, left, newPivot - 1, countingRm);
//# asyncQuicksort(array, newPivot + 1, right, countingRm);
@ -89,7 +89,7 @@ public class AsyncQuicksort {
//#ifdef exercises
// 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.
static int partition(int[] array, int left, int right, int pivot)
//#else
@ -97,8 +97,8 @@ public class AsyncQuicksort {
//#endif
{
int pivotValue = array[pivot];
array[pivot] = array[right];
array[right] = pivotValue;
array[pivot] = array[right];
array[right] = pivotValue;
int store = left;
for (int i = left; i < right; i++) {
if (array[i] <= pivotValue) {
@ -112,7 +112,7 @@ public class AsyncQuicksort {
array[store] = pivotValue;
//#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.
return store;
//#else

View file

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

View file

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