org.eclipse.dd.examples.dsf.requestmonitor.AsyncHelloWorld |
|
26: public class AsyncHelloWorld { |
Excercise 1: A common
problem in DSF is implementing nested asynchronous methods, this
excercise adds a second-level asynchronous method to
AsyncHelloWorld. Look for comments preceeded with "// TODO Excercise 1" in the org.eclipse.dd.examples.dsf.requestmonitor.AsyncHelloWorld module. |
org.eclipse.dd.examples.dsf.requestmonitor.Async2Plus2 |
|
22: public class Async2Plus2 { |
org.eclipse.dd.examples.dsf.requestmonitor.AsyncQuicksort.asyncQuickSort() |
|
42: static void asyncQuicksort(final int[] array, final int left, |
Excercise 2: Converting a
synchronous method into an asynchronous one, is another common task in
DSF. This excercise converts the AsyncQuicksort.partition()
method into asynchronous AsyncQuicksort.asyncPartition(). Look for comments preceeded with "// TODO Excercise 2" in the org.eclipse.dd.examples.dsf.requestmonitor.AsyncQuicksort module. |
The IDataGenerator interface contains the following two asynchronous
data access methods:
org.eclipse.dd.examples.dsf.dataviewer.IDataGenerator |
|
49: void getCount(DataRequestMonitor<Integer> rm); |
The example is intended to simulate a realistic problem therefore, it can be assumed that these methods do not complete the request monitor immediately, but rather that the requests are completed on a separate thread and with some delay. There are two implementations of this service provided:
org.eclipse.dd.examples.dsf.dataviewer.SyncDataViewer.getElements() | |
59: // Create the query object for reading data count. |
![]() |
Image 1: Sequence diagram of Query use in
getElements(). |
Note: Using the query object requires a great deal of care because calling a blocking method can create performance problems and raises possibility of deadlock. One common deadlock scenario occurs when the get() method is being called by a thread which is itself required for completion of the asynchronous methods called by execute(). |
TODO
?: add a sequence diagram of the deadlock scenario
org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExecutor.addListener() |
|
174: public void addListener(final Listener listener) { |
Note:
It is immediately apparent that this synchronization mechanism
adds a lot of overhead and for such a simple example, it is much less
efficient than using a synchronized section or an atomic
variable. It
is less obvious how this mechanism adds value, however this document is
just a tutorial so the discussion of the merits of the design will be
left out. |
![]() |
![]() |
Image 1: Synchronization using multiple
locks on data. |
Image 2: Synchronization using a single
DSF executor thread. |
org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithThread.run() |
|
139: public void run() { |
In contrast the executor-based generator uses a dedicated method for
servicing the queue, which is called by every method that adds a new
request to the queue:
org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExecutor.serviceQueue() | |
197: private void serviceQueue() { |
Note: When using a single-threaded
executor as the synchronization
method very few other synchronization mechanisms need to be used.
For example the DataGeneratorWithExecutor.fQueue member is just a plain
un-synchronized list. This is true even when using background
threads to perform long-running tasks, as long as these background
threads can call a request monitor when finished. |
Excercise 3: One benefit of
the single-threaded executor concurrency model is that as long as a
method is guaranteed to run in the executor thread, this method may
access and modify any of the variables protected by this
executor. This excercise demonstrates performing a somewhat more
complicated operation on protected state data. Look for comments preceeded with "// TODO Excercise 3" in the org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExcecutor module. |
DSF synchronization annotations defined in
org.eclipse.dd.dsf.concurrent
Note: The DSF synchronization
annotations are no more than a comment intended to help make the code
more understandable and maintainable. Unfortunately, since there
is no compiler enforcment of their presence, it is easy to forget to
add them. |
Excercise 4:
This excercise adds the appropriate synchronization annotations to the
methods and fields of DataProviderWithExecutor. Look for comments preceeded with "// TODO Excercise 4" in the org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExcecutor module. |
Excercise 5: It is all too
easy to get into a deadlock situation. This excercise
purposefully puts the data viewer system into a deadlock. The
deadlock first renders the data viewer unusable, but the main thread
also gets deadlocked when attempting to exit the program. Look for comments preceeded with "// TODO Excercise 5" in the org.eclipse.dd.examples.dsf.dataviewer.SyncDataViewer module. |
org.eclipse.dd.examples.dsf.requestmonitor.Async2Plus2 |
|
|
|
Excercise abc: xyz |