/******************************************************************************* * Copyright (c) 2008, 2009 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ //#ifdef exercises package org.eclipse.cdt.examples.dsf.dataviewer; //#else //#package org.eclipse.cdt.examples.dsf.dataviewer.answers; //#endif import java.util.Set; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.Query; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** * Data viewer based on a table, which reads data using synchronous methods. * <p> * This viewer implements the {@link IStructuredContentProvider} interface * which is used by the JFace TableViewer class to populate a Table. This * interface contains one principal methods for reading data {@link #getElements(Object)}, * which synchronously returns an array of elements. In order to implement this * method using the asynchronous data generator, this provider uses the * {@link Query} object. * </p> */ public class SyncDataViewer implements IStructuredContentProvider, IDataGenerator.Listener { // The viewer and generator that this content provider using. final private TableViewer fViewer; final private IDataGenerator fDataGenerator; public SyncDataViewer(TableViewer viewer, IDataGenerator generator) { fViewer = viewer; fDataGenerator = generator; fDataGenerator.addListener(this); } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // Not used } public Object[] getElements(Object inputElement) { // Create the query object for reading data count. Query<Integer> countQuery = new Query<Integer>() { @Override protected void execute(DataRequestMonitor<Integer> rm) { fDataGenerator.getCount(rm); } }; // Submit the query to be executed. A query implements a runnable // interface and it has to be executed in order to do its work. ImmediateExecutor.getInstance().execute(countQuery); int count = 0; // Block until the query completes, which will happen when the request // monitor of the execute() method is marked done. try { count = countQuery.get(); } catch (Exception e) { // InterruptedException and ExecutionException can be thrown here. // ExecutionException containing a CoreException will be thrown // if an error status is set to the Query's request monitor. return new Object[0]; } // Create the array that will be filled with elements. // For each index in the array execute a query to get the element at // that index. final Object[] elements = new Object[count]; for (int i = 0; i < count; i++) { final int index = i; Query<String> valueQuery = new Query<String>() { @Override protected void execute(DataRequestMonitor<String> rm) { fDataGenerator.getValue(index, rm); } }; ImmediateExecutor.getInstance().execute(valueQuery); try { elements[i] = valueQuery.get(); } catch (Exception e) { elements[i] = "error"; } } return elements; } public void dispose() { fDataGenerator.removeListener(this); } public void countChanged() { // For any event from the generator, refresh the whole viewer. refreshViewer(); } public void valuesChanged(Set<Integer> indexes) { // For any event from the generator, refresh the whole viewer. refreshViewer(); } private void refreshViewer() { //#ifdef exercises // TODO Exercise 5 - Add a call to getElements() to force a deadlock. //#else //# getElements(null); //#endif // This method may be called on any thread, switch to the display // thread before calling the viewer. Display display = fViewer.getControl().getDisplay(); display.asyncExec( new Runnable() { public void run() { if (!fViewer.getControl().isDisposed()) { fViewer.refresh(); } } }); } public static void main(String[] args) { // Create the shell to hold the viewer. Display display = new Display(); Shell shell = new Shell(display, SWT.SHELL_TRIM); shell.setLayout(new GridLayout()); GridData data = new GridData(GridData.FILL_BOTH); shell.setLayoutData(data); Font font = new Font(display, "Courier", 10, SWT.NORMAL); // Create the table viewer. TableViewer tableViewer = new TableViewer(shell, SWT.BORDER); tableViewer.getControl().setLayoutData(data); // Create the data generator. //#ifdef exercises // TODO Exercise 5 - Use the DataGeneratorWithExecutor() instead. final IDataGenerator generator = new DataGeneratorWithThread(); //#else //# final IDataGenerator generator = new DataGeneratorWithExecutor(); //#endif // Create the content provider which will populate the viewer. SyncDataViewer contentProvider = new SyncDataViewer(tableViewer, generator); tableViewer.setContentProvider(contentProvider); tableViewer.setInput(new Object()); // Open the shell and service the display dispatch loop until user // closes the shell. shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } // The IDataGenerator.shutdown() method is asynchronous, this requires // using a query again in order to wait for its completion. Query<Object> shutdownQuery = new Query<Object>() { @Override protected void execute(DataRequestMonitor<Object> rm) { generator.shutdown(rm); } }; ImmediateExecutor.getInstance().execute(shutdownQuery); try { shutdownQuery.get(); } catch (Exception e) {} // Shut down the display. font.dispose(); display.dispose(); } }