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:
parent
b4031b5a8b
commit
be35c7327d
20 changed files with 587 additions and 587 deletions
|
@ -80,7 +80,7 @@ public class GdbDisconnectCommand implements IDisconnectHandler {
|
|||
request.setEnabled(false);
|
||||
} else {
|
||||
request.setEnabled(getData());
|
||||
|
||||
|
||||
}
|
||||
request.done();
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -451,7 +451,7 @@ abstract public class AbstractVMProvider implements IVMProvider, IVMEventListene
|
|||
}
|
||||
}
|
||||
fNodesListCache = list.toArray(new IVMNode[list.size()]);
|
||||
|
||||
|
||||
return fNodesListCache;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ abstract public class ReflectionSequence extends Sequence {
|
|||
assert executeMethod != null;
|
||||
|
||||
fExecuteMethod = executeMethod;
|
||||
|
||||
|
||||
fRollbackMethod = rollbackMethod;
|
||||
}
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue