mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-22 06:02:11 +02:00
Bug 540373: Cleanup: Remove trailing whitespace in Java files
Some Java files were missed, or other cleanups introduced trailing whitespace. So clean it up with this commit. Command used: find . ! -path "./.git/*" -type f -name *.java -exec sed -i -E 's/[ \t]+$//' {} + Change-Id: I18f5e3a3eb5352443c9e753d427bb8d06107b8a4
This commit is contained in:
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);
|
request.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
request.setEnabled(getData());
|
request.setEnabled(getData());
|
||||||
|
|
||||||
}
|
}
|
||||||
request.done();
|
request.done();
|
||||||
}
|
}
|
||||||
|
|
|
@ -606,7 +606,7 @@ public class LaunchConfigurationAndRestartTest extends BaseParametrizedTestCase
|
||||||
shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
|
shutdownEventWaitor.waitForEvent(TestsPlugin.massageTimeout(1000));
|
||||||
|
|
||||||
IProcess[] launchProcesses = getGDBLaunch().getProcesses();
|
IProcess[] launchProcesses = getGDBLaunch().getProcesses();
|
||||||
|
|
||||||
for (IProcess proc : launchProcesses) {
|
for (IProcess proc : launchProcesses) {
|
||||||
if (proc instanceof InferiorRuntimeProcess) {
|
if (proc instanceof InferiorRuntimeProcess) {
|
||||||
assertThat(proc.getAttribute(IGdbDebugConstants.INFERIOR_EXITED_ATTR), is(notNullValue()));
|
assertThat(proc.getAttribute(IGdbDebugConstants.INFERIOR_EXITED_ATTR), is(notNullValue()));
|
||||||
|
|
|
@ -451,7 +451,7 @@ abstract public class AbstractVMProvider implements IVMProvider, IVMEventListene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fNodesListCache = list.toArray(new IVMNode[list.size()]);
|
fNodesListCache = list.toArray(new IVMNode[list.size()]);
|
||||||
|
|
||||||
return fNodesListCache;
|
return fNodesListCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ abstract public class ReflectionSequence extends Sequence {
|
||||||
assert executeMethod != null;
|
assert executeMethod != null;
|
||||||
|
|
||||||
fExecuteMethod = executeMethod;
|
fExecuteMethod = executeMethod;
|
||||||
|
|
||||||
fRollbackMethod = rollbackMethod;
|
fRollbackMethod = rollbackMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -422,7 +422,7 @@ public class CommandCache implements ICommandListener {
|
||||||
// protect against the cache being called in non-session thread, but at
|
// protect against the cache being called in non-session thread, but at
|
||||||
// the same time avoid adding extra dispatch cycles to command processing.
|
// the same time avoid adding extra dispatch cycles to command processing.
|
||||||
if (fSession.getExecutor().isInExecutorThread()) {
|
if (fSession.getExecutor().isInExecutorThread()) {
|
||||||
|
|
||||||
super.done();
|
super.done();
|
||||||
} else {
|
} else {
|
||||||
fSession.getExecutor().execute(new DsfRunnable() {
|
fSession.getExecutor().execute(new DsfRunnable() {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -34,55 +34,55 @@ import org.eclipse.cdt.dsf.concurrent.Transaction;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data generator which performs a sum computation on data retrieved from a
|
* A data generator which performs a sum computation on data retrieved from a
|
||||||
* number of other data generators. The data retrieval from other generators
|
* number of other data generators. The data retrieval from other generators
|
||||||
* is performed using ACPM caches and the result is calculated once all caches
|
* is performed using ACPM caches and the result is calculated once all caches
|
||||||
* are valid.
|
* are valid.
|
||||||
* <p>
|
* <p>
|
||||||
* Unlike {@link AsyncSumDataGenerator}, this data generator listens to events
|
* Unlike {@link AsyncSumDataGenerator}, this data generator listens to events
|
||||||
* from the individual the data providers. Theve events are used to
|
* from the individual the data providers. Theve events are used to
|
||||||
* invalidate caches to make sure that they don't return incorrect data. This
|
* invalidate caches to make sure that they don't return incorrect data. This
|
||||||
* generator also sends out events to its clients to notify them to update, or
|
* generator also sends out events to its clients to notify them to update, or
|
||||||
* invalidate their caches.
|
* invalidate their caches.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class ACPMSumDataGenerator
|
public class ACPMSumDataGenerator
|
||||||
implements IDataGenerator, IDataGenerator.Listener
|
implements IDataGenerator, IDataGenerator.Listener
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSF executor used to serialize data access within this data generator.
|
* DSF executor used to serialize data access within this data generator.
|
||||||
*/
|
*/
|
||||||
final private DsfExecutor fExecutor;
|
final private DsfExecutor fExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data generators to retrieve original data to perform calculations on.
|
* Data generators to retrieve original data to perform calculations on.
|
||||||
* The generators are accessed through the cache manager wrappers.
|
* The generators are accessed through the cache manager wrappers.
|
||||||
*/
|
*/
|
||||||
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of listeners for this data generator.
|
* List of listeners for this data generator.
|
||||||
*/
|
*/
|
||||||
final private List<Listener> fListeners = new LinkedList<Listener>();
|
final private List<Listener> fListeners = new LinkedList<Listener>();
|
||||||
|
|
||||||
public ACPMSumDataGenerator(DsfExecutor executor,
|
public ACPMSumDataGenerator(DsfExecutor executor,
|
||||||
IDataGenerator[] generators)
|
IDataGenerator[] generators)
|
||||||
{
|
{
|
||||||
fExecutor = executor;
|
fExecutor = executor;
|
||||||
|
|
||||||
// Create wrappers for data generators and add ourselves as listener
|
// Create wrappers for data generators and add ourselves as listener
|
||||||
// to their events.
|
// to their events.
|
||||||
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
||||||
ImmediateInDsfExecutor immediateExecutor =
|
ImmediateInDsfExecutor immediateExecutor =
|
||||||
new ImmediateInDsfExecutor(fExecutor);
|
new ImmediateInDsfExecutor(fExecutor);
|
||||||
for (int i = 0; i < generators.length; i++) {
|
for (int i = 0; i < generators.length; i++) {
|
||||||
fDataGeneratorCMs[i] = new DataGeneratorCacheManager(
|
fDataGeneratorCMs[i] = new DataGeneratorCacheManager(
|
||||||
immediateExecutor, generators[i]);
|
immediateExecutor, generators[i]);
|
||||||
generators[i].addListener(this);
|
generators[i].addListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getCount(final DataRequestMonitor<Integer> rm) {
|
public void getCount(final DataRequestMonitor<Integer> rm) {
|
||||||
// Artificially delay the retrieval of the sum data to simulate
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
|
@ -94,38 +94,38 @@ public class ACPMSumDataGenerator
|
||||||
// code in one place.
|
// code in one place.
|
||||||
new Transaction<Integer>() {
|
new Transaction<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
protected Integer process()
|
protected Integer process()
|
||||||
throws Transaction.InvalidCacheException,
|
throws Transaction.InvalidCacheException,
|
||||||
CoreException
|
CoreException
|
||||||
{
|
{
|
||||||
return processCount(this);
|
return processCount(this);
|
||||||
}
|
}
|
||||||
}.request(rm);
|
}.request(rm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the calculation to get the max count for the given transaction.
|
* Perform the calculation to get the max count for the given transaction.
|
||||||
* @param transaction The ACPM transaction to use for calculation.
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
* @return Calculated count.
|
* @return Calculated count.
|
||||||
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
* @throws CoreException See {@link Transaction#process}
|
* @throws CoreException See {@link Transaction#process}
|
||||||
*/
|
*/
|
||||||
private Integer processCount(Transaction<Integer> transaction)
|
private Integer processCount(Transaction<Integer> transaction)
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
// Assemble all needed count caches into a collection.
|
// Assemble all needed count caches into a collection.
|
||||||
List<ICache<Integer>> countCaches =
|
List<ICache<Integer>> countCaches =
|
||||||
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
countCaches.add(dataGeneratorCM.getCount());
|
countCaches.add(dataGeneratorCM.getCount());
|
||||||
}
|
}
|
||||||
// Validate all count caches at once. This executes needed requests
|
// Validate all count caches at once. This executes needed requests
|
||||||
// in parallel.
|
// in parallel.
|
||||||
transaction.validate(countCaches);
|
transaction.validate(countCaches);
|
||||||
|
|
||||||
// Calculate the max value and return.
|
// Calculate the max value and return.
|
||||||
int maxCount = 0;
|
int maxCount = 0;
|
||||||
for (ICache<Integer> countCache : countCaches) {
|
for (ICache<Integer> countCache : countCaches) {
|
||||||
|
@ -135,7 +135,7 @@ public class ACPMSumDataGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
||||||
{
|
{
|
||||||
// Add a processing delay.
|
// Add a processing delay.
|
||||||
fExecutor.schedule( new Runnable() {
|
fExecutor.schedule( new Runnable() {
|
||||||
|
@ -143,45 +143,45 @@ public class ACPMSumDataGenerator
|
||||||
public void run() {
|
public void run() {
|
||||||
new Transaction<Integer>() {
|
new Transaction<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
protected Integer process()
|
protected Integer process()
|
||||||
throws Transaction.InvalidCacheException,
|
throws Transaction.InvalidCacheException,
|
||||||
CoreException
|
CoreException
|
||||||
{
|
{
|
||||||
return processValue(this, index);
|
return processValue(this, index);
|
||||||
}
|
}
|
||||||
}.request(rm);
|
}.request(rm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the calculation to get the sum of values at given index.
|
* Perform the calculation to get the sum of values at given index.
|
||||||
* @param transaction The ACPM transaction to use for calculation.
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
* @param index Index of value to calculate.
|
* @param index Index of value to calculate.
|
||||||
* @return Calculated value.
|
* @return Calculated value.
|
||||||
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
* @throws CoreException See {@link Transaction#process}
|
* @throws CoreException See {@link Transaction#process}
|
||||||
*/
|
*/
|
||||||
private Integer processValue(Transaction<Integer> transaction, int index)
|
private Integer processValue(Transaction<Integer> transaction, int index)
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
List<ICache<Integer>> valueCaches =
|
List<ICache<Integer>> valueCaches =
|
||||||
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
valueCaches.add(dataGeneratorCM.getValue(index));
|
valueCaches.add(dataGeneratorCM.getValue(index));
|
||||||
}
|
}
|
||||||
// Validate all value caches at once. This executes needed requests
|
// Validate all value caches at once. This executes needed requests
|
||||||
// in parallel.
|
// in parallel.
|
||||||
transaction.validate(valueCaches);
|
transaction.validate(valueCaches);
|
||||||
|
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (ICache<Integer> valueCache : valueCaches) {
|
for (ICache<Integer> valueCache : valueCaches) {
|
||||||
sum += valueCache.getData();
|
sum += valueCache.getData();
|
||||||
}
|
}
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown(final RequestMonitor rm) {
|
public void shutdown(final RequestMonitor rm) {
|
||||||
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
|
@ -220,7 +220,7 @@ public class ACPMSumDataGenerator
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void countChanged() {
|
public void countChanged() {
|
||||||
// Must access fListeners on executor thread.
|
// Must access fListeners on executor thread.
|
||||||
try {
|
try {
|
||||||
fExecutor.execute( new DsfRunnable() {
|
fExecutor.execute( new DsfRunnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -232,7 +232,7 @@ public class ACPMSumDataGenerator
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {}
|
} catch (RejectedExecutionException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void valuesChanged(final Set<Integer> changed) {
|
public void valuesChanged(final Set<Integer> changed) {
|
||||||
// Must access fListeners on executor thread.
|
// Must access fListeners on executor thread.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -52,13 +52,13 @@ import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.swt.widgets.Table;
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data viewer based on a table, which reads data from multiple data
|
* Data viewer based on a table, which reads data from multiple data
|
||||||
* providers using ACPM methods and performs a computation on the
|
* providers using ACPM methods and performs a computation on the
|
||||||
* retrieved data.
|
* retrieved data.
|
||||||
* <p>
|
* <p>
|
||||||
* This example builds on the {@link AsyncSumDataViewer} example. It
|
* This example builds on the {@link AsyncSumDataViewer} example. It
|
||||||
* demonstrates using ACPM to solve the data consistency problem when
|
* demonstrates using ACPM to solve the data consistency problem when
|
||||||
* retrieving data from multiple sources asynchronously.
|
* retrieving data from multiple sources asynchronously.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@ConfinedToDsfExecutor("fDisplayExecutor")
|
@ConfinedToDsfExecutor("fDisplayExecutor")
|
||||||
|
@ -66,47 +66,47 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
{
|
{
|
||||||
/** View update frequency interval. */
|
/** View update frequency interval. */
|
||||||
final private static int UPDATE_INTERVAL = 10000;
|
final private static int UPDATE_INTERVAL = 10000;
|
||||||
|
|
||||||
/** Executor to use instead of Display.asyncExec(). **/
|
/** Executor to use instead of Display.asyncExec(). **/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
final private DsfExecutor fDisplayExecutor;
|
final private DsfExecutor fDisplayExecutor;
|
||||||
|
|
||||||
/** Executor to use when retrieving data from data providers */
|
/** Executor to use when retrieving data from data providers */
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
final private ImmediateInDsfExecutor fDataExecutor;
|
final private ImmediateInDsfExecutor fDataExecutor;
|
||||||
|
|
||||||
// The viewer and generator that this content provider using.
|
// The viewer and generator that this content provider using.
|
||||||
final private TableViewer fViewer;
|
final private TableViewer fViewer;
|
||||||
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
final private DataGeneratorCacheManager[] fDataGeneratorCMs;
|
||||||
final private DataGeneratorCacheManager fSumGeneratorCM;
|
final private DataGeneratorCacheManager fSumGeneratorCM;
|
||||||
|
|
||||||
// Fields used in request cancellation logic.
|
// Fields used in request cancellation logic.
|
||||||
private List<ValueRequestMonitor> fItemDataRequestMonitors =
|
private List<ValueRequestMonitor> fItemDataRequestMonitors =
|
||||||
new LinkedList<ValueRequestMonitor>();
|
new LinkedList<ValueRequestMonitor>();
|
||||||
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
private int fCancelCallsPending = 0;
|
private int fCancelCallsPending = 0;
|
||||||
private Future<?> fRefreshFuture;
|
private Future<?> fRefreshFuture;
|
||||||
|
|
||||||
public ACPMSumDataViewer(TableViewer viewer,
|
public ACPMSumDataViewer(TableViewer viewer,
|
||||||
ImmediateInDsfExecutor dataExecutor, IDataGenerator[] generators,
|
ImmediateInDsfExecutor dataExecutor, IDataGenerator[] generators,
|
||||||
IDataGenerator sumGenerator)
|
IDataGenerator sumGenerator)
|
||||||
{
|
{
|
||||||
fViewer = viewer;
|
fViewer = viewer;
|
||||||
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
fViewer.getTable().getDisplay());
|
fViewer.getTable().getDisplay());
|
||||||
fDataExecutor = dataExecutor;
|
fDataExecutor = dataExecutor;
|
||||||
|
|
||||||
// Create wrappers for data generators. Don't need to register as
|
// Create wrappers for data generators. Don't need to register as
|
||||||
// listeners to generator events because the cache managers ensure data
|
// listeners to generator events because the cache managers ensure data
|
||||||
// are already registered for them.
|
// are already registered for them.
|
||||||
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
fDataGeneratorCMs = new DataGeneratorCacheManager[generators.length];
|
||||||
for (int i = 0; i < generators.length; i++) {
|
for (int i = 0; i < generators.length; i++) {
|
||||||
fDataGeneratorCMs[i] =
|
fDataGeneratorCMs[i] =
|
||||||
new DataGeneratorCacheManager(fDataExecutor, generators[i]);
|
new DataGeneratorCacheManager(fDataExecutor, generators[i]);
|
||||||
}
|
}
|
||||||
fSumGeneratorCM =
|
fSumGeneratorCM =
|
||||||
new DataGeneratorCacheManager(fDataExecutor, sumGenerator);
|
new DataGeneratorCacheManager(fDataExecutor, sumGenerator);
|
||||||
|
|
||||||
// Schedule a task to refresh the viewer periodically.
|
// Schedule a task to refresh the viewer periodically.
|
||||||
fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate(
|
fRefreshFuture = fDisplayExecutor.scheduleAtFixedRate(
|
||||||
new Runnable() {
|
new Runnable() {
|
||||||
|
@ -114,25 +114,25 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
public void run() {
|
public void run() {
|
||||||
queryItemCount();
|
queryItemCount();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
// Cancel the periodic task of refreshing the view.
|
// Cancel the periodic task of refreshing the view.
|
||||||
fRefreshFuture.cancel(false);
|
fRefreshFuture.cancel(false);
|
||||||
|
|
||||||
// Need to dispose cache managers that were created in this class. This
|
// Need to dispose cache managers that were created in this class. This
|
||||||
// needs to be done on the cache manager's thread.
|
// needs to be done on the cache manager's thread.
|
||||||
Query<Object> disposeCacheManagersQuery = new Query<Object>() {
|
Query<Object> disposeCacheManagersQuery = new Query<Object>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(DataRequestMonitor<Object> rm) {
|
protected void execute(DataRequestMonitor<Object> rm) {
|
||||||
fSumGeneratorCM.dispose();
|
fSumGeneratorCM.dispose();
|
||||||
for (DataGeneratorCacheManager dataGeneratorCM :
|
for (DataGeneratorCacheManager dataGeneratorCM :
|
||||||
fDataGeneratorCMs)
|
fDataGeneratorCMs)
|
||||||
{
|
{
|
||||||
dataGeneratorCM.dispose();
|
dataGeneratorCM.dispose();
|
||||||
}
|
}
|
||||||
rm.setData(new Object());
|
rm.setData(new Object());
|
||||||
rm.done();
|
rm.done();
|
||||||
|
@ -141,10 +141,10 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
fDataExecutor.execute(disposeCacheManagersQuery);
|
fDataExecutor.execute(disposeCacheManagersQuery);
|
||||||
try {
|
try {
|
||||||
disposeCacheManagersQuery.get();
|
disposeCacheManagersQuery.get();
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {}
|
catch (InterruptedException e) {}
|
||||||
catch (ExecutionException e) {}
|
catch (ExecutionException e) {}
|
||||||
|
|
||||||
// Cancel any outstanding data requests.
|
// Cancel any outstanding data requests.
|
||||||
for (ValueRequestMonitor rm : fItemDataRequestMonitors) {
|
for (ValueRequestMonitor rm : fItemDataRequestMonitors) {
|
||||||
rm.cancel();
|
rm.cancel();
|
||||||
|
@ -167,7 +167,7 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
// Request the item for the given index.
|
// Request the item for the given index.
|
||||||
queryValue(index);
|
queryValue(index);
|
||||||
|
|
||||||
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
||||||
// calls to be combined together improving performance of the viewer.
|
// calls to be combined together improving performance of the viewer.
|
||||||
fCancelCallsPending++;
|
fCancelCallsPending++;
|
||||||
fDisplayExecutor.execute(
|
fDisplayExecutor.execute(
|
||||||
|
@ -176,9 +176,9 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
cancelStaleRequests(topIdx, botIdx);
|
cancelStaleRequests(topIdx, botIdx);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the number of visible items based on the top item index and
|
* Calculates the number of visible items based on the top item index and
|
||||||
* table bounds.
|
* table bounds.
|
||||||
* @param top Index of top item.
|
* @param top Index of top item.
|
||||||
* @return calculated number of items in viewer
|
* @return calculated number of items in viewer
|
||||||
|
@ -187,19 +187,19 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
Table table = fViewer.getTable();
|
Table table = fViewer.getTable();
|
||||||
int itemCount = table.getItemCount();
|
int itemCount = table.getItemCount();
|
||||||
return Math.min(
|
return Math.min(
|
||||||
(table.getBounds().height / table.getItemHeight()) + 2,
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
itemCount - top);
|
itemCount - top);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the current count. When a new count is set to viewer, the viewer
|
* Retrieve the current count. When a new count is set to viewer, the viewer
|
||||||
* will refresh all items as well.
|
* will refresh all items as well.
|
||||||
*/
|
*/
|
||||||
private void queryItemCount() {
|
private void queryItemCount() {
|
||||||
// Create the request monitor to collect the count. This request
|
// Create the request monitor to collect the count. This request
|
||||||
// monitor will be completed by the following transaction.
|
// monitor will be completed by the following transaction.
|
||||||
final DataRequestMonitor<Integer> rm =
|
final DataRequestMonitor<Integer> rm =
|
||||||
new DataRequestMonitor<Integer>(fDisplayExecutor, null)
|
new DataRequestMonitor<Integer>(fDisplayExecutor, null)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -209,16 +209,16 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
protected void handleRejectedExecutionException() {} // Shutting down, ignore.
|
protected void handleRejectedExecutionException() {} // Shutting down, ignore.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use a transaction, even with a single cache. This will ensure that
|
// Use a transaction, even with a single cache. This will ensure that
|
||||||
// if the cache is reset during processing by an event. The request
|
// if the cache is reset during processing by an event. The request
|
||||||
// for data will be re-issued.
|
// for data will be re-issued.
|
||||||
fDataExecutor.execute(new Runnable() {
|
fDataExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new Transaction<Integer>() {
|
new Transaction<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
protected Integer process()
|
protected Integer process()
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
return processCount(this);
|
return processCount(this);
|
||||||
}
|
}
|
||||||
|
@ -226,24 +226,24 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the count retrieval from the sum data generator.
|
* Perform the count retrieval from the sum data generator.
|
||||||
* @param transaction The ACPM transaction to use for calculation.
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
* @return Calculated count.
|
* @return Calculated count.
|
||||||
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
* @throws CoreException See {@link Transaction#process}
|
* @throws CoreException See {@link Transaction#process}
|
||||||
*/
|
*/
|
||||||
private Integer processCount(Transaction<Integer> transaction)
|
private Integer processCount(Transaction<Integer> transaction)
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
ICache<Integer> countCache = fSumGeneratorCM.getCount();
|
ICache<Integer> countCache = fSumGeneratorCM.getCount();
|
||||||
transaction.validate(countCache);
|
transaction.validate(countCache);
|
||||||
return countCache.getData();
|
return countCache.getData();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the givne count to the viewer. This will cause the viewer will
|
* Set the givne count to the viewer. This will cause the viewer will
|
||||||
* refresh all items' data as well.
|
* refresh all items' data as well.
|
||||||
* <p>Note: This method must be called in the display thread. </p>
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
* @param count New count to set to viewer.
|
* @param count New count to set to viewer.
|
||||||
|
@ -259,8 +259,8 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
* Retrieve the current value for given index.
|
* Retrieve the current value for given index.
|
||||||
*/
|
*/
|
||||||
private void queryValue(final int index) {
|
private void queryValue(final int index) {
|
||||||
// Create the request monitor to collect the value. This request
|
// Create the request monitor to collect the value. This request
|
||||||
// monitor will be completed by the following transaction.
|
// monitor will be completed by the following transaction.
|
||||||
final ValueRequestMonitor rm = new ValueRequestMonitor(index) {
|
final ValueRequestMonitor rm = new ValueRequestMonitor(index) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
|
@ -271,24 +271,24 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void handleRejectedExecutionException() {
|
protected void handleRejectedExecutionException() {
|
||||||
// Shutting down, ignore.
|
// Shutting down, ignore.
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save the value request monitor, to cancel it if the view is
|
// Save the value request monitor, to cancel it if the view is
|
||||||
// scrolled.
|
// scrolled.
|
||||||
fItemDataRequestMonitors.add(rm);
|
fItemDataRequestMonitors.add(rm);
|
||||||
|
|
||||||
// Use a transaction, even with a single cache. This will ensure that
|
// Use a transaction, even with a single cache. This will ensure that
|
||||||
// if the cache is reset during processing by an event. The request
|
// if the cache is reset during processing by an event. The request
|
||||||
// for data will be re-issued.
|
// for data will be re-issued.
|
||||||
fDataExecutor.execute(new Runnable() {
|
fDataExecutor.execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
new Transaction<String>() {
|
new Transaction<String>() {
|
||||||
@Override
|
@Override
|
||||||
protected String process()
|
protected String process()
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
return processValue(this, index);
|
return processValue(this, index);
|
||||||
}
|
}
|
||||||
|
@ -296,9 +296,9 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the view value to the viewer.
|
* Write the view value to the viewer.
|
||||||
* <p>Note: This method must be called in the display thread. </p>
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
* @param index Index of value to set.
|
* @param index Index of value to set.
|
||||||
* @param value New value.
|
* @param value New value.
|
||||||
|
@ -308,32 +308,32 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
fViewer.replace(value, index);
|
fViewer.replace(value, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform the calculation compose the string with data provider values
|
* Perform the calculation compose the string with data provider values
|
||||||
* and the sum. This implementation also validates the result.
|
* and the sum. This implementation also validates the result.
|
||||||
* @param transaction The ACPM transaction to use for calculation.
|
* @param transaction The ACPM transaction to use for calculation.
|
||||||
* @param index Index of value to calculate.
|
* @param index Index of value to calculate.
|
||||||
* @return Calculated value.
|
* @return Calculated value.
|
||||||
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
* @throws Transaction.InvalidCacheException {@link Transaction#process}
|
||||||
* @throws CoreException See {@link Transaction#process}
|
* @throws CoreException See {@link Transaction#process}
|
||||||
*/
|
*/
|
||||||
private String processValue(Transaction<String> transaction, int index)
|
private String processValue(Transaction<String> transaction, int index)
|
||||||
throws Transaction.InvalidCacheException, CoreException
|
throws Transaction.InvalidCacheException, CoreException
|
||||||
{
|
{
|
||||||
List<ICache<Integer>> valueCaches =
|
List<ICache<Integer>> valueCaches =
|
||||||
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
new ArrayList<ICache<Integer>>(fDataGeneratorCMs.length);
|
||||||
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
for (DataGeneratorCacheManager dataGeneratorCM : fDataGeneratorCMs) {
|
||||||
valueCaches.add(dataGeneratorCM.getValue(index));
|
valueCaches.add(dataGeneratorCM.getValue(index));
|
||||||
}
|
}
|
||||||
// Validate all value caches at once. This executes needed requests
|
// Validate all value caches at once. This executes needed requests
|
||||||
// in parallel.
|
// in parallel.
|
||||||
transaction.validate(valueCaches);
|
transaction.validate(valueCaches);
|
||||||
|
|
||||||
// TODO: evaluate sum generator cache in parallel with value caches.
|
// TODO: evaluate sum generator cache in parallel with value caches.
|
||||||
ICache<Integer> sumCache = fSumGeneratorCM.getValue(index);
|
ICache<Integer> sumCache = fSumGeneratorCM.getValue(index);
|
||||||
transaction.validate(sumCache);
|
transaction.validate(sumCache);
|
||||||
|
|
||||||
// Compose the string with values, sum, and validation result.
|
// Compose the string with values, sum, and validation result.
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
int calcSum = 0;
|
int calcSum = 0;
|
||||||
|
@ -347,23 +347,23 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
if (calcSum != sumCache.getData()) {
|
if (calcSum != sumCache.getData()) {
|
||||||
result.append(" !INCORRECT! ");
|
result.append(" !INCORRECT! ");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dedicated class for data item requests. This class holds the index
|
* Dedicated class for data item requests. This class holds the index
|
||||||
* argument so it can be examined when canceling stale requests.
|
* argument so it can be examined when canceling stale requests.
|
||||||
*/
|
*/
|
||||||
private class ValueRequestMonitor extends DataRequestMonitor<String> {
|
private class ValueRequestMonitor extends DataRequestMonitor<String> {
|
||||||
/** Index is used when canceling stale requests. */
|
/** Index is used when canceling stale requests. */
|
||||||
int fIndex;
|
int fIndex;
|
||||||
|
|
||||||
ValueRequestMonitor(int index) {
|
ValueRequestMonitor(int index) {
|
||||||
super(fDisplayExecutor, null);
|
super(fDisplayExecutor, null);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleRejectedExecutionException() {
|
protected void handleRejectedExecutionException() {
|
||||||
// Shutting down, ignore.
|
// Shutting down, ignore.
|
||||||
|
@ -373,8 +373,8 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
/**
|
/**
|
||||||
* Cancels any outstanding value requests for items which are no longer
|
* Cancels any outstanding value requests for items which are no longer
|
||||||
* visible in the viewer.
|
* visible in the viewer.
|
||||||
*
|
*
|
||||||
* @param topIdx Index of top visible item in viewer.
|
* @param topIdx Index of top visible item in viewer.
|
||||||
* @param botIdx Index of bottom visible item in viewer.
|
* @param botIdx Index of bottom visible item in viewer.
|
||||||
*/
|
*/
|
||||||
private void cancelStaleRequests(int topIdx, int botIdx) {
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
|
@ -386,31 +386,31 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through the outstanding requests and cancel any that
|
// Go through the outstanding requests and cancel any that
|
||||||
// are not visible anymore.
|
// are not visible anymore.
|
||||||
for (Iterator<ValueRequestMonitor> itr =
|
for (Iterator<ValueRequestMonitor> itr =
|
||||||
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
||||||
{
|
{
|
||||||
ValueRequestMonitor item = itr.next();
|
ValueRequestMonitor item = itr.next();
|
||||||
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
// Set the item to canceled status, so that the data provider
|
// Set the item to canceled status, so that the data provider
|
||||||
// will ignore it.
|
// will ignore it.
|
||||||
item.cancel();
|
item.cancel();
|
||||||
|
|
||||||
// Add the item index to list of indexes that were canceled,
|
// Add the item index to list of indexes that were canceled,
|
||||||
// which will be sent to the table widget.
|
// which will be sent to the table widget.
|
||||||
fIndexesToCancel.add(item.fIndex);
|
fIndexesToCancel.add(item.fIndex);
|
||||||
|
|
||||||
// Remove the item from the outstanding cancel requests.
|
// Remove the item from the outstanding cancel requests.
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
||||||
Set<Integer> canceledIdxs = fIndexesToCancel;
|
Set<Integer> canceledIdxs = fIndexesToCancel;
|
||||||
fIndexesToCancel = new HashSet<Integer>();
|
fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
|
||||||
// Clear the indexes of the canceled request, so that the
|
// Clear the indexes of the canceled request, so that the
|
||||||
// viewer knows to request them again when needed.
|
// viewer knows to request them again when needed.
|
||||||
// Note: clearing using TableViewer.clear(int) seems very
|
// Note: clearing using TableViewer.clear(int) seems very
|
||||||
// inefficient, it's better to use Table.clear(int[]).
|
// inefficient, it's better to use Table.clear(int[]).
|
||||||
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
||||||
|
@ -421,11 +421,11 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
fViewer.getTable().clear(canceledIdxsArray);
|
fViewer.getTable().clear(canceledIdxsArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the example.
|
* The entry point for the example.
|
||||||
* @param args Program arguments.
|
* @param args Program arguments.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Create the shell to hold the viewer.
|
// Create the shell to hold the viewer.
|
||||||
Display display = new Display();
|
Display display = new Display();
|
||||||
|
@ -436,23 +436,23 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
// Create the table viewer.
|
// Create the table viewer.
|
||||||
TableViewer tableViewer =
|
TableViewer tableViewer =
|
||||||
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
tableViewer.getControl().setLayoutData(data);
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
||||||
|
|
||||||
// Create the data generator.
|
// Create the data generator.
|
||||||
final IDataGenerator[] generators = new IDataGenerator[5];
|
final IDataGenerator[] generators = new IDataGenerator[5];
|
||||||
for (int i = 0; i < generators.length; i++) {
|
for (int i = 0; i < generators.length; i++) {
|
||||||
generators[i] = new DataGeneratorWithExecutor(executor);
|
generators[i] = new DataGeneratorWithExecutor(executor);
|
||||||
}
|
}
|
||||||
final IDataGenerator sumGenerator =
|
final IDataGenerator sumGenerator =
|
||||||
new ACPMSumDataGenerator(executor, generators);
|
new ACPMSumDataGenerator(executor, generators);
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
ACPMSumDataViewer contentProvider = new ACPMSumDataViewer(
|
ACPMSumDataViewer contentProvider = new ACPMSumDataViewer(
|
||||||
tableViewer, new ImmediateInDsfExecutor(executor),
|
tableViewer, new ImmediateInDsfExecutor(executor),
|
||||||
generators, sumGenerator);
|
generators, sumGenerator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
@ -464,7 +464,7 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
if (!display.readAndDispatch())
|
if (!display.readAndDispatch())
|
||||||
display.sleep();
|
display.sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
// using a query again in order to wait for its completion.
|
// using a query again in order to wait for its completion.
|
||||||
Query<Object> shutdownQuery = new Query<Object>() {
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@ -483,10 +483,10 @@ public class ACPMSumDataViewer implements ILazyContentProvider
|
||||||
executor.execute(shutdownQuery);
|
executor.execute(shutdownQuery);
|
||||||
try {
|
try {
|
||||||
shutdownQuery.get();
|
shutdownQuery.get();
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
|
|
||||||
// Shut down the display.
|
// Shut down the display.
|
||||||
font.dispose();
|
font.dispose();
|
||||||
display.dispose();
|
display.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -45,43 +45,43 @@ import org.eclipse.swt.widgets.Table;
|
||||||
/**
|
/**
|
||||||
* Data viewer based on a table, which reads data using asynchronous methods.
|
* Data viewer based on a table, which reads data using asynchronous methods.
|
||||||
* <p>
|
* <p>
|
||||||
* This viewer implements the {@link ILazyContentProvider} interface
|
* This viewer implements the {@link ILazyContentProvider} interface
|
||||||
* which is used by the JFace TableViewer class to populate a Table. This
|
* which is used by the JFace TableViewer class to populate a Table. This
|
||||||
* interface contains separate asynchronous methods for requesting the count
|
* interface contains separate asynchronous methods for requesting the count
|
||||||
* and values for individual indexes, which neatly correspond to the methods
|
* and values for individual indexes, which neatly correspond to the methods
|
||||||
* in {@link IDataGenerator}. As an added optimization, this viewer
|
* in {@link IDataGenerator}. As an added optimization, this viewer
|
||||||
* implementation checks for the range of visible items in the view upon each
|
* implementation checks for the range of visible items in the view upon each
|
||||||
* request, and it cancels old requests which scroll out of view but have not
|
* request, and it cancels old requests which scroll out of view but have not
|
||||||
* been completed yet. However, it is up to the data generator implementation
|
* been completed yet. However, it is up to the data generator implementation
|
||||||
* to check the canceled state of the requests and ignore them.
|
* to check the canceled state of the requests and ignore them.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
@ConfinedToDsfExecutor("fDisplayExecutor")
|
@ConfinedToDsfExecutor("fDisplayExecutor")
|
||||||
public class AsyncDataViewer
|
public class AsyncDataViewer
|
||||||
implements ILazyContentProvider, IDataGenerator.Listener
|
implements ILazyContentProvider, IDataGenerator.Listener
|
||||||
{
|
{
|
||||||
// Executor to use instead of Display.asyncExec().
|
// Executor to use instead of Display.asyncExec().
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
final private DsfExecutor fDisplayExecutor;
|
final private DsfExecutor fDisplayExecutor;
|
||||||
|
|
||||||
// The viewer and generator that this content provider using.
|
// The viewer and generator that this content provider using.
|
||||||
final private TableViewer fViewer;
|
final private TableViewer fViewer;
|
||||||
final private IDataGenerator fDataGenerator;
|
final private IDataGenerator fDataGenerator;
|
||||||
|
|
||||||
// Fields used in request cancellation logic.
|
// Fields used in request cancellation logic.
|
||||||
private List<ValueDataRequestMonitor> fItemDataRequestMonitors =
|
private List<ValueDataRequestMonitor> fItemDataRequestMonitors =
|
||||||
new LinkedList<ValueDataRequestMonitor>();
|
new LinkedList<ValueDataRequestMonitor>();
|
||||||
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
private int fCancelCallsPending = 0;
|
private int fCancelCallsPending = 0;
|
||||||
|
|
||||||
public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
public AsyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
||||||
fViewer = viewer;
|
fViewer = viewer;
|
||||||
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
fViewer.getTable().getDisplay());
|
fViewer.getTable().getDisplay());
|
||||||
fDataGenerator = generator;
|
fDataGenerator = generator;
|
||||||
fDataGenerator.addListener(this);
|
fDataGenerator.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
fDataGenerator.removeListener(this);
|
fDataGenerator.removeListener(this);
|
||||||
|
@ -102,19 +102,19 @@ public class AsyncDataViewer
|
||||||
// Request the item for the given index.
|
// Request the item for the given index.
|
||||||
queryValue(index);
|
queryValue(index);
|
||||||
|
|
||||||
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
||||||
// calls to be combined together improving performance of the viewer.
|
// calls to be combined together improving performance of the viewer.
|
||||||
fCancelCallsPending++;
|
fCancelCallsPending++;
|
||||||
fDisplayExecutor.schedule(
|
fDisplayExecutor.schedule(
|
||||||
new Runnable() { @Override
|
new Runnable() { @Override
|
||||||
public void run() {
|
public void run() {
|
||||||
cancelStaleRequests(topIdx, botIdx);
|
cancelStaleRequests(topIdx, botIdx);
|
||||||
}},
|
}},
|
||||||
1, TimeUnit.MILLISECONDS);
|
1, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the number of visible items based on the top item index and
|
* Calculates the number of visible items based on the top item index and
|
||||||
* table bounds.
|
* table bounds.
|
||||||
* @param top Index of top item.
|
* @param top Index of top item.
|
||||||
* @return calculated number of items in viewer
|
* @return calculated number of items in viewer
|
||||||
|
@ -123,24 +123,24 @@ public class AsyncDataViewer
|
||||||
Table table = fViewer.getTable();
|
Table table = fViewer.getTable();
|
||||||
int itemCount = table.getItemCount();
|
int itemCount = table.getItemCount();
|
||||||
return Math.min(
|
return Math.min(
|
||||||
(table.getBounds().height / table.getItemHeight()) + 2,
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
itemCount - top);
|
itemCount - top);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public void countChanged() {
|
public void countChanged() {
|
||||||
queryItemCount();
|
queryItemCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public void valuesChanged(final Set<Integer> indexes) {
|
public void valuesChanged(final Set<Integer> indexes) {
|
||||||
// Mark the changed items in table viewer as dirty, this will
|
// Mark the changed items in table viewer as dirty, this will
|
||||||
// trigger update requests for these indexes if they are
|
// trigger update requests for these indexes if they are
|
||||||
// visible in the viewer.
|
// visible in the viewer.
|
||||||
final TableViewer tableViewer = fViewer;
|
final TableViewer tableViewer = fViewer;
|
||||||
fDisplayExecutor.execute( new Runnable() {
|
fDisplayExecutor.execute( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (!fViewer.getTable().isDisposed()) {
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
@ -150,18 +150,18 @@ public class AsyncDataViewer
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the up to date count. When a new count is set to viewer, the
|
* Retrieve the up to date count. When a new count is set to viewer, the
|
||||||
* viewer will refresh all items as well.
|
* viewer will refresh all items as well.
|
||||||
*/
|
*/
|
||||||
private void queryItemCount() {
|
private void queryItemCount() {
|
||||||
// Request count from data provider. When the count is returned, we
|
// Request count from data provider. When the count is returned, we
|
||||||
// have to re-dispatch into the display thread to avoid calling
|
// have to re-dispatch into the display thread to avoid calling
|
||||||
// the table widget on the DSF dispatch thread.
|
// the table widget on the DSF dispatch thread.
|
||||||
fIndexesToCancel.clear();
|
fIndexesToCancel.clear();
|
||||||
fDataGenerator.getCount(
|
fDataGenerator.getCount(
|
||||||
// Use the display executor to construct the request monitor, this
|
// Use the display executor to construct the request monitor, this
|
||||||
// will cause the handleCompleted() method to be automatically
|
// will cause the handleCompleted() method to be automatically
|
||||||
// called on the display thread.
|
// called on the display thread.
|
||||||
new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
|
new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
|
||||||
|
@ -172,40 +172,40 @@ public class AsyncDataViewer
|
||||||
fViewer.getTable().clearAll();
|
fViewer.getTable().clearAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves value of an element at given index. When complete the value
|
* Retrieves value of an element at given index. When complete the value
|
||||||
* is written to the viewer.
|
* is written to the viewer.
|
||||||
* @param index Index of value to retrieve.
|
* @param index Index of value to retrieve.
|
||||||
*/
|
*/
|
||||||
private void queryValue(final int index) {
|
private void queryValue(final int index) {
|
||||||
ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index);
|
ValueDataRequestMonitor rm = new ValueDataRequestMonitor(index);
|
||||||
fItemDataRequestMonitors.add(rm);
|
fItemDataRequestMonitors.add(rm);
|
||||||
fDataGenerator.getValue(index, rm);
|
fDataGenerator.getValue(index, rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dedicated class for data item requests. This class holds the index
|
* Dedicated class for data item requests. This class holds the index
|
||||||
* argument so it can be examined when canceling stale requests.
|
* argument so it can be examined when canceling stale requests.
|
||||||
*/
|
*/
|
||||||
private class ValueDataRequestMonitor extends DataRequestMonitor<Integer> {
|
private class ValueDataRequestMonitor extends DataRequestMonitor<Integer> {
|
||||||
|
|
||||||
/** Index is used when canceling stale requests. */
|
/** Index is used when canceling stale requests. */
|
||||||
int fIndex;
|
int fIndex;
|
||||||
|
|
||||||
ValueDataRequestMonitor(int index) {
|
ValueDataRequestMonitor(int index) {
|
||||||
super(fDisplayExecutor, null);
|
super(fDisplayExecutor, null);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
fItemDataRequestMonitors.remove(this);
|
fItemDataRequestMonitors.remove(this);
|
||||||
|
|
||||||
// Check if the request completed successfully, otherwise ignore
|
// Check if the request completed successfully, otherwise ignore
|
||||||
// it.
|
// it.
|
||||||
if (isSuccess()) {
|
if (isSuccess()) {
|
||||||
if (!fViewer.getTable().isDisposed()) {
|
if (!fViewer.getTable().isDisposed()) {
|
||||||
|
@ -214,7 +214,7 @@ public class AsyncDataViewer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cancelStaleRequests(int topIdx, int botIdx) {
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
// Decrement the count of outstanding cancel calls.
|
// Decrement the count of outstanding cancel calls.
|
||||||
fCancelCallsPending--;
|
fCancelCallsPending--;
|
||||||
|
@ -222,32 +222,32 @@ public class AsyncDataViewer
|
||||||
// Must check again, in case disposed while re-dispatching.
|
// Must check again, in case disposed while re-dispatching.
|
||||||
if (fDataGenerator == null || fViewer.getTable().isDisposed()) return;
|
if (fDataGenerator == null || fViewer.getTable().isDisposed()) return;
|
||||||
|
|
||||||
// Go through the outstanding requests and cancel any that
|
// Go through the outstanding requests and cancel any that
|
||||||
// are not visible anymore.
|
// are not visible anymore.
|
||||||
for (Iterator<ValueDataRequestMonitor> itr =
|
for (Iterator<ValueDataRequestMonitor> itr =
|
||||||
fItemDataRequestMonitors.iterator();
|
fItemDataRequestMonitors.iterator();
|
||||||
itr.hasNext();)
|
itr.hasNext();)
|
||||||
{
|
{
|
||||||
ValueDataRequestMonitor item = itr.next();
|
ValueDataRequestMonitor item = itr.next();
|
||||||
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
// Set the item to canceled status, so that the data provider
|
// Set the item to canceled status, so that the data provider
|
||||||
// will ignore it.
|
// will ignore it.
|
||||||
item.cancel();
|
item.cancel();
|
||||||
|
|
||||||
// Add the item index to list of indexes that were canceled,
|
// Add the item index to list of indexes that were canceled,
|
||||||
// which will be sent to the table widget.
|
// which will be sent to the table widget.
|
||||||
fIndexesToCancel.add(item.fIndex);
|
fIndexesToCancel.add(item.fIndex);
|
||||||
|
|
||||||
// Remove the item from the outstanding cancel requests.
|
// Remove the item from the outstanding cancel requests.
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
||||||
Set<Integer> canceledIdxs = fIndexesToCancel;
|
Set<Integer> canceledIdxs = fIndexesToCancel;
|
||||||
fIndexesToCancel = new HashSet<Integer>();
|
fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
|
||||||
// Clear the indexes of the canceled request, so that the
|
// Clear the indexes of the canceled request, so that the
|
||||||
// viewer knows to request them again when needed.
|
// viewer knows to request them again when needed.
|
||||||
// Note: clearing using TableViewer.clear(int) seems very
|
// Note: clearing using TableViewer.clear(int) seems very
|
||||||
// inefficient, it's better to use Table.clear(int[]).
|
// inefficient, it's better to use Table.clear(int[]).
|
||||||
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
||||||
|
@ -258,8 +258,8 @@ public class AsyncDataViewer
|
||||||
fViewer.getTable().clear(canceledIdxsArray);
|
fViewer.getTable().clear(canceledIdxsArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// Create the shell to hold the viewer.
|
// Create the shell to hold the viewer.
|
||||||
Display display = new Display();
|
Display display = new Display();
|
||||||
|
@ -270,15 +270,15 @@ public class AsyncDataViewer
|
||||||
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
// Create the table viewer.
|
// Create the table viewer.
|
||||||
TableViewer tableViewer =
|
TableViewer tableViewer =
|
||||||
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
tableViewer.getControl().setLayoutData(data);
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
// Create the data generator.
|
// Create the data generator.
|
||||||
final IDataGenerator generator = new DataGeneratorWithExecutor();
|
final IDataGenerator generator = new DataGeneratorWithExecutor();
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
AsyncDataViewer contentProvider =
|
AsyncDataViewer contentProvider =
|
||||||
new AsyncDataViewer(tableViewer, generator);
|
new AsyncDataViewer(tableViewer, generator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
@ -290,7 +290,7 @@ public class AsyncDataViewer
|
||||||
if (!display.readAndDispatch())
|
if (!display.readAndDispatch())
|
||||||
display.sleep();
|
display.sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
// using a query again in order to wait for its completion.
|
// using a query again in order to wait for its completion.
|
||||||
Query<Object> shutdownQuery = new Query<Object>() {
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@ -302,10 +302,10 @@ public class AsyncDataViewer
|
||||||
ImmediateExecutor.getInstance().execute(shutdownQuery);
|
ImmediateExecutor.getInstance().execute(shutdownQuery);
|
||||||
try {
|
try {
|
||||||
shutdownQuery.get();
|
shutdownQuery.get();
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
|
|
||||||
// Shut down the display.
|
// Shut down the display.
|
||||||
font.dispose();
|
font.dispose();
|
||||||
display.dispose();
|
display.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -27,19 +27,19 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A data generator which performs a sum computation on data retrieved from a
|
* A data generator which performs a sum computation on data retrieved from a
|
||||||
* number of other data generators. The data retrieval from other generators
|
* number of other data generators. The data retrieval from other generators
|
||||||
* is performed in parallel and the result is calculated once all data is
|
* is performed in parallel and the result is calculated once all data is
|
||||||
* received.
|
* received.
|
||||||
* <p>
|
* <p>
|
||||||
* This calculating generator does not listen to events from the data
|
* This calculating generator does not listen to events from the data
|
||||||
* providers so it relies on the client to re-retrieve data as needed.
|
* providers so it relies on the client to re-retrieve data as needed.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class AsyncSumDataGenerator implements IDataGenerator {
|
public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DSF executor used to serialize data access within this data generator.
|
* DSF executor used to serialize data access within this data generator.
|
||||||
*/
|
*/
|
||||||
final private DsfExecutor fExecutor;
|
final private DsfExecutor fExecutor;
|
||||||
|
|
||||||
|
@ -48,13 +48,13 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
*/
|
*/
|
||||||
final private IDataGenerator[] fDataGenerators;
|
final private IDataGenerator[] fDataGenerators;
|
||||||
|
|
||||||
public AsyncSumDataGenerator(DsfExecutor executor,
|
public AsyncSumDataGenerator(DsfExecutor executor,
|
||||||
IDataGenerator[] generators)
|
IDataGenerator[] generators)
|
||||||
{
|
{
|
||||||
fExecutor = executor;
|
fExecutor = executor;
|
||||||
fDataGenerators = generators;
|
fDataGenerators = generators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getCount(final DataRequestMonitor<Integer> rm) {
|
public void getCount(final DataRequestMonitor<Integer> rm) {
|
||||||
// Artificially delay the retrieval of the sum data to simulate
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
|
@ -64,10 +64,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
public void run() {
|
public void run() {
|
||||||
doGetCount(rm);
|
doGetCount(rm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the actual count retrieval and calculation.
|
* Performs the actual count retrieval and calculation.
|
||||||
* @param rm Request monitor to complete with data.
|
* @param rm Request monitor to complete with data.
|
||||||
|
@ -75,10 +75,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
private void doGetCount(final DataRequestMonitor<Integer> rm) {
|
private void doGetCount(final DataRequestMonitor<Integer> rm) {
|
||||||
// Array to store counts retrieved asynchronously
|
// Array to store counts retrieved asynchronously
|
||||||
final int[] counts = new int[fDataGenerators.length];
|
final int[] counts = new int[fDataGenerators.length];
|
||||||
|
|
||||||
// Counting request monitor is called once all data is retrieved.
|
// Counting request monitor is called once all data is retrieved.
|
||||||
final CountingRequestMonitor crm =
|
final CountingRequestMonitor crm =
|
||||||
new CountingRequestMonitor(fExecutor, rm)
|
new CountingRequestMonitor(fExecutor, rm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -89,26 +89,26 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
rm.done();
|
rm.done();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Each call to data generator fills in one value in array.
|
// Each call to data generator fills in one value in array.
|
||||||
for (int i = 0; i < fDataGenerators.length; i++) {
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
fDataGenerators[i].getCount(
|
fDataGenerators[i].getCount(
|
||||||
new DataRequestMonitor<Integer>(
|
new DataRequestMonitor<Integer>(
|
||||||
ImmediateExecutor.getInstance(), crm)
|
ImmediateExecutor.getInstance(), crm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
counts[finalI] = getData();
|
counts[finalI] = getData();
|
||||||
crm.done();
|
crm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
crm.setDoneCount(fDataGenerators.length);
|
crm.setDoneCount(fDataGenerators.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm)
|
||||||
{
|
{
|
||||||
// Artificially delay the retrieval of the sum data to simulate
|
// Artificially delay the retrieval of the sum data to simulate
|
||||||
// real processing time.
|
// real processing time.
|
||||||
|
@ -117,10 +117,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
public void run() {
|
public void run() {
|
||||||
doGetValue(index, rm);
|
doGetValue(index, rm);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the actual value retrieval and calculation.
|
* Performs the actual value retrieval and calculation.
|
||||||
* @param rm Request monitor to complete with data.
|
* @param rm Request monitor to complete with data.
|
||||||
|
@ -128,10 +128,10 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
private void doGetValue(int index, final DataRequestMonitor<Integer> rm) {
|
private void doGetValue(int index, final DataRequestMonitor<Integer> rm) {
|
||||||
// Array to store counts retrieved asynchronously
|
// Array to store counts retrieved asynchronously
|
||||||
final int[] values = new int[fDataGenerators.length];
|
final int[] values = new int[fDataGenerators.length];
|
||||||
|
|
||||||
// Counting request monitor is called once all data is retrieved.
|
// Counting request monitor is called once all data is retrieved.
|
||||||
final CountingRequestMonitor crm =
|
final CountingRequestMonitor crm =
|
||||||
new CountingRequestMonitor(fExecutor, rm)
|
new CountingRequestMonitor(fExecutor, rm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -144,22 +144,22 @@ public class AsyncSumDataGenerator implements IDataGenerator {
|
||||||
rm.done();
|
rm.done();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Each call to data generator fills in one value in array.
|
// Each call to data generator fills in one value in array.
|
||||||
for (int i = 0; i < fDataGenerators.length; i++) {
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
fDataGenerators[i].getValue(
|
fDataGenerators[i].getValue(
|
||||||
index,
|
index,
|
||||||
new DataRequestMonitor<Integer>(
|
new DataRequestMonitor<Integer>(
|
||||||
ImmediateExecutor.getInstance(), crm)
|
ImmediateExecutor.getInstance(), crm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
values[finalI] = getData();
|
values[finalI] = getData();
|
||||||
crm.done();
|
crm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
crm.setDoneCount(fDataGenerators.length);
|
crm.setDoneCount(fDataGenerators.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -46,20 +46,20 @@ import org.eclipse.swt.widgets.Shell;
|
||||||
import org.eclipse.swt.widgets.Table;
|
import org.eclipse.swt.widgets.Table;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data viewer based on a table, which reads data from multiple data
|
* Data viewer based on a table, which reads data from multiple data
|
||||||
* providers using asynchronous methods and performs a compultation
|
* providers using asynchronous methods and performs a compultation
|
||||||
* on the retrieved data.
|
* on the retrieved data.
|
||||||
* <p>
|
* <p>
|
||||||
* This example builds on the {@link AsyncDataViewer} example and
|
* This example builds on the {@link AsyncDataViewer} example and
|
||||||
* demonstrates the pitfalls of retrieving data from multiple sources
|
* demonstrates the pitfalls of retrieving data from multiple sources
|
||||||
* asynchronously: The data is retrieved separate from a set of providers
|
* asynchronously: The data is retrieved separate from a set of providers
|
||||||
* as well as from a data provider that sums the values from the other
|
* as well as from a data provider that sums the values from the other
|
||||||
* providers. The viewer then performs a check to ensure consistency of
|
* providers. The viewer then performs a check to ensure consistency of
|
||||||
* retrieved data. If the retrieved data is inconsistent an "INCORRECT"
|
* retrieved data. If the retrieved data is inconsistent an "INCORRECT"
|
||||||
* label is added in the viewer.
|
* label is added in the viewer.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* This viewer is updated periodically every 10 seconds, instead of being
|
* This viewer is updated periodically every 10 seconds, instead of being
|
||||||
* updated with every change in every data provider, which would overwhelm
|
* updated with every change in every data provider, which would overwhelm
|
||||||
* the viewer.
|
* the viewer.
|
||||||
* </p>
|
* </p>
|
||||||
|
@ -69,25 +69,25 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
{
|
{
|
||||||
/** View update frequency interval. */
|
/** View update frequency interval. */
|
||||||
final private static int UPDATE_INTERVAL = 10000;
|
final private static int UPDATE_INTERVAL = 10000;
|
||||||
|
|
||||||
/** Executor to use instead of Display.asyncExec(). **/
|
/** Executor to use instead of Display.asyncExec(). **/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
final private DsfExecutor fDisplayExecutor;
|
final private DsfExecutor fDisplayExecutor;
|
||||||
|
|
||||||
// The viewer and generator that this content provider using.
|
// The viewer and generator that this content provider using.
|
||||||
final private TableViewer fViewer;
|
final private TableViewer fViewer;
|
||||||
final private IDataGenerator[] fDataGenerators;
|
final private IDataGenerator[] fDataGenerators;
|
||||||
final private IDataGenerator fSumGenerator;
|
final private IDataGenerator fSumGenerator;
|
||||||
|
|
||||||
// Fields used in request cancellation logic.
|
// Fields used in request cancellation logic.
|
||||||
private List<ValueCountingRequestMonitor> fItemDataRequestMonitors =
|
private List<ValueCountingRequestMonitor> fItemDataRequestMonitors =
|
||||||
new LinkedList<ValueCountingRequestMonitor>();
|
new LinkedList<ValueCountingRequestMonitor>();
|
||||||
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
private Set<Integer> fIndexesToCancel = new HashSet<Integer>();
|
||||||
private int fCancelCallsPending = 0;
|
private int fCancelCallsPending = 0;
|
||||||
private Future<?> fRefreshFuture;
|
private Future<?> fRefreshFuture;
|
||||||
|
|
||||||
public AsyncSumDataViewer(TableViewer viewer,
|
public AsyncSumDataViewer(TableViewer viewer,
|
||||||
IDataGenerator[] generators, IDataGenerator sumGenerator)
|
IDataGenerator[] generators, IDataGenerator sumGenerator)
|
||||||
{
|
{
|
||||||
fViewer = viewer;
|
fViewer = viewer;
|
||||||
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
fDisplayExecutor = DisplayDsfExecutor.getDisplayDsfExecutor(
|
||||||
|
@ -102,15 +102,15 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
public void run() {
|
public void run() {
|
||||||
queryItemCount();
|
queryItemCount();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
UPDATE_INTERVAL, UPDATE_INTERVAL, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
// Cancel the periodic task of refreshing the view.
|
// Cancel the periodic task of refreshing the view.
|
||||||
fRefreshFuture.cancel(false);
|
fRefreshFuture.cancel(false);
|
||||||
|
|
||||||
// Cancel any outstanding data requests.
|
// Cancel any outstanding data requests.
|
||||||
for (ValueCountingRequestMonitor rm : fItemDataRequestMonitors) {
|
for (ValueCountingRequestMonitor rm : fItemDataRequestMonitors) {
|
||||||
rm.cancel();
|
rm.cancel();
|
||||||
|
@ -133,7 +133,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
// Request the item for the given index.
|
// Request the item for the given index.
|
||||||
queryValue(index);
|
queryValue(index);
|
||||||
|
|
||||||
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
// Invoke a cancel task with a delay. The delay allows multiple cancel
|
||||||
// calls to be combined together improving performance of the viewer.
|
// calls to be combined together improving performance of the viewer.
|
||||||
fCancelCallsPending++;
|
fCancelCallsPending++;
|
||||||
fDisplayExecutor.execute(
|
fDisplayExecutor.execute(
|
||||||
|
@ -142,9 +142,9 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
cancelStaleRequests(topIdx, botIdx);
|
cancelStaleRequests(topIdx, botIdx);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the number of visible items based on the top item index and
|
* Calculates the number of visible items based on the top item index and
|
||||||
* table bounds.
|
* table bounds.
|
||||||
* @param top Index of top item.
|
* @param top Index of top item.
|
||||||
* @return calculated number of items in viewer
|
* @return calculated number of items in viewer
|
||||||
|
@ -153,19 +153,19 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
Table table = fViewer.getTable();
|
Table table = fViewer.getTable();
|
||||||
int itemCount = table.getItemCount();
|
int itemCount = table.getItemCount();
|
||||||
return Math.min(
|
return Math.min(
|
||||||
(table.getBounds().height / table.getItemHeight()) + 2,
|
(table.getBounds().height / table.getItemHeight()) + 2,
|
||||||
itemCount - top);
|
itemCount - top);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the up to date count.
|
* Retrieve the up to date count.
|
||||||
*/
|
*/
|
||||||
private void queryItemCount() {
|
private void queryItemCount() {
|
||||||
// Note:The count is retrieved from the sum generator only, the sum
|
// Note:The count is retrieved from the sum generator only, the sum
|
||||||
// generator is responsible for calculating the count based on
|
// generator is responsible for calculating the count based on
|
||||||
// individual data providers' counts.
|
// individual data providers' counts.
|
||||||
fIndexesToCancel.clear();
|
fIndexesToCancel.clear();
|
||||||
fSumGenerator.getCount(
|
fSumGenerator.getCount(
|
||||||
new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
|
new DataRequestMonitor<Integer>(fDisplayExecutor, null) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -174,12 +174,12 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
@Override
|
@Override
|
||||||
protected void handleRejectedExecutionException() {
|
protected void handleRejectedExecutionException() {
|
||||||
// Shutting down, ignore.
|
// Shutting down, ignore.
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the givne count to the viewer. This will cause the viewer will
|
* Set the givne count to the viewer. This will cause the viewer will
|
||||||
* refresh all items' data as well.
|
* refresh all items' data as well.
|
||||||
* @param count New count to set to viewer.
|
* @param count New count to set to viewer.
|
||||||
*/
|
*/
|
||||||
|
@ -189,28 +189,28 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
fViewer.getTable().clearAll();
|
fViewer.getTable().clearAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves value of an element at given index. When complete the value
|
* Retrieves value of an element at given index. When complete the value
|
||||||
* is written to the viewer.
|
* is written to the viewer.
|
||||||
* @param index Index of value to retrieve.
|
* @param index Index of value to retrieve.
|
||||||
*/
|
*/
|
||||||
private void queryValue(final int index) {
|
private void queryValue(final int index) {
|
||||||
// Values retrieved asynchronously from providers are stored in local
|
// Values retrieved asynchronously from providers are stored in local
|
||||||
// arrays.
|
// arrays.
|
||||||
final int[] values = new int[fDataGenerators.length];
|
final int[] values = new int[fDataGenerators.length];
|
||||||
final int[] sum = new int[1];
|
final int[] sum = new int[1];
|
||||||
|
|
||||||
// Counting request monitor is invoked when the required number of
|
// Counting request monitor is invoked when the required number of
|
||||||
// value requests is completed.
|
// value requests is completed.
|
||||||
final ValueCountingRequestMonitor crm =
|
final ValueCountingRequestMonitor crm =
|
||||||
new ValueCountingRequestMonitor(index)
|
new ValueCountingRequestMonitor(index)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
fItemDataRequestMonitors.remove(this);
|
fItemDataRequestMonitors.remove(this);
|
||||||
|
|
||||||
// Check if the request completed successfully, otherwise
|
// Check if the request completed successfully, otherwise
|
||||||
// ignore it.
|
// ignore it.
|
||||||
if (isSuccess()) {
|
if (isSuccess()) {
|
||||||
StringBuilder result = new StringBuilder();
|
StringBuilder result = new StringBuilder();
|
||||||
|
@ -229,45 +229,45 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Request data from each data generator.
|
// Request data from each data generator.
|
||||||
for (int i = 0; i < fDataGenerators.length; i++) {
|
for (int i = 0; i < fDataGenerators.length; i++) {
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
fDataGenerators[i].getValue(
|
fDataGenerators[i].getValue(
|
||||||
index,
|
index,
|
||||||
// Use the display executor to construct the request monitor,
|
// Use the display executor to construct the request monitor,
|
||||||
// this will cause the handleCompleted() method to be
|
// this will cause the handleCompleted() method to be
|
||||||
// automatically called on the display thread.
|
// automatically called on the display thread.
|
||||||
new DataRequestMonitor<Integer>(
|
new DataRequestMonitor<Integer>(
|
||||||
ImmediateExecutor.getInstance(), crm)
|
ImmediateExecutor.getInstance(), crm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
values[finalI] = getData();
|
values[finalI] = getData();
|
||||||
crm.done();
|
crm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Separately request data from the sum data generator.
|
// Separately request data from the sum data generator.
|
||||||
fSumGenerator.getValue(
|
fSumGenerator.getValue(
|
||||||
index,
|
index,
|
||||||
new DataRequestMonitor<Integer>(
|
new DataRequestMonitor<Integer>(
|
||||||
ImmediateExecutor.getInstance(), crm)
|
ImmediateExecutor.getInstance(), crm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
sum[0] = getData();
|
sum[0] = getData();
|
||||||
crm.done();
|
crm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
crm.setDoneCount(fDataGenerators.length + 1);
|
crm.setDoneCount(fDataGenerators.length + 1);
|
||||||
fItemDataRequestMonitors.add(crm);
|
fItemDataRequestMonitors.add(crm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the view value to the viewer.
|
* Write the view value to the viewer.
|
||||||
* <p>Note: This method must be called in the display thread. </p>
|
* <p>Note: This method must be called in the display thread. </p>
|
||||||
* @param index Index of value to set.
|
* @param index Index of value to set.
|
||||||
* @param value New value.
|
* @param value New value.
|
||||||
|
@ -277,20 +277,20 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
fViewer.replace(value, index);
|
fViewer.replace(value, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dedicated class for data item requests. This class holds the index
|
* Dedicated class for data item requests. This class holds the index
|
||||||
* argument so it can be examined when canceling stale requests.
|
* argument so it can be examined when canceling stale requests.
|
||||||
*/
|
*/
|
||||||
private class ValueCountingRequestMonitor extends CountingRequestMonitor {
|
private class ValueCountingRequestMonitor extends CountingRequestMonitor {
|
||||||
/** Index is used when canceling stale requests. */
|
/** Index is used when canceling stale requests. */
|
||||||
int fIndex;
|
int fIndex;
|
||||||
|
|
||||||
ValueCountingRequestMonitor(int index) {
|
ValueCountingRequestMonitor(int index) {
|
||||||
super(fDisplayExecutor, null);
|
super(fDisplayExecutor, null);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleRejectedExecutionException() {
|
protected void handleRejectedExecutionException() {
|
||||||
// Shutting down, ignore.
|
// Shutting down, ignore.
|
||||||
|
@ -300,8 +300,8 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
/**
|
/**
|
||||||
* Cancels any outstanding value requests for items which are no longer
|
* Cancels any outstanding value requests for items which are no longer
|
||||||
* visible in the viewer.
|
* visible in the viewer.
|
||||||
*
|
*
|
||||||
* @param topIdx Index of top visible item in viewer.
|
* @param topIdx Index of top visible item in viewer.
|
||||||
* @param botIdx Index of bottom visible item in viewer.
|
* @param botIdx Index of bottom visible item in viewer.
|
||||||
*/
|
*/
|
||||||
private void cancelStaleRequests(int topIdx, int botIdx) {
|
private void cancelStaleRequests(int topIdx, int botIdx) {
|
||||||
|
@ -311,31 +311,31 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
// Must check again, in case disposed while re-dispatching.
|
// Must check again, in case disposed while re-dispatching.
|
||||||
if (fDataGenerators == null || fViewer.getTable().isDisposed()) return;
|
if (fDataGenerators == null || fViewer.getTable().isDisposed()) return;
|
||||||
|
|
||||||
// Go through the outstanding requests and cancel any that
|
// Go through the outstanding requests and cancel any that
|
||||||
// are not visible anymore.
|
// are not visible anymore.
|
||||||
for (Iterator<ValueCountingRequestMonitor> itr =
|
for (Iterator<ValueCountingRequestMonitor> itr =
|
||||||
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
fItemDataRequestMonitors.iterator(); itr.hasNext();)
|
||||||
{
|
{
|
||||||
ValueCountingRequestMonitor item = itr.next();
|
ValueCountingRequestMonitor item = itr.next();
|
||||||
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
if (item.fIndex < topIdx || item.fIndex > botIdx) {
|
||||||
// Set the item to canceled status, so that the data provider
|
// Set the item to canceled status, so that the data provider
|
||||||
// will ignore it.
|
// will ignore it.
|
||||||
item.cancel();
|
item.cancel();
|
||||||
|
|
||||||
// Add the item index to list of indexes that were canceled,
|
// Add the item index to list of indexes that were canceled,
|
||||||
// which will be sent to the table widget.
|
// which will be sent to the table widget.
|
||||||
fIndexesToCancel.add(item.fIndex);
|
fIndexesToCancel.add(item.fIndex);
|
||||||
|
|
||||||
// Remove the item from the outstanding cancel requests.
|
// Remove the item from the outstanding cancel requests.
|
||||||
itr.remove();
|
itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
if (!fIndexesToCancel.isEmpty() && fCancelCallsPending == 0) {
|
||||||
Set<Integer> canceledIdxs = fIndexesToCancel;
|
Set<Integer> canceledIdxs = fIndexesToCancel;
|
||||||
fIndexesToCancel = new HashSet<Integer>();
|
fIndexesToCancel = new HashSet<Integer>();
|
||||||
|
|
||||||
// Clear the indexes of the canceled request, so that the
|
// Clear the indexes of the canceled request, so that the
|
||||||
// viewer knows to request them again when needed.
|
// viewer knows to request them again when needed.
|
||||||
// Note: clearing using TableViewer.clear(int) seems very
|
// Note: clearing using TableViewer.clear(int) seems very
|
||||||
// inefficient, it's better to use Table.clear(int[]).
|
// inefficient, it's better to use Table.clear(int[]).
|
||||||
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
int[] canceledIdxsArray = new int[canceledIdxs.size()];
|
||||||
|
@ -346,7 +346,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
fViewer.getTable().clear(canceledIdxsArray);
|
fViewer.getTable().clear(canceledIdxsArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the example.
|
* The entry point for the example.
|
||||||
* @param args Program arguments.
|
* @param args Program arguments.
|
||||||
|
@ -361,24 +361,24 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
|
||||||
|
|
||||||
// Create the table viewer.
|
// Create the table viewer.
|
||||||
TableViewer tableViewer =
|
TableViewer tableViewer =
|
||||||
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
new TableViewer(shell, SWT.BORDER | SWT.VIRTUAL);
|
||||||
tableViewer.getControl().setLayoutData(data);
|
tableViewer.getControl().setLayoutData(data);
|
||||||
|
|
||||||
// Single executor (and single thread) is used by all data generators,
|
// Single executor (and single thread) is used by all data generators,
|
||||||
// including the sum generator.
|
// including the sum generator.
|
||||||
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
DsfExecutor executor = new DefaultDsfExecutor("Example executor");
|
||||||
|
|
||||||
// Create the data generator.
|
// Create the data generator.
|
||||||
final IDataGenerator[] generators = new IDataGenerator[5];
|
final IDataGenerator[] generators = new IDataGenerator[5];
|
||||||
for (int i = 0; i < generators.length; i++) {
|
for (int i = 0; i < generators.length; i++) {
|
||||||
generators[i] = new DataGeneratorWithExecutor(executor);
|
generators[i] = new DataGeneratorWithExecutor(executor);
|
||||||
}
|
}
|
||||||
final IDataGenerator sumGenerator =
|
final IDataGenerator sumGenerator =
|
||||||
new AsyncSumDataGenerator(executor, generators);
|
new AsyncSumDataGenerator(executor, generators);
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
AsyncSumDataViewer contentProvider =
|
AsyncSumDataViewer contentProvider =
|
||||||
new AsyncSumDataViewer(tableViewer, generators, sumGenerator);
|
new AsyncSumDataViewer(tableViewer, generators, sumGenerator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
@ -390,7 +390,7 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
if (!display.readAndDispatch())
|
if (!display.readAndDispatch())
|
||||||
display.sleep();
|
display.sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
// using a query again in order to wait for its completion.
|
// using a query again in order to wait for its completion.
|
||||||
Query<Object> shutdownQuery = new Query<Object>() {
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@ -409,10 +409,10 @@ public class AsyncSumDataViewer implements ILazyContentProvider
|
||||||
executor.execute(shutdownQuery);
|
executor.execute(shutdownQuery);
|
||||||
try {
|
try {
|
||||||
shutdownQuery.get();
|
shutdownQuery.get();
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
|
|
||||||
// Shut down the display.
|
// Shut down the display.
|
||||||
font.dispose();
|
font.dispose();
|
||||||
display.dispose();
|
display.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -30,7 +30,7 @@ import org.eclipse.core.runtime.IStatus;
|
||||||
import org.eclipse.core.runtime.Status;
|
import org.eclipse.core.runtime.Status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper class for the {@link IDataGenerator} interface, which returns
|
* A wrapper class for the {@link IDataGenerator} interface, which returns
|
||||||
* ACPM cache objects to use for data retrieval instead of calling
|
* ACPM cache objects to use for data retrieval instead of calling
|
||||||
* {@link IDataGenerator} asynchronous methods directly.
|
* {@link IDataGenerator} asynchronous methods directly.
|
||||||
*/
|
*/
|
||||||
|
@ -38,23 +38,23 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
|
|
||||||
/** Cache class for retrieving the data generator's count. */
|
/** Cache class for retrieving the data generator's count. */
|
||||||
private class CountCache extends RequestCache<Integer> {
|
private class CountCache extends RequestCache<Integer> {
|
||||||
|
|
||||||
public CountCache() {
|
public CountCache() {
|
||||||
super(fExecutor);
|
super(fExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void retrieve(DataRequestMonitor<Integer> rm) {
|
protected void retrieve(DataRequestMonitor<Integer> rm) {
|
||||||
fDataGenerator.getCount(rm);
|
fDataGenerator.getCount(rm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the cache when the count is changed.
|
* Reset the cache when the count is changed.
|
||||||
*/
|
*/
|
||||||
public void countChanged() {
|
public void countChanged() {
|
||||||
// Make sure that if clients are currently waiting for a count,
|
// Make sure that if clients are currently waiting for a count,
|
||||||
// they are notified of the update (their request monitors will be
|
// they are notified of the update (their request monitors will be
|
||||||
// completed with an error). They shoudl then re-request data
|
// completed with an error). They shoudl then re-request data
|
||||||
// from provider again.
|
// from provider again.
|
||||||
setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Count changed"));
|
setAndReset(null, new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID, "Count changed"));
|
||||||
}
|
}
|
||||||
|
@ -63,17 +63,17 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
/** Cache class for retrieving the data generator's values. */
|
/** Cache class for retrieving the data generator's values. */
|
||||||
private class ValueCache extends RequestCache<Integer> {
|
private class ValueCache extends RequestCache<Integer> {
|
||||||
private int fIndex;
|
private int fIndex;
|
||||||
|
|
||||||
public ValueCache(int index) {
|
public ValueCache(int index) {
|
||||||
super(fExecutor);
|
super(fExecutor);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void retrieve(org.eclipse.cdt.dsf.concurrent.DataRequestMonitor<Integer> rm) {
|
protected void retrieve(org.eclipse.cdt.dsf.concurrent.DataRequestMonitor<Integer> rm) {
|
||||||
fDataGenerator.getValue(fIndex, rm);
|
fDataGenerator.getValue(fIndex, rm);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CountCache#countChanged()
|
* @see CountCache#countChanged()
|
||||||
*/
|
*/
|
||||||
|
@ -83,26 +83,26 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executor used to synchronize data access in this cache manager.
|
* Executor used to synchronize data access in this cache manager.
|
||||||
* It has to be the same executor that is used by the data generators in
|
* It has to be the same executor that is used by the data generators in
|
||||||
* order to guarantee data consistency.
|
* order to guarantee data consistency.
|
||||||
*/
|
*/
|
||||||
private ImmediateInDsfExecutor fExecutor;
|
private ImmediateInDsfExecutor fExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data generator that this cache manager is a wrapper for.
|
* Data generator that this cache manager is a wrapper for.
|
||||||
*/
|
*/
|
||||||
private IDataGenerator fDataGenerator;
|
private IDataGenerator fDataGenerator;
|
||||||
|
|
||||||
/** Cache for data generator's count */
|
/** Cache for data generator's count */
|
||||||
private CountCache fCountCache;
|
private CountCache fCountCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of caches for retrieving values. Each value index has a separate
|
* Map of caches for retrieving values. Each value index has a separate
|
||||||
* cache value object.
|
* cache value object.
|
||||||
*/
|
*/
|
||||||
private Map<Integer, ValueCache> fValueCaches = new HashMap<Integer, ValueCache>();
|
private Map<Integer, ValueCache> fValueCaches = new HashMap<Integer, ValueCache>();
|
||||||
|
|
||||||
public DataGeneratorCacheManager(ImmediateInDsfExecutor executor, IDataGenerator dataGenerator) {
|
public DataGeneratorCacheManager(ImmediateInDsfExecutor executor, IDataGenerator dataGenerator) {
|
||||||
fExecutor = executor;
|
fExecutor = executor;
|
||||||
fDataGenerator = dataGenerator;
|
fDataGenerator = dataGenerator;
|
||||||
|
@ -112,14 +112,14 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
fDataGenerator.removeListener(this);
|
fDataGenerator.removeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the data generator that this cache manager wraps.
|
* Returns the data generator that this cache manager wraps.
|
||||||
*/
|
*/
|
||||||
public IDataGenerator getDataGenerator() {
|
public IDataGenerator getDataGenerator() {
|
||||||
return fDataGenerator;
|
return fDataGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cache for data generator count.
|
* Returns the cache for data generator count.
|
||||||
*/
|
*/
|
||||||
|
@ -132,7 +132,7 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cache for a value at given index.
|
* Returns the cache for a value at given index.
|
||||||
*
|
*
|
||||||
* @param index Index of value to return.
|
* @param index Index of value to return.
|
||||||
* @return Cache object for given value.
|
* @return Cache object for given value.
|
||||||
*/
|
*/
|
||||||
|
@ -142,10 +142,10 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
value = new ValueCache(index);
|
value = new ValueCache(index);
|
||||||
fValueCaches.put(index, value);
|
fValueCaches.put(index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void countChanged() {
|
public void countChanged() {
|
||||||
// Reset the count cache and all the value caches.
|
// Reset the count cache and all the value caches.
|
||||||
|
@ -156,7 +156,7 @@ public class DataGeneratorCacheManager implements IDataGenerator.Listener {
|
||||||
value.valueChanged();
|
value.valueChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void valuesChanged(Set<Integer> indexes) {
|
public void valuesChanged(Set<Integer> indexes) {
|
||||||
// Reset selected value caches.
|
// Reset selected value caches.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -53,7 +53,7 @@ import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
//TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
//TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
//indicating allowed thread access to this class/method/member
|
//indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//#@ThreadSafe
|
//#@ThreadSafe
|
||||||
|
@ -70,10 +70,10 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//#endif
|
//#endif
|
||||||
abstract class Request {
|
abstract class Request {
|
||||||
final RequestMonitor fRequestMonitor;
|
final RequestMonitor fRequestMonitor;
|
||||||
|
|
||||||
Request(RequestMonitor rm) {
|
Request(RequestMonitor rm) {
|
||||||
fRequestMonitor = rm;
|
fRequestMonitor = rm;
|
||||||
|
|
||||||
rm.addCancelListener(new RequestMonitor.ICanceledListener() {
|
rm.addCancelListener(new RequestMonitor.ICanceledListener() {
|
||||||
@Override
|
@Override
|
||||||
public void requestCanceled(RequestMonitor rm) {
|
public void requestCanceled(RequestMonitor rm) {
|
||||||
|
@ -87,49 +87,49 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @Immutable
|
//# @Immutable
|
||||||
//#endif
|
//#endif
|
||||||
class CountRequest extends Request {
|
class CountRequest extends Request {
|
||||||
CountRequest(DataRequestMonitor<Integer> rm) {
|
CountRequest(DataRequestMonitor<Integer> rm) {
|
||||||
super(rm);
|
super(rm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @Immutable
|
//# @Immutable
|
||||||
//#endif
|
//#endif
|
||||||
class ItemRequest extends Request {
|
class ItemRequest extends Request {
|
||||||
final int fIndex;
|
final int fIndex;
|
||||||
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
||||||
super(rm);
|
super(rm);
|
||||||
fIndex = index;
|
fIndex = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The executor used to access all internal data of the generator.
|
// The executor used to access all internal data of the generator.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
// Hint: If a member does not have an annotation, the programmer can assume
|
// Hint: If a member does not have an annotation, the programmer can assume
|
||||||
// that the concurrency rule that applies to the class also applies to this
|
// that the concurrency rule that applies to the class also applies to this
|
||||||
// member.
|
// member.
|
||||||
//#endif
|
//#endif
|
||||||
private DsfExecutor fExecutor;
|
private DsfExecutor fExecutor;
|
||||||
|
|
||||||
// Main request queue of the data generator. The getValue(), getCount(),
|
// Main request queue of the data generator. The getValue(), getCount(),
|
||||||
// and shutdown() methods write into the queue, while the serviceQueue()
|
// and shutdown() methods write into the queue, while the serviceQueue()
|
||||||
// method reads from it.
|
// method reads from it.
|
||||||
// The executor used to access all internal data of the generator.
|
// The executor used to access all internal data of the generator.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
|
@ -139,7 +139,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
// List of listeners is not synchronized, it also has to be accessed
|
// List of listeners is not synchronized, it also has to be accessed
|
||||||
// using the executor.
|
// using the executor.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
|
@ -148,38 +148,38 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
|
|
||||||
// Current number of elements in this generator.
|
// Current number of elements in this generator.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private int fCount = MIN_COUNT;
|
private int fCount = MIN_COUNT;
|
||||||
|
|
||||||
// Counter used to determine when to reset the element count.
|
// Counter used to determine when to reset the element count.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private int fCountResetTrigger = 0;
|
private int fCountResetTrigger = 0;
|
||||||
|
|
||||||
// Elements which were modified since the last reset.
|
// Elements which were modified since the last reset.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private Map<Integer, Integer> fChangedValues =
|
private Map<Integer, Integer> fChangedValues =
|
||||||
new HashMap<Integer, Integer>();
|
new HashMap<Integer, Integer>();
|
||||||
|
|
||||||
public DataGeneratorWithExecutor() {
|
public DataGeneratorWithExecutor() {
|
||||||
// Create the executor
|
// Create the executor
|
||||||
this(new DefaultDsfExecutor("Supplier Executor"));
|
this(new DefaultDsfExecutor("Supplier Executor"));
|
||||||
}
|
}
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
public DataGeneratorWithExecutor(DsfExecutor executor) {
|
public DataGeneratorWithExecutor(DsfExecutor executor) {
|
||||||
|
@ -194,13 +194,13 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
randomChanges();
|
randomChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rand.nextInt(RANDOM_CHANGE_INTERVAL),
|
rand.nextInt(RANDOM_CHANGE_INTERVAL),
|
||||||
RANDOM_CHANGE_INTERVAL, //Add a 10% variance to the interval.
|
RANDOM_CHANGE_INTERVAL, //Add a 10% variance to the interval.
|
||||||
TimeUnit.MILLISECONDS);
|
TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
@Override
|
@Override
|
||||||
|
@ -212,26 +212,26 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
// Empty the queue of requests and fail them.
|
// Empty the queue of requests and fail them.
|
||||||
for (Request request : fQueue) {
|
for (Request request : fQueue) {
|
||||||
request.fRequestMonitor.setStatus(new Status(
|
request.fRequestMonitor.setStatus(new Status(
|
||||||
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
request.fRequestMonitor.done();
|
request.fRequestMonitor.done();
|
||||||
}
|
}
|
||||||
fQueue.clear();
|
fQueue.clear();
|
||||||
|
|
||||||
// Kill executor.
|
// Kill executor.
|
||||||
fExecutor.shutdown();
|
fExecutor.shutdown();
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
@Override
|
@Override
|
||||||
|
@ -246,18 +246,18 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(
|
rm.setStatus(new Status(
|
||||||
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
@Override
|
@Override
|
||||||
public void getValue(final int index, final DataRequestMonitor<Integer> rm) {
|
public void getValue(final int index, final DataRequestMonitor<Integer> rm) {
|
||||||
try {
|
try {
|
||||||
fExecutor.execute( new DsfRunnable() {
|
fExecutor.execute( new DsfRunnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -267,14 +267,14 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (RejectedExecutionException e) {
|
} catch (RejectedExecutionException e) {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
@Override
|
@Override
|
||||||
|
@ -290,7 +290,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#endif
|
//#endif
|
||||||
@Override
|
@Override
|
||||||
|
@ -307,7 +307,7 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
|
|
||||||
// Main processing function of this generator.
|
// Main processing function of this generator.
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
|
@ -319,8 +319,8 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
public void run() {
|
public void run() {
|
||||||
doServiceQueue();
|
doServiceQueue();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
PROCESSING_DELAY, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
|
@ -332,9 +332,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
private void doServiceQueue() {
|
private void doServiceQueue() {
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 3 - Add logic to discard cancelled requests from queue.
|
// TODO Exercise 3 - Add logic to discard cancelled requests from queue.
|
||||||
// Hint: Since serviceQueue() is called using the executor, and the
|
// Hint: Since serviceQueue() is called using the executor, and the
|
||||||
// fQueue list can only be modified when running in the executor
|
// fQueue list can only be modified when running in the executor
|
||||||
// thread. This method can safely iterate and modify fQueue without
|
// thread. This method can safely iterate and modify fQueue without
|
||||||
// risk of race conditions or concurrent modification exceptions.
|
// risk of race conditions or concurrent modification exceptions.
|
||||||
//#else
|
//#else
|
||||||
//# for (Iterator<Request> requestItr = fQueue.iterator(); requestItr.hasNext();) {
|
//# for (Iterator<Request> requestItr = fQueue.iterator(); requestItr.hasNext();) {
|
||||||
|
@ -347,9 +347,9 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
//# }
|
//# }
|
||||||
//# }
|
//# }
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
while (fQueue.size() != 0) {
|
while (fQueue.size() != 0) {
|
||||||
// If there are requests to service, remove one from the queue and
|
// If there are requests to service, remove one from the queue and
|
||||||
// schedule a runnable to process the request after a processing
|
// schedule a runnable to process the request after a processing
|
||||||
// delay.
|
// delay.
|
||||||
Request request = fQueue.remove(0);
|
Request request = fQueue.remove(0);
|
||||||
|
@ -357,55 +357,55 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
processCountRequest((CountRequest)request);
|
processCountRequest((CountRequest)request);
|
||||||
} else if (request instanceof ItemRequest) {
|
} else if (request instanceof ItemRequest) {
|
||||||
processItemRequest((ItemRequest)request);
|
processItemRequest((ItemRequest)request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private void processCountRequest(CountRequest request) {
|
private void processCountRequest(CountRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm =
|
DataRequestMonitor<Integer> rm =
|
||||||
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
rm.setData(fCount);
|
rm.setData(fCount);
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private void processItemRequest(ItemRequest request) {
|
private void processItemRequest(ItemRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm =
|
DataRequestMonitor<Integer> rm =
|
||||||
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
if (fChangedValues.containsKey(request.fIndex)) {
|
if (fChangedValues.containsKey(request.fIndex)) {
|
||||||
rm.setData(fChangedValues.get(request.fIndex));
|
rm.setData(fChangedValues.get(request.fIndex));
|
||||||
} else {
|
} else {
|
||||||
rm.setData(request.fIndex);
|
rm.setData(request.fIndex);
|
||||||
}
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method simulates changes in the supplier's data set.
|
* This method simulates changes in the supplier's data set.
|
||||||
*/
|
*/
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
//#endif
|
//#endif
|
||||||
private void randomChanges() {
|
private void randomChanges() {
|
||||||
// Once every number of changes, reset the count, the rest of the
|
// Once every number of changes, reset the count, the rest of the
|
||||||
// times just change certain values.
|
// times just change certain values.
|
||||||
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0){
|
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0){
|
||||||
randomCountReset();
|
randomCountReset();
|
||||||
|
@ -413,12 +413,12 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
randomDataChange();
|
randomDataChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates new size for provider's data set.
|
* Calculates new size for provider's data set.
|
||||||
*/
|
*/
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
|
@ -430,18 +430,18 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
|
|
||||||
// Reset the changed values.
|
// Reset the changed values.
|
||||||
fChangedValues.clear();
|
fChangedValues.clear();
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Listener listener : fListeners) {
|
for (Listener listener : fListeners) {
|
||||||
listener.countChanged();
|
listener.countChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates a random range of indexes.
|
* Invalidates a random range of indexes.
|
||||||
*/
|
*/
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//# @ConfinedToDsfExecutor("fExecutor")
|
//# @ConfinedToDsfExecutor("fExecutor")
|
||||||
|
@ -454,15 +454,15 @@ public class DataGeneratorWithExecutor implements IDataGenerator {
|
||||||
int randomIndex = random.nextInt(fCount);
|
int randomIndex = random.nextInt(fCount);
|
||||||
int randomValue = random.nextInt(fCount);
|
int randomValue = random.nextInt(fCount);
|
||||||
changed.put(randomIndex, randomValue);
|
changed.put(randomIndex, randomValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the indexes to an overall set of changed indexes.
|
// Add the indexes to an overall set of changed indexes.
|
||||||
fChangedValues.putAll(changed);
|
fChangedValues.putAll(changed);
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Object listener : fListeners) {
|
for (Object listener : fListeners) {
|
||||||
((Listener)listener).valuesChanged(changed.keySet());
|
((Listener)listener).valuesChanged(changed.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -36,78 +36,78 @@ import org.eclipse.cdt.examples.dsf.DsfExamplesPlugin;
|
||||||
/**
|
/**
|
||||||
* Thread-based implementation of the data generator.
|
* Thread-based implementation of the data generator.
|
||||||
* <p>
|
* <p>
|
||||||
* This generator is based around a queue of client requests and a thread which
|
* This generator is based around a queue of client requests and a thread which
|
||||||
* reads the requests from the queue and processes them. The distinguishing
|
* reads the requests from the queue and processes them. The distinguishing
|
||||||
* feature of this generator is that it uses a a blocking queue as the main
|
* feature of this generator is that it uses a a blocking queue as the main
|
||||||
* synchronization object. However, fListeners, fShutdown, and fChangedIndexes
|
* synchronization object. However, fListeners, fShutdown, and fChangedIndexes
|
||||||
* fields also need to be thread-safe and so they implement their own
|
* fields also need to be thread-safe and so they implement their own
|
||||||
* synchronization.
|
* synchronization.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class DataGeneratorWithThread extends Thread
|
public class DataGeneratorWithThread extends Thread
|
||||||
implements IDataGenerator
|
implements IDataGenerator
|
||||||
{
|
{
|
||||||
|
|
||||||
// Request objects are used to serialize the interface calls into objects
|
// Request objects are used to serialize the interface calls into objects
|
||||||
// which can then be pushed into a queue.
|
// which can then be pushed into a queue.
|
||||||
abstract class Request {
|
abstract class Request {
|
||||||
final RequestMonitor fRequestMonitor;
|
final RequestMonitor fRequestMonitor;
|
||||||
|
|
||||||
Request(RequestMonitor rm) {
|
Request(RequestMonitor rm) {
|
||||||
fRequestMonitor = rm;
|
fRequestMonitor = rm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CountRequest extends Request {
|
class CountRequest extends Request {
|
||||||
CountRequest(DataRequestMonitor<Integer> rm) {
|
CountRequest(DataRequestMonitor<Integer> rm) {
|
||||||
super(rm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ItemRequest extends Request {
|
|
||||||
final int fIndex;
|
|
||||||
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
|
||||||
super(rm);
|
|
||||||
fIndex = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ShutdownRequest extends Request {
|
|
||||||
ShutdownRequest(RequestMonitor rm) {
|
|
||||||
super(rm);
|
super(rm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main request queue of the data generator. The getValue(), getCount(),
|
class ItemRequest extends Request {
|
||||||
// and shutdown() methods write into the queue, while the run() method
|
final int fIndex;
|
||||||
|
ItemRequest(int index, DataRequestMonitor<Integer> rm) {
|
||||||
|
super(rm);
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShutdownRequest extends Request {
|
||||||
|
ShutdownRequest(RequestMonitor rm) {
|
||||||
|
super(rm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main request queue of the data generator. The getValue(), getCount(),
|
||||||
|
// and shutdown() methods write into the queue, while the run() method
|
||||||
// reads from it.
|
// reads from it.
|
||||||
private final BlockingQueue<Request> fQueue =
|
private final BlockingQueue<Request> fQueue =
|
||||||
new LinkedBlockingQueue<Request>();
|
new LinkedBlockingQueue<Request>();
|
||||||
|
|
||||||
// ListenerList class provides thread safety.
|
// ListenerList class provides thread safety.
|
||||||
private ListenerList<Listener> fListeners = new ListenerList<>();
|
private ListenerList<Listener> fListeners = new ListenerList<>();
|
||||||
|
|
||||||
// Current number of elements in this generator.
|
// Current number of elements in this generator.
|
||||||
private int fCount = MIN_COUNT;
|
private int fCount = MIN_COUNT;
|
||||||
|
|
||||||
// Counter used to determine when to reset the element count.
|
// Counter used to determine when to reset the element count.
|
||||||
private int fCountResetTrigger = 0;
|
private int fCountResetTrigger = 0;
|
||||||
|
|
||||||
// Elements which were modified since the last reset.
|
// Elements which were modified since the last reset.
|
||||||
private Map<Integer, Integer> fChangedValues =
|
private Map<Integer, Integer> fChangedValues =
|
||||||
Collections.synchronizedMap(new HashMap<Integer, Integer>());
|
Collections.synchronizedMap(new HashMap<Integer, Integer>());
|
||||||
|
|
||||||
// Used to determine when to make changes in data.
|
// Used to determine when to make changes in data.
|
||||||
private long fLastChangeTime = System.currentTimeMillis();
|
private long fLastChangeTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Flag indicating when the generator has been shut down.
|
// Flag indicating when the generator has been shut down.
|
||||||
private AtomicBoolean fShutdown = new AtomicBoolean(false);
|
private AtomicBoolean fShutdown = new AtomicBoolean(false);
|
||||||
|
|
||||||
public DataGeneratorWithThread() {
|
public DataGeneratorWithThread() {
|
||||||
// Immediately kick off the request processing thread.
|
// Immediately kick off the request processing thread.
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void shutdown(RequestMonitor rm) {
|
public void shutdown(RequestMonitor rm) {
|
||||||
// Mark the generator as shut down. After the fShutdown flag is set,
|
// Mark the generator as shut down. After the fShutdown flag is set,
|
||||||
|
@ -115,11 +115,11 @@ public class DataGeneratorWithThread extends Thread
|
||||||
if (!fShutdown.getAndSet(true)) {
|
if (!fShutdown.getAndSet(true)) {
|
||||||
fQueue.add(new ShutdownRequest(rm));
|
fQueue.add(new ShutdownRequest(rm));
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -127,22 +127,22 @@ public class DataGeneratorWithThread extends Thread
|
||||||
if (!fShutdown.get()) {
|
if (!fShutdown.get()) {
|
||||||
fQueue.add(new CountRequest(rm));
|
fQueue.add(new CountRequest(rm));
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getValue(int index, DataRequestMonitor<Integer> rm) {
|
public void getValue(int index, DataRequestMonitor<Integer> rm) {
|
||||||
if (!fShutdown.get()) {
|
if (!fShutdown.get()) {
|
||||||
fQueue.add(new ItemRequest(index, rm));
|
fQueue.add(new ItemRequest(index, rm));
|
||||||
} else {
|
} else {
|
||||||
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
rm.setStatus(new Status(IStatus.ERROR, DsfExamplesPlugin.PLUGIN_ID,
|
||||||
"Supplier shut down"));
|
"Supplier shut down"));
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(Listener listener) {
|
public void addListener(Listener listener) {
|
||||||
|
@ -153,25 +153,25 @@ public class DataGeneratorWithThread extends Thread
|
||||||
public void removeListener(Listener listener) {
|
public void removeListener(Listener listener) {
|
||||||
fListeners.remove(listener);
|
fListeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
while(true) {
|
while(true) {
|
||||||
// Get the next request from the queue. The time-out
|
// Get the next request from the queue. The time-out
|
||||||
// ensures that that the random changes get processed.
|
// ensures that that the random changes get processed.
|
||||||
final Request request = fQueue.poll(100, TimeUnit.MILLISECONDS);
|
final Request request = fQueue.poll(100, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
// If a request was dequeued, process it.
|
// If a request was dequeued, process it.
|
||||||
if (request != null) {
|
if (request != null) {
|
||||||
// Simulate a processing delay.
|
// Simulate a processing delay.
|
||||||
|
|
||||||
if (request instanceof CountRequest) {
|
if (request instanceof CountRequest) {
|
||||||
processCountRequest((CountRequest)request);
|
processCountRequest((CountRequest)request);
|
||||||
} else if (request instanceof ItemRequest) {
|
} else if (request instanceof ItemRequest) {
|
||||||
processItemRequest((ItemRequest)request);
|
processItemRequest((ItemRequest)request);
|
||||||
} else if (request instanceof ShutdownRequest) {
|
} else if (request instanceof ShutdownRequest) {
|
||||||
// If shutting down, just break out of the while(true)
|
// If shutting down, just break out of the while(true)
|
||||||
// loop and thread will exit.
|
// loop and thread will exit.
|
||||||
request.fRequestMonitor.done();
|
request.fRequestMonitor.done();
|
||||||
break;
|
break;
|
||||||
|
@ -179,27 +179,27 @@ public class DataGeneratorWithThread extends Thread
|
||||||
} else {
|
} else {
|
||||||
Thread.sleep(PROCESSING_DELAY);
|
Thread.sleep(PROCESSING_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simulate data changes.
|
// Simulate data changes.
|
||||||
randomChanges();
|
randomChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (InterruptedException x) {}
|
catch (InterruptedException x) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processCountRequest(CountRequest request) {
|
private void processCountRequest(CountRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm =
|
DataRequestMonitor<Integer> rm =
|
||||||
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
rm.setData(fCount);
|
rm.setData(fCount);
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processItemRequest(ItemRequest request) {
|
private void processItemRequest(ItemRequest request) {
|
||||||
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
@SuppressWarnings("unchecked") // Suppress warning about lost type info.
|
||||||
DataRequestMonitor<Integer> rm =
|
DataRequestMonitor<Integer> rm =
|
||||||
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
(DataRequestMonitor<Integer>)request.fRequestMonitor;
|
||||||
|
|
||||||
if (fChangedValues.containsKey(request.fIndex)) {
|
if (fChangedValues.containsKey(request.fIndex)) {
|
||||||
rm.setData(fChangedValues.get(request.fIndex));
|
rm.setData(fChangedValues.get(request.fIndex));
|
||||||
|
@ -207,17 +207,17 @@ public class DataGeneratorWithThread extends Thread
|
||||||
rm.setData(request.fIndex);
|
rm.setData(request.fIndex);
|
||||||
}
|
}
|
||||||
rm.done();
|
rm.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void randomChanges() {
|
private void randomChanges() {
|
||||||
// Check if enough time is elapsed.
|
// Check if enough time is elapsed.
|
||||||
if (System.currentTimeMillis() >
|
if (System.currentTimeMillis() >
|
||||||
fLastChangeTime + RANDOM_CHANGE_INTERVAL)
|
fLastChangeTime + RANDOM_CHANGE_INTERVAL)
|
||||||
{
|
{
|
||||||
fLastChangeTime = System.currentTimeMillis();
|
fLastChangeTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// Once every number of changes, reset the count, the rest of the
|
// Once every number of changes, reset the count, the rest of the
|
||||||
// times just change certain values.
|
// times just change certain values.
|
||||||
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0) {
|
if (++fCountResetTrigger % RANDOM_COUNT_CHANGE_INTERVALS == 0) {
|
||||||
randomCountReset();
|
randomCountReset();
|
||||||
|
@ -226,7 +226,7 @@ public class DataGeneratorWithThread extends Thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void randomCountReset() {
|
private void randomCountReset() {
|
||||||
// Calculate the new count.
|
// Calculate the new count.
|
||||||
Random random = new java.util.Random();
|
Random random = new java.util.Random();
|
||||||
|
@ -234,13 +234,13 @@ public class DataGeneratorWithThread extends Thread
|
||||||
|
|
||||||
// Reset the changed values.
|
// Reset the changed values.
|
||||||
fChangedValues.clear();
|
fChangedValues.clear();
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Object listener : fListeners.getListeners()) {
|
for (Object listener : fListeners.getListeners()) {
|
||||||
((Listener)listener).countChanged();
|
((Listener)listener).countChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void randomDataChange() {
|
private void randomDataChange() {
|
||||||
// Calculate the indexes to change.
|
// Calculate the indexes to change.
|
||||||
Random random = new java.util.Random();
|
Random random = new java.util.Random();
|
||||||
|
@ -249,16 +249,16 @@ public class DataGeneratorWithThread extends Thread
|
||||||
int randomIndex = random.nextInt(fCount);
|
int randomIndex = random.nextInt(fCount);
|
||||||
int randomValue = random.nextInt(fCount);
|
int randomValue = random.nextInt(fCount);
|
||||||
changed.put(randomIndex, randomValue);
|
changed.put(randomIndex, randomValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the indexes to an overall set of changed indexes.
|
// Add the indexes to an overall set of changed indexes.
|
||||||
fChangedValues.putAll(changed);
|
fChangedValues.putAll(changed);
|
||||||
|
|
||||||
// Notify listeners
|
// Notify listeners
|
||||||
for (Object listener : fListeners.getListeners()) {
|
for (Object listener : fListeners.getListeners()) {
|
||||||
((Listener)listener).valuesChanged(changed.keySet());
|
((Listener)listener).valuesChanged(changed.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -26,14 +26,14 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data generator is simple source of data used to populate the example table
|
* Data generator is simple source of data used to populate the example table
|
||||||
* view. It contains two asynchronous methods for retrieving the data
|
* view. It contains two asynchronous methods for retrieving the data
|
||||||
* parameters: the count and the value for a given index. It also allows the
|
* parameters: the count and the value for a given index. It also allows the
|
||||||
* view to receive events indicating when the data supplied by the generator
|
* view to receive events indicating when the data supplied by the generator
|
||||||
* is changed.
|
* is changed.
|
||||||
*/
|
*/
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
// TODO Exercise 4 - Add an annotation (ThreadSafe/ConfinedToDsfExecutor)
|
||||||
// indicating allowed thread access to this class/method/member
|
// indicating allowed thread access to this class/method/member
|
||||||
//#else
|
//#else
|
||||||
//#@ThreadSafe
|
//#@ThreadSafe
|
||||||
|
@ -42,7 +42,7 @@ public interface IDataGenerator {
|
||||||
|
|
||||||
// Constants which control the data generator behavior.
|
// Constants which control the data generator behavior.
|
||||||
// Changing the count range can stress the scalability of the system, while
|
// Changing the count range can stress the scalability of the system, while
|
||||||
// changing of the process delay and random change interval can stress
|
// changing of the process delay and random change interval can stress
|
||||||
// its performance.
|
// its performance.
|
||||||
final static int MIN_COUNT = 50;
|
final static int MIN_COUNT = 50;
|
||||||
final static int MAX_COUNT = 100;
|
final static int MAX_COUNT = 100;
|
||||||
|
@ -51,7 +51,7 @@ public interface IDataGenerator {
|
||||||
final static int RANDOM_COUNT_CHANGE_INTERVALS = 5;
|
final static int RANDOM_COUNT_CHANGE_INTERVALS = 5;
|
||||||
final static int RANDOM_CHANGE_SET_PERCENTAGE = 10;
|
final static int RANDOM_CHANGE_SET_PERCENTAGE = 10;
|
||||||
|
|
||||||
|
|
||||||
// Listener interface that the view needs to implement to react
|
// Listener interface that the view needs to implement to react
|
||||||
// to the changes in data.
|
// to the changes in data.
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
|
@ -61,10 +61,10 @@ public interface IDataGenerator {
|
||||||
|
|
||||||
// Data access methods.
|
// Data access methods.
|
||||||
void getCount(DataRequestMonitor<Integer> rm);
|
void getCount(DataRequestMonitor<Integer> rm);
|
||||||
void getValue(int index, DataRequestMonitor<Integer> rm);
|
void getValue(int index, DataRequestMonitor<Integer> rm);
|
||||||
|
|
||||||
// Method used to shutdown the data generator including any threads that
|
// Method used to shutdown the data generator including any threads that
|
||||||
// it may use.
|
// it may use.
|
||||||
void shutdown(RequestMonitor rm);
|
void shutdown(RequestMonitor rm);
|
||||||
|
|
||||||
// Methods for registering change listeners.
|
// Methods for registering change listeners.
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -38,67 +38,67 @@ import org.eclipse.swt.widgets.Shell;
|
||||||
/**
|
/**
|
||||||
* Data viewer based on a table, which reads data using synchronous methods.
|
* Data viewer based on a table, which reads data using synchronous methods.
|
||||||
* <p>
|
* <p>
|
||||||
* This viewer implements the {@link IStructuredContentProvider} interface
|
* This viewer implements the {@link IStructuredContentProvider} interface
|
||||||
* which is used by the JFace TableViewer class to populate a Table. This
|
* which is used by the JFace TableViewer class to populate a Table. This
|
||||||
* interface contains one principal methods for reading data {@link #getElements(Object)},
|
* interface contains one principal methods for reading data {@link #getElements(Object)},
|
||||||
* which synchronously returns an array of elements. In order to implement
|
* which synchronously returns an array of elements. In order to implement
|
||||||
* this method using the asynchronous data generator, this provider uses the
|
* this method using the asynchronous data generator, this provider uses the
|
||||||
* {@link Query} object.
|
* {@link Query} object.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class SyncDataViewer
|
public class SyncDataViewer
|
||||||
implements IStructuredContentProvider, IDataGenerator.Listener
|
implements IStructuredContentProvider, IDataGenerator.Listener
|
||||||
{
|
{
|
||||||
// The viewer and generator that this content provider using.
|
// The viewer and generator that this content provider using.
|
||||||
final private TableViewer fViewer;
|
final private TableViewer fViewer;
|
||||||
final private IDataGenerator fDataGenerator;
|
final private IDataGenerator fDataGenerator;
|
||||||
|
|
||||||
public SyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
public SyncDataViewer(TableViewer viewer, IDataGenerator generator) {
|
||||||
fViewer = viewer;
|
fViewer = viewer;
|
||||||
fDataGenerator = generator;
|
fDataGenerator = generator;
|
||||||
fDataGenerator.addListener(this);
|
fDataGenerator.addListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
|
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
|
||||||
// Not used
|
// Not used
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] getElements(Object inputElement) {
|
public Object[] getElements(Object inputElement) {
|
||||||
|
|
||||||
// Create the query object for reading data count.
|
// Create the query object for reading data count.
|
||||||
Query<Integer> countQuery = new Query<Integer>() {
|
Query<Integer> countQuery = new Query<Integer>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(DataRequestMonitor<Integer> rm) {
|
protected void execute(DataRequestMonitor<Integer> rm) {
|
||||||
fDataGenerator.getCount(rm);
|
fDataGenerator.getCount(rm);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Submit the query to be executed. A query implements a runnable
|
// Submit the query to be executed. A query implements a runnable
|
||||||
// interface and it has to be executed in order to do its work.
|
// interface and it has to be executed in order to do its work.
|
||||||
ImmediateExecutor.getInstance().execute(countQuery);
|
ImmediateExecutor.getInstance().execute(countQuery);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
// Block until the query completes, which will happen when the request
|
// Block until the query completes, which will happen when the request
|
||||||
// monitor of the execute() method is marked done.
|
// monitor of the execute() method is marked done.
|
||||||
try {
|
try {
|
||||||
count = countQuery.get();
|
count = countQuery.get();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// InterruptedException and ExecutionException can be thrown here.
|
// InterruptedException and ExecutionException can be thrown here.
|
||||||
// ExecutionException containing a CoreException will be thrown
|
// ExecutionException containing a CoreException will be thrown
|
||||||
// if an error status is set to the Query's request monitor.
|
// if an error status is set to the Query's request monitor.
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
final int finalCount = count;
|
final int finalCount = count;
|
||||||
Query<List<Integer>> valueQuery = new Query<List<Integer>>() {
|
Query<List<Integer>> valueQuery = new Query<List<Integer>>() {
|
||||||
@Override
|
@Override
|
||||||
protected void execute(final DataRequestMonitor<List<Integer>> rm) {
|
protected void execute(final DataRequestMonitor<List<Integer>> rm) {
|
||||||
final Integer[] retVal = new Integer[finalCount];
|
final Integer[] retVal = new Integer[finalCount];
|
||||||
final CountingRequestMonitor crm = new CountingRequestMonitor(
|
final CountingRequestMonitor crm = new CountingRequestMonitor(
|
||||||
ImmediateExecutor.getInstance(), rm)
|
ImmediateExecutor.getInstance(), rm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -109,9 +109,9 @@ public class SyncDataViewer
|
||||||
for (int i = 0; i < finalCount; i++) {
|
for (int i = 0; i < finalCount; i++) {
|
||||||
final int finalI = i;
|
final int finalI = i;
|
||||||
fDataGenerator.getValue(
|
fDataGenerator.getValue(
|
||||||
i,
|
i,
|
||||||
new DataRequestMonitor<Integer>(
|
new DataRequestMonitor<Integer>(
|
||||||
ImmediateExecutor.getInstance(), crm)
|
ImmediateExecutor.getInstance(), crm)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected void handleSuccess() {
|
protected void handleSuccess() {
|
||||||
|
@ -126,7 +126,7 @@ public class SyncDataViewer
|
||||||
ImmediateExecutor.getInstance().execute(valueQuery);
|
ImmediateExecutor.getInstance().execute(valueQuery);
|
||||||
try {
|
try {
|
||||||
return valueQuery.get().toArray(new Integer[0]);
|
return valueQuery.get().toArray(new Integer[0]);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
return new Object[0];
|
return new Object[0];
|
||||||
}
|
}
|
||||||
|
@ -141,23 +141,23 @@ public class SyncDataViewer
|
||||||
// For any event from the generator, refresh the whole viewer.
|
// For any event from the generator, refresh the whole viewer.
|
||||||
refreshViewer();
|
refreshViewer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void valuesChanged(Set<Integer> indexes) {
|
public void valuesChanged(Set<Integer> indexes) {
|
||||||
// For any event from the generator, refresh the whole viewer.
|
// For any event from the generator, refresh the whole viewer.
|
||||||
refreshViewer();
|
refreshViewer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshViewer() {
|
private void refreshViewer() {
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 5 - Add a call to getElements() to force a deadlock.
|
// TODO Exercise 5 - Add a call to getElements() to force a deadlock.
|
||||||
//#else
|
//#else
|
||||||
//# getElements(null);
|
//# getElements(null);
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
// This method may be called on any thread, switch to the display
|
// This method may be called on any thread, switch to the display
|
||||||
// thread before calling the viewer.
|
// thread before calling the viewer.
|
||||||
Display display = fViewer.getControl().getDisplay();
|
Display display = fViewer.getControl().getDisplay();
|
||||||
display.asyncExec( new Runnable() {
|
display.asyncExec( new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -167,7 +167,7 @@ public class SyncDataViewer
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entry point for the example.
|
* The entry point for the example.
|
||||||
* @param args Program arguments.
|
* @param args Program arguments.
|
||||||
|
@ -190,11 +190,11 @@ public class SyncDataViewer
|
||||||
// TODO Exercise 5 - Use the DataGeneratorWithExecutor() instead.
|
// TODO Exercise 5 - Use the DataGeneratorWithExecutor() instead.
|
||||||
final IDataGenerator generator = new DataGeneratorWithThread();
|
final IDataGenerator generator = new DataGeneratorWithThread();
|
||||||
//#else
|
//#else
|
||||||
//# final IDataGenerator generator = new DataGeneratorWithExecutor();
|
//# final IDataGenerator generator = new DataGeneratorWithExecutor();
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
// Create the content provider which will populate the viewer.
|
// Create the content provider which will populate the viewer.
|
||||||
SyncDataViewer contentProvider =
|
SyncDataViewer contentProvider =
|
||||||
new SyncDataViewer(tableViewer, generator);
|
new SyncDataViewer(tableViewer, generator);
|
||||||
tableViewer.setContentProvider(contentProvider);
|
tableViewer.setContentProvider(contentProvider);
|
||||||
tableViewer.setInput(new Object());
|
tableViewer.setInput(new Object());
|
||||||
|
@ -206,7 +206,7 @@ public class SyncDataViewer
|
||||||
if (!display.readAndDispatch())
|
if (!display.readAndDispatch())
|
||||||
display.sleep();
|
display.sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
// The IDataGenerator.shutdown() method is asynchronous, this requires
|
||||||
// using a query again in order to wait for its completion.
|
// using a query again in order to wait for its completion.
|
||||||
Query<Object> shutdownQuery = new Query<Object>() {
|
Query<Object> shutdownQuery = new Query<Object>() {
|
||||||
|
@ -219,10 +219,10 @@ public class SyncDataViewer
|
||||||
try {
|
try {
|
||||||
shutdownQuery.get();
|
shutdownQuery.get();
|
||||||
} catch (Exception e) {}
|
} catch (Exception e) {}
|
||||||
|
|
||||||
// Shut down the display.
|
// Shut down the display.
|
||||||
font.dispose();
|
font.dispose();
|
||||||
display.dispose();
|
display.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -23,14 +23,14 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example of using a DataRequestMonitor to retrieve a result from an
|
* Example of using a DataRequestMonitor to retrieve a result from an
|
||||||
* asynchronous method.
|
* asynchronous method.
|
||||||
*/
|
*/
|
||||||
public class Async2Plus2 {
|
public class Async2Plus2 {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Executor executor = ImmediateExecutor.getInstance();
|
Executor executor = ImmediateExecutor.getInstance();
|
||||||
DataRequestMonitor<Integer> rm =
|
DataRequestMonitor<Integer> rm =
|
||||||
new DataRequestMonitor<Integer>(executor, null) {
|
new DataRequestMonitor<Integer>(executor, null) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -24,11 +24,11 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Hello world" example which uses an asynchronous method to print out
|
* "Hello world" example which uses an asynchronous method to print out
|
||||||
* the result.
|
* the result.
|
||||||
* <p>
|
* <p>
|
||||||
* The main method uses an immediate executor, which executes runnables
|
* The main method uses an immediate executor, which executes runnables
|
||||||
* as soon as they are submitted, in creating its request monitor.
|
* as soon as they are submitted, in creating its request monitor.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class AsyncHelloWorld {
|
public class AsyncHelloWorld {
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ public class AsyncHelloWorld {
|
||||||
System.out.println("Hello world");
|
System.out.println("Hello world");
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 1: - Call the second async. "Hello world 2" method.
|
// TODO Exercise 1: - Call the second async. "Hello world 2" method.
|
||||||
// Hint: Calling an asynchronous method requires passing to it a
|
// Hint: Calling an asynchronous method requires passing to it a
|
||||||
// request monitor. A new request monitor can be constructed with
|
// request monitor. A new request monitor can be constructed with
|
||||||
// a parent RequestMonitor as an argument argument. The parent gets
|
// a parent RequestMonitor as an argument argument. The parent gets
|
||||||
// completed automatically when the lower level request monitor is
|
// completed automatically when the lower level request monitor is
|
||||||
// completed.
|
// completed.
|
||||||
rm.done();
|
rm.done();
|
||||||
//#else
|
//#else
|
||||||
|
@ -53,9 +53,9 @@ public class AsyncHelloWorld {
|
||||||
//# asyncHelloWorld2(rm2);
|
//# asyncHelloWorld2(rm2);
|
||||||
//#endif
|
//#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO: Exercise 1 - Add a second async. "Hello world 2" method.
|
// TODO: Exercise 1 - Add a second async. "Hello world 2" method.
|
||||||
//#else
|
//#else
|
||||||
//# static void asyncHelloWorld2(RequestMonitor rm) {
|
//# static void asyncHelloWorld2(RequestMonitor rm) {
|
||||||
//# System.out.println("Hello world 2");
|
//# System.out.println("Hello world 2");
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* https://www.eclipse.org/legal/epl-2.0/
|
* https://www.eclipse.org/legal/epl-2.0/
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: EPL-2.0
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* Wind River Systems - initial API and implementation
|
* Wind River Systems - initial API and implementation
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -28,8 +28,8 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
|
||||||
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example of using a CountingRequestMonitor to wait for multiple
|
* Example of using a CountingRequestMonitor to wait for multiple
|
||||||
* asynchronous calls to complete.
|
* asynchronous calls to complete.
|
||||||
*/
|
*/
|
||||||
public class AsyncQuicksort {
|
public class AsyncQuicksort {
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ public class AsyncQuicksort {
|
||||||
|
|
||||||
System.out.println("To sort: " + Arrays.toString(array));
|
System.out.println("To sort: " + Arrays.toString(array));
|
||||||
asyncQuicksort(
|
asyncQuicksort(
|
||||||
array, 0, array.length - 1,
|
array, 0, array.length - 1,
|
||||||
new RequestMonitor(fgExecutor, null) {
|
new RequestMonitor(fgExecutor, null) {
|
||||||
@Override
|
@Override
|
||||||
protected void handleCompleted() {
|
protected void handleCompleted() {
|
||||||
|
@ -49,8 +49,8 @@ public class AsyncQuicksort {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asyncQuicksort(final int[] array, final int left,
|
static void asyncQuicksort(final int[] array, final int left,
|
||||||
final int right, final RequestMonitor rm)
|
final int right, final RequestMonitor rm)
|
||||||
{
|
{
|
||||||
if (right > left) {
|
if (right > left) {
|
||||||
int pivot = left;
|
int pivot = left;
|
||||||
|
@ -68,13 +68,13 @@ public class AsyncQuicksort {
|
||||||
countingRm.setDoneCount(2);
|
countingRm.setDoneCount(2);
|
||||||
//#else
|
//#else
|
||||||
//# asyncPartition(
|
//# asyncPartition(
|
||||||
//# array, left, right, pivot,
|
//# array, left, right, pivot,
|
||||||
//# new DataRequestMonitor<Integer>(fgExecutor, rm) {
|
//# new DataRequestMonitor<Integer>(fgExecutor, rm) {
|
||||||
//# @Override
|
//# @Override
|
||||||
//# protected void handleCompleted() {
|
//# protected void handleCompleted() {
|
||||||
//# int newPivot = getData();
|
//# int newPivot = getData();
|
||||||
//# printArray(array, left, right, newPivot);
|
//# printArray(array, left, right, newPivot);
|
||||||
//#
|
//#
|
||||||
//# CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm);
|
//# CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm);
|
||||||
//# asyncQuicksort(array, left, newPivot - 1, countingRm);
|
//# asyncQuicksort(array, left, newPivot - 1, countingRm);
|
||||||
//# asyncQuicksort(array, newPivot + 1, right, countingRm);
|
//# asyncQuicksort(array, newPivot + 1, right, countingRm);
|
||||||
|
@ -89,7 +89,7 @@ public class AsyncQuicksort {
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO Exercise 2 - Convert partition to an asynchronous method.
|
// TODO Exercise 2 - Convert partition to an asynchronous method.
|
||||||
// Hint: a DataRequestMonitor<Integer> should be used to carry the
|
// Hint: a DataRequestMonitor<Integer> should be used to carry the
|
||||||
// return value to the caller.
|
// return value to the caller.
|
||||||
static int partition(int[] array, int left, int right, int pivot)
|
static int partition(int[] array, int left, int right, int pivot)
|
||||||
//#else
|
//#else
|
||||||
|
@ -97,8 +97,8 @@ public class AsyncQuicksort {
|
||||||
//#endif
|
//#endif
|
||||||
{
|
{
|
||||||
int pivotValue = array[pivot];
|
int pivotValue = array[pivot];
|
||||||
array[pivot] = array[right];
|
array[pivot] = array[right];
|
||||||
array[right] = pivotValue;
|
array[right] = pivotValue;
|
||||||
int store = left;
|
int store = left;
|
||||||
for (int i = left; i < right; i++) {
|
for (int i = left; i < right; i++) {
|
||||||
if (array[i] <= pivotValue) {
|
if (array[i] <= pivotValue) {
|
||||||
|
@ -112,7 +112,7 @@ public class AsyncQuicksort {
|
||||||
array[store] = pivotValue;
|
array[store] = pivotValue;
|
||||||
|
|
||||||
//#ifdef exercises
|
//#ifdef exercises
|
||||||
// TODO: Request Monitors Exercise 2 - Return the data to caller using
|
// TODO: Request Monitors Exercise 2 - Return the data to caller using
|
||||||
// a request monitor.
|
// a request monitor.
|
||||||
return store;
|
return store;
|
||||||
//#else
|
//#else
|
||||||
|
|
|
@ -616,7 +616,7 @@ public abstract class AbstractCLaunchDelegate2 extends LaunchConfigurationDelega
|
||||||
if (location != null) {
|
if (location != null) {
|
||||||
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager()
|
String expandedLocation = VariablesPlugin.getDefault().getStringVariableManager()
|
||||||
.performStringSubstitution(location);
|
.performStringSubstitution(location);
|
||||||
|
|
||||||
if (!expandedLocation.isEmpty()) {
|
if (!expandedLocation.isEmpty()) {
|
||||||
return new Path(expandedLocation);
|
return new Path(expandedLocation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -659,7 +659,7 @@ public class MemoryBrowser extends ViewPart
|
||||||
}
|
}
|
||||||
|
|
||||||
label += ' ' + renderingType;
|
label += ' ' + renderingType;
|
||||||
|
|
||||||
|
|
||||||
// Allow the memory block to customize the label. The platform's
|
// Allow the memory block to customize the label. The platform's
|
||||||
// Memory view support this (it was done in the call to
|
// Memory view support this (it was done in the call to
|
||||||
|
|
Loading…
Add table
Reference in a new issue