diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/dsf_common_patterns.html b/plugins/org.eclipse.dd.doc.dsf/docs/common/dsf_common_patterns.html
new file mode 100644
index 00000000000..79f481f79fb
--- /dev/null
+++ b/plugins/org.eclipse.dd.doc.dsf/docs/common/dsf_common_patterns.html
@@ -0,0 +1,837 @@
+
+
+
+ DSF Common Patterns
+
+
+DSF Common Patterns
+
+Summary
+Examples
+
+Running example code is and performing included excercises is very
+helpful in following this tutorial. In order to run the examples
+in this tutorial the following is needed:
+
+ - Download and install Eclipse development environment, either the Eclipse Classic 3.4 or Eclipse IDE for C/C++ Developers
+
+ - Install the DSF SDK feature to build against, by performing
+either:
+
+
+ - Using update manager, install the Debugger Services Framework end-user and
+extender SDK, found in the Ganymede
+Discovery Site under Remote
+Access and Device Development.
+ - Check out org.eclipse.dd.dsf
+and org.eclipse.dd.dsf.ui plugins, found in the /cvsroot/dsdp repository under org.eclipse.dd.dsf/plugins
+directory.
+
+ - Check out the org.eclipse.dd.examples.dsf
+plugin, found /cvsroot/dsdp
+under org.eclipse.dd.dsf/plugins
+directory.
+ - Build the examples plugin:
+
+ - Execute the build the first time to build and run the
+excercises preprocessor.
+ - Refresh the resources in the plugin (right-click on project in Navigator and select Refresh), in order to recognize the
+sources generated by the preprocessor.
+ - Build the plugin again to compile the generated sources.
+
+ - Launch the examples
+
+ - Examples in data org.eclipse.dd.examples.dsf.requestmonitor and
+org.eclipse.dd.examples.dsf.dataviewer packages each contain a public
+main() function. They can be launched using the Java Application
+launch type.
+ - TODO: Launching timers
+example
+
+
+Asynchronous Methods
+One of the central features of DSF is that it relies very heavily on
+the use of asynchronous methods. Asynchronous methods here mean
+simply methods that use a callback
+object to indicate their completion. The use of asynchronous
+methods can be very contageous in a system, where if a lower level API
+is composed of asynchronous methods, a higher level system which uses
+those methods also has to have asynchronous methods in its interface
+(or risk blocking its calling thread).
+
+TODO? :
+diagram of a layered system with asynchronous APIs
+Request Monitor
+There is a standard callback object used in DSF, the request
+monitor. A request monitor has the following features:
+
+ - Executor - A
+argument to the request monitor constructor allows the user to specify
+what executor should be used to invoke the callback method.
+
+ - Status -
+Asynchronous methods that take a callback can always set the status
+indicating the success or failure of the call.
+ - Callback Methods
+- The request monitor declares several protected methods which are
+invoked when the callback is invoked: handleCompleted(), handleOK(),
+handleError(), etc. The users may override these methods as
+needed to perform additional processing upon asynchronous method
+completion.
+ - Parent Request Monitor
+- If the method calling an asynchronous method is itself asynchronous,
+it may set its argument request monitor as the parent of the request
+monitor it is creating. The parent request monitor will be
+automatically invoked when the lower level request monitor is completed.
+
+Following is the snippet from a the
+"hello world" example of using a
+request monitor:
+
+
+
+
+ org.eclipse.dd.examples.dsf.requestmonitor.AsyncHelloWorld
+ |
+
+
+
+ |
+
+ 26: public class AsyncHelloWorld {
28: public static void main(String[] args) { 29: Executor executor = ImmediateExecutor.getInstance(); 30: RequestMonitor rm = new RequestMonitor(executor, null); 31: asyncHelloWorld(rm); 32: }
34: static void asyncHelloWorld(RequestMonitor rm) { 35: System.out.println("Hello world"); 36: rm.done(); 37: }
+ |
+
+
+
+
+
+
+
+
+
+
+ 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.
+ |
+
+
+
+
+Data Request Monitor
+The base request monitor is useful for returning
+status of the
+asynchronous method, but they do not have an option of returning a
+value to the caller. DataRequestMonitor can be used for that
+purpose. A simple example of using the data request monitor:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.requestmonitor.Async2Plus2
+ |
+
+
+
+ |
+
+ 22: public class Async2Plus2 { 23: 24: public static void main(String[] args) { 25: Executor executor = ImmediateExecutor.getInstance(); 26: DataRequestMonitor<Integer> rm = 27: new DataRequestMonitor<Integer>(executor, null) { 28: @Override 29: protected void handleCompleted() { 30: System.out.println("2 + 2 = " + getData()); 31: } 32: }; 33: asyncAdd(2, 2, rm); 34: }
36: static void asyncAdd(int value1, int value2, DataRequestMonitor<Integer> rm) { 37: rm.setData(value1 + value2); 38: rm.done(); 39: } 40: }
+ |
+
+
+
+
+
+ - Lines 26-27 create the data request monitor using a local class
+declaraion. Note the type parameter to DataRequestMonitor allows
+for compiler checking of the type when calling getData() and setData()
+methods.
+ - Lines 29-31 override the standard callback to print the result of
+the calculation to the console.
+
+
+Multi-Request Monitor
+A common problem when using asynchronous is that several asynchronous
+methods need to be called in parallel, so the calling method needs to
+somehow manage the completion of several request monitors.
+CountingRequestMonitor can be used for this purpose. It is
+configured such that it's done() method needs to be called a count number of times before the
+callback method is invoked.
+The following snipped from the AsyncQuicksort example shows a simple
+example of using the CountingRequestMonitor:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.requestmonitor.AsyncQuicksort.asyncQuickSort()
+ |
+
+
+
+ |
+
+ 42: static void asyncQuicksort(final int[] array, final int left, 43: final int right, final RequestMonitor rm) 44: { 45: if (right > left) { 46: int pivot = left; 48: int newPivot = partition(array, left, right, pivot); 49: printArray(array, left, right, newPivot);
51: CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm); 52: asyncQuicksort(array, left, newPivot - 1, countingRm); 53: asyncQuicksort(array, newPivot + 1, right, countingRm); 54: countingRm.setDoneCount(2); 55: } else { 56: rm.done(); 57: } 58: }
+ |
+
+
+
+
+
+ - Line 50 creates the CountingRequestMonitor. Note that the
+parent request monitor is set to the request monitor from the
+asyncQuicksort() argument. This parent request monitor is
+automatically called when the counting request monitor is completed.
+ - Lines 51 and 52, use the same instance of counting request
+monitor when calling the sub-routine. Each sub-routine will call
+done() on the counting request monitor.
+ - Line 53 sets the count to the number of sub-routines called with
+the counting request monitor. Note that the done count can be set
+after calling the sub-routines, because the counting request monitor
+will not be completed until the count is set.
+
+ - Line 55 Don't forget to complete the request monitor in all
+execution paths!
+
+
+
+
+ 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.
+ |
+
+
+
+Concurrency
+The simple examples in previous section used asynchronous method
+signatures, however no real asynchronous work was performed since all
+execution was performed in the main thread. This section examines
+a more typical example of a problem that DSF is intended to solve: a
+viewer and an asynchronous data generator.
+The IDataGenerator interface contains the following two asynchronous
+data access methods:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.dataviewer.IDataGenerator
+ |
+
+
+
+ |
+
+ 49: void getCount(DataRequestMonitor<Integer> rm); 50: void getValue(int index, DataRequestMonitor<String> 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:
+
+ - DataGeneratorWithThread - Uses a java thread directly and various
+synchronization mechanisms for data integrity.
+
+ - DataGeneratorWithExecutor - Uses a DSF executor for both
+asynchronous execution and synchronization.
+
+There are also two viewers provided which display data from the data
+generator:
+
+ - SyncDataViewer - Table-based viewer which implements a
+synchronous IStructuredContentProvider interface.
+
+ - AsyncDataViewer - Table-based viewer which implements an
+asynchronous ILazyContentProvider interface.
+
+Query
+DSF is designed to facilitate use of asynchronous APIs. However,
+sometimes there are situations where a synchronous method has to be
+implemented to call an asynchronous method. One utility used to
+accomplish this is a DSF Query object. The Query object is meant
+to be extended by clients in order to override the asynchronous
+execute() method. The client code using a query can use the execute()
+implementation in order to call other asynchronous methods. The
+following snippet
+from SyncDataViewer.getElements() shows the use of Query:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.dataviewer.SyncDataViewer.getElements()
+ |
+
+
+
+ |
+
+ 59: // Create the query object for reading data count. 60: Query<Integer> countQuery = new Query<Integer>() { 61: @Override 62: protected void execute(DataRequestMonitor<Integer> rm) { 63: fDataGenerator.getCount(rm); 64: } 65: }; 66: 67: // Submit the query to be executed. A query implements a runnable 68: // interface and it has to be executed in order to do its work. 69: ImmediateExecutor.getInstance().execute(countQuery); 70: int count = 0; 71: 72: // Block until the query completes, which will happen when the request 73: // monitor of the execute() method is marked done. 74: try { 75: count = countQuery.get(); 76: } catch (Exception e) { 77: // InterruptedException and ExecutionException can be thrown here. 78: // ExecutionException containing a CoreException will be thrown 79: // if an error status is set to the Query's request monitor. 80: return new Object[0]; 81: }
+ |
+
+
+
+
+
+ - Line 60 creates the query object.
+
+ - On line 63, inside the execute() method, the asynchronous
+getCount() method is called
+ - Line 69 submits the query to an executor. This is very
+important, because a Query object simply implements Runnable, it will
+not perform the work in its exectute() method unless it is submitted to
+an executor.
+
+ - Line 75 blocks while calling the
+java.util.concurrent.Future.get() method, implemented by Query, until
+the request monitor from the execute() method is completed.
+
+
+
+
+ 
+ |
+
+
+ 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
+
+
+Synchronization
+Managing race conditions and deadlocks is one of the most challanging
+problems of large multi-threaded systems. DSF uses a
+single-threaded executor as the primary mechanism for safe-guarding
+access to data. Methods, which need to access data protected by
+the DSF executor, have to access this data inside a runnable submitted
+to the executor thread. The following is an example of this from
+the DataGeneratorWithExecutor:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExecutor.addListener()
+ |
+
+
+
+ |
+
+ 174: public void addListener(final Listener listener) { 175: try { 176: fExecutor.execute( new DsfRunnable() { 177: public void run() { 178: fListeners.add(listener); 179: } 180: }); 181: } catch (RejectedExecutionException e) {} 182: }
+ |
+
+
+
+
+
+ - Line 174 declares the addListener() method which can be called on
+any thread.
+ - Line 176 submits a local runnable to the DSF executor.
+ - Line 178 accesses the protected data: fListeners.
+
+
+
+
+ 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.
+ |
+
+
+
+Comparing other parts of the two data generator implementation shows
+that using the synchronization mechanism above is the principal
+difference between the two implementations. One notable exception
+is the principal processing loop in each data generator. In the
+thread-based implementation this loop is implemented in the run method
+of the generator's thread:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithThread.run()
+ |
+
+
+
+ |
+
+ 139: public void run() { 140: try { 141: while(true) { 142: // Get the next request from the queue. The time-out 143: // ensures that that the random changes get processed. 144: final Request request = fQueue.poll(100, TimeUnit.MILLISECONDS); 145: 146: // If a request was dequeued, process it. 147: if (request != null) { 148: // Simulate a processing delay. 149: Thread.sleep(PROCESSING_DELAY); 150: 151: if (request instanceof CountRequest) { 152: processCountRequest((CountRequest)request); 153: } else if (request instanceof ItemRequest) { 154: processItemRequest((ItemRequest)request); 155: } else if (request instanceof ShutdownRequest) { 156: // If shutting down, just break out of the while(true) 157: // loop and thread will exit. 158: request.fRequestMonitor.done(); 159: break; 160: } 161: } 162: 163: // Simulate data changes. 164: randomChanges(); 165: } 166: } 167: catch (InterruptedException x) {} 168: }
+ |
+
+
+
+
+
+ - Line 141 creates the loop that runs continuously until the break
+statement on line 159.
+ - Line 149 implements the artcificial processing delay that is
+executed for each request.
+
+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() { ... 201: // If a queue servicing is already scheduled, do nothing. 202: if (fServiceQueueInProgress) { 203: return; 204: } 205: 206: if (fQueue.size() != 0) { 207: // If there are requests to service, remove one from the queue and 208: // schedule a runnable to process the request after a processing 209: // delay. 210: fServiceQueueInProgress = true; 211: final Request request = fQueue.remove(0); 212: fExecutor.schedule( 213: new DsfRunnable() { 214: public void run() { 215: if (request instanceof CountRequest) { 216: processCountRequest((CountRequest)request); 217: } else if (request instanceof ItemRequest) { 218: processItemRequest((ItemRequest)request); 219: } 220: 221: // Reset the processing flag and process next 222: // request. 223: fServiceQueueInProgress = false; 224: serviceQueue(); 225: } 226: }, 227: PROCESSING_DELAY, TimeUnit.MILLISECONDS); 228: } 229: }
+ |
+
+
+
+
+
+ - On line 202, the fServiceQueueInProgress flag is used to ensure
+that the queue servicing runnable is not scheduled too often.
+ - Line 211 removes the top request from the queue.
+
+ - Line 212 calls the ExecutorService.schedule() method to run the
+queue servicing runnable, with a delay that simulates the request
+processing time.
+ - Line 224, after servicing runnableis finished, calls
+serviceQueue() again to process the next item in the queue.
+
+
+
+
+ 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.
+ |
+
+
+
+Annotations
+In any multi-threaded system it can become very difficult to determine
+what are the rules governing access to the various data objects.
+In a DSF system, it is even more important to identify which data
+objects can only be accessed using a designated DSF executor.
+Since there is no Java language mechanisms for this purpose, DSF
+defines a number annotations that can be used for this purpose.
+The annotations are hierarchical, so that if a class has a given
+annotation in its declaration, its members and fields are assumed to
+have the same access restriction unless otherwise specified.
+DSF synchronization annotations defined in
+org.eclipse.dd.dsf.concurrent
+
+
+ - ThreadSafe -
+Indicates that the given element can be accessed on any thread.
+Typically, if this annotation is used, the given member or class uses
+syncrhonized or atomic objects to protect its data.
+ - Immutable -
+Immutable objects cannot be modified after they are created, thus they
+are also thread-safe. The easiest way to make an object
+immutable, is to declare all its fields final and make sure that its
+fields are also immutable. Examples of immutable objects are Java
+Strings, primitive object types, etc.
+ - ConfinedToDsfExecutor(executor)
+- Indicates that the given object can only be accessed using the given
+executor. The executor parameter is a string (since that's the
+only allowable parameter type to annotations), but it should indicate
+the executor, using classe's member and method names.
+ - ThreadSafeAndProhibitedFromDsfExecutor(executor)
+- Rarely used, it indicates that the given element can be accessed on
+any thread except using the given executor. An example of such a
+method would be the SyncDataViewer.getElements() method, which should
+never be called using the executor belonging to the data provider.
+
+
+
+
+
+
+ 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.
+ |
+
+
+
+Services
+OSGi
+Session
+Tracker
+Data Model
+View Model
+Adapter, Provider, Node
+Timers
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.requestmonitor.Async2Plus2
+ |
+
+
+
+ |
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+ Excercise abc: xyz |
+
+
+
+
+
+
+
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.dia b/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.dia
new file mode 100644
index 00000000000..68078a3d47b
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.dia differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.png b/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.png
new file mode 100644
index 00000000000..e5563fcb6f2
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.png differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.dia b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.dia
new file mode 100644
index 00000000000..6d523d8702b
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.dia differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.png b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.png
new file mode 100644
index 00000000000..181a77f4401
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.png differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.dia b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.dia
new file mode 100644
index 00000000000..8a725e36e02
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.dia differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.png b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.png
new file mode 100644
index 00000000000..63124ecdf1b
Binary files /dev/null and b/plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.png differ
diff --git a/plugins/org.eclipse.dd.doc.dsf/docs/pda/dsf_common_patterns.html b/plugins/org.eclipse.dd.doc.dsf/docs/pda/dsf_common_patterns.html
deleted file mode 100644
index da0a8d99b5b..00000000000
--- a/plugins/org.eclipse.dd.doc.dsf/docs/pda/dsf_common_patterns.html
+++ /dev/null
@@ -1,159 +0,0 @@
-
-
-
- DSF Common Patterns
-
-
-DSF Common Patterns
-
-Summary
-DSF
-
- - Customizing, componentization, performance.
-
-Asynchronous Methods
-One of the central features of DSF is that it relies very heavily on
-the use of asynchronous methods. Asynchronous methods here mean
-simply methods that use a callback
-object to indicate their completion. The use of asynchronous
-methods can be very contageous in a system, where if a lower level API
-is composed of asynchronous methods, a higher level system which uses
-those methods also has to have asynchronous methods in its interface
-(or risk blocking its calling thread).
-
-TODO? : diagram of a layered system with asynchronous APIs
-Request Monitor
-There is a standard callback object used in DSF, the request
-monitor. A request monitor has the following features:
-
- - Executor - A
-argument to the request monitor constructor allows the user to specify
-what executor should be used to invoke the callback method.
-
- - Status -
-Asynchronous methods that take a callback can always set the status
-indicating the success or failure of the call.
- - Callback Methods
-- The request monitor declares several protected methods which are
-invoked when the callback is invoked: handleCompleted(), handleOK(),
-handleError(), etc. The users may override these methods as
-needed to perform additional processing upon asynchronous method
-completion.
- - Parent Request Monitor
-- If the method calling an asynchronous method is itself asynchronous,
-it may set its argument request monitor as the parent of the request
-monitor it is creating. The parent request monitor will be
-automatically invoked when the lower level request monitor is completed.
-
-Following is the snippet from a the "hello world" example of using a
-request monitor:
- 26: public class AsyncHelloWorld {
28: public static void main(String[] args) {
29: Executor executor = ImmediateExecutor.getInstance();
30: RequestMonitor rm = new RequestMonitor(executor, null);
31: asyncHelloWorld(rm);
32: }
34: static void asyncHelloWorld(RequestMonitor rm) {
35: System.out.println("Hello world");
36: rm.done();
37: }
-
- - Line 29 creates an "immediate executor". Unlike more
-sophisticated executors, the immediate executor simply invokes the
-runnable it receives immediately. It does not use any threads and
-it will never throw a RejectedExecutionException.
- - Line 30 creates the request monitor. This program does not
-perform any processing after the callback is invoked, so it does not
-override RequestMonitor's completion methods.
- - Line 36 marks the callback as completed and implicilty invokes
-the callback method. As a contract with the caller, the
-asynchronous method has to invoke done() when its finished. As
-there is no compiler support for ensuring that the asynchronous method
-completes the request monitor, failure to do so results in common
-but often suble and difficult to track down bugs.
-
-
-Data Request Monitor
-The base request monitor is useful for returning status of the
-asynchronous method, but they do not have an option of returning a
-value to the caller. DataRequestMonitor can be used for that
-purpose. A simple example of using the data request monitor:
- 22: public class Async2Plus2 {
24: public static void main(String[] args) {
25: Executor executor = ImmediateExecutor.getInstance();
26: DataRequestMonitor<Integer> rm =
27: new DataRequestMonitor<Integer>(executor, null) {
28: @Override
29: protected void handleCompleted() {
30: System.out.println("2 + 2 = " + getData());
31: }
32: };
33: asyncAdd(2, 2, rm);
34: }
36: static void asyncAdd(int value1, int value2, DataRequestMonitor<Integer> rm) {
37: rm.setData(value1 + value2);
38: rm.done();
39: }
40: }
-
- - Lines 26-27 create the data request monitor using a local class
-declaraion. Note the type parameter to DataRequestMonitor allows
-for compiler checking of the type when calling getData() and setData()
-methods.
- - Lines 29-31 override the standard callback to print the result of
-the calculation to the console.
-
-
-Multi-Request Monitor
-A common problem when using asynchronous is that several asynchronous
-methods need to be called in parallel, so the calling method needs to
-somehow manage the completion of several request monitors.
-CountingRequestMonitor can be used for this purpose. It is
-configured such that it's done() method needs to be called a count number of times before the
-callback method is invoked.
-The following snipped from the AsyncQuicksort example shows a simple
-example of using the CountingRequestMonitor:
- 42: static void asyncQuicksort(final int[] array, final int left,
43: final int right, RequestMonitor rm)
44: {
45: if (right > left) {
46: int pivot = left;
47: int newPivot = partition(array, left, right, pivot);
48: printArray(array, left, right, newPivot);
49:
50: CountingRequestMonitor countingRm = new CountingRequestMonitor(fgExecutor, rm);
51: asyncQuicksort(array, left, newPivot - 1, countingRm);
52: asyncQuicksort(array, newPivot + 1, right, countingRm);
53: countingRm.setDoneCount(2);
54: } else {
55: rm.done();
56: }
57: }
-
- - Line 50 creates the CountingRequestMonitor. Note that the
-parent request monitor is set to the request monitor from the
-asyncQuicksort() argument. This parent request monitor is
-automatically called when the counting request monitor is completed.
- - Lines 51 and 52, use the same instance of counting request
-monitor when calling the sub-routine. Each sub-routine will call
-done() on the counting request monitor.
- - Line 53 sets the count to the number of sub-routines called with
-the counting request monitor. Note that the done count can be set
-after calling the sub-routines, because the counting request monitor
-will not be completed until the count is set.
-
- - Line 55 Don't forget to complete the request monitor in all
-execution paths!
-
-
-Non-Executor Thread
-Future
-Query
-Concurrency Annotations
-
-Services
-OSGi
-Session
-Tracker
-Data Model
-View Model
-Adapter, Provider, Node
-Timers
-
-