From 86e9c84f412764a7375621958377d25ae6e3a462 Mon Sep 17 00:00:00 2001 From: Pawel Piech Date: Sat, 1 Mar 2008 00:43:50 +0000 Subject: [PATCH] [220446] Updated the "DSF Common Patterns" document. --- .../docs/common/dsf_common_patterns.html | 837 ++++++++++++++++++ .../docs/common/query_1.dia | Bin 0 -> 2247 bytes .../docs/common/query_1.png | Bin 0 -> 14759 bytes .../docs/common/synchronization_1.dia | Bin 0 -> 1487 bytes .../docs/common/synchronization_1.png | Bin 0 -> 4228 bytes .../docs/common/synchronization_2.dia | Bin 0 -> 1501 bytes .../docs/common/synchronization_2.png | Bin 0 -> 6076 bytes .../docs/pda/dsf_common_patterns.html | 159 ---- 8 files changed, 837 insertions(+), 159 deletions(-) create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/dsf_common_patterns.html create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.dia create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/query_1.png create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.dia create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_1.png create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.dia create mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/common/synchronization_2.png delete mode 100644 plugins/org.eclipse.dd.doc.dsf/docs/pda/dsf_common_patterns.html 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:
+
    +
  1. Download and install Eclipse development environment, either the Eclipse Classic 3.4 or Eclipse IDE for C/C++ Developers
    +
  2. +
  3. Install the DSF SDK feature to build against, by performing +either:
    +
  4. +
      +
    1. 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.
    2. +
    3. 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.
    4. +
    +
  5. Check out the org.eclipse.dd.examples.dsf +plugin, found /cvsroot/dsdp +under org.eclipse.dd.dsf/plugins +directory.
  6. +
  7. Build the examples plugin:
  8. +
      +
    1. Execute the build the first time to build and run the +excercises preprocessor.
    2. +
    3. 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.
    4. +
    5. Build the plugin again to compile the generated sources.
    6. +
    +
  9. Launch the examples
  10. +
      +
    1. 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.
    2. +
    3. TODO: Launching timers +example
    4. +
    +
+

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:
+ +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: }
+
+
+ +

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: }
+
+
+ + + + + + + +
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:

+
    +
  1. DataGeneratorWithThread - Uses a java thread directly and various +synchronization mechanisms for data integrity.
    +
  2. +
  3. DataGeneratorWithExecutor - Uses a DSF executor for both +asynchronous execution and synchronization.
  4. +
+There are also two viewers provided which display data from the data +generator:
+
    +
  1. SyncDataViewer - Table-based viewer which implements a +synchronous IStructuredContentProvider interface.
    +
  2. +
  3. AsyncDataViewer - Table-based viewer which implements an +asynchronous ILazyContentProvider interface.
  4. +
+

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: }
+
+
+ + + + + + + + + + +

+
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: }
+
+
+ + + + + + + +
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: }
+
+
+ +

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: }
+
+
+ + + + + + + +
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
+

+ +
+ + + + + + +
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 0000000000000000000000000000000000000000..68078a3d47b921de5a29d5f1f6bcc7afe7d74e90 GIT binary patch literal 2247 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

I(t<*Ctpi`J<(Ru&oEMEHKe=|##U*~E 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8a725e36e02f3d70927cd23d55ecac769299f4ac GIT binary patch literal 1501 zcmV<31tR(%iwFP!000001MOSeZrer>efL)o@~gAr-pJiJc915$JQQt#B+tT%TuWP1 zq(D-Z)rWq2XGx{jjk=JcP^T1N113guc7`)&4`=Cj@1G};^Q6)}`C__dQsKw`Ua?tPWndJK z?yovBoU3opKQEwmCOpQvoXsJ%gO0*!^^@&mxW6& z3um&yG)ePRnS2{^m?V)_afzCzGhH7i3seLpwlAy(Q9PJDPY$gAK}Fdy0hE{j?Y2`p zca)lNf8(xMRCt-2Fdq+|TS`~yebJKlCzF|Bq<5{}#QE9WFV5qB^X?Sv{qpsO)lhn? z+#W)qx#p*D52Kk0b#|c4)@>?0jhANqLs{RnJ2o-prH#$HfQZyWr%U%gylm6X@&+#% zXC({C@J}7&%kVy$EJ&O;&aX-E*n80&pg2r;*ZbXFPtImI;0kzeD?8KVrGz;02_`o_ zl7v#Z8TdABRKW~~n`>f?<;2Ok%JM~|Hvx1!n=Eh47NPCj z+D^(}WTu00lA6DgI9Ji$;5M|z$uK}?xe3kyQeG^Hvx-SS0~v)X4S`HQq`?j@#f`a? zA(!7^im(v8O(vzlnLuYQ;Xb=11aV@Slp~-VS`Rl!;&`Cru!yEcj8%pb`Lu2>f?4{c z2cgLz_CQy&lRymO$F8856GnMmJP3cF(lnV@_ZuM%T@NB1kM>h-)72j)bAE|#B8|Jr zL)7E=29yG29%)yZ2=4|9x^r&F%HWjtOGwBn; zT}CMONY_-YH`UKNnP~V{0A2NU`sPzIkD~ zN?Btnm6m5bBwA+DB@FR}1l?~1wnyPPfcP%1$)mZ=$bnJehD}v-6lW`Ib{oeqKR)YV zmP03g8AG*(6=yPg2ANeQ1qHhc*IsuX)Wk#!Se}Zro>R0{v4@sl{Y6Jl+Lq#KKb^jU zEzaJ_rDB6iSu@b}l03dF>tLfrZqS4wq!8kCB1W>-gz%{IsJcJAQhF{Ny#} zC#b(0j1g;@p9&ZkNy|@|At{+fm9K)H{z#J?!qLtrl`E&?r`GvtXH9ne^q=FW-*i4t z(np}D&+vSqMtaA*%s<0CS`^1FKBcWv6yUfP#}l-eM!SraWhfgBmJUzLng@8yw2UB3 zr62;6a*Ty>tJ5-$eFh2SL^6zhzdI%Gre$ZCmR)k&?>73@H+uVO5R+CIdVG~+zlXgZ zUv97eZfD5H2n=zCSMiv4g9)Of-De=c!4`)U$K4<_m=wkFoZzzM7x9_~*a?hIU~~eb z6Bw^eV0Z}lLE3lp2;-f==mbU$fg#Uu21Gq>RW9>s%cnpTmq3Ja`>sFdc80+ap)Joa z&Jbd!F*=RWX^c)|yfTeJfb*ywVo*e7H^lgVYmD;m;$IK%uh#xI@&4)`P;Ajozd!&0 DR-NLU literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..63124ecdf1bbaf7cb07030244c378ef5487d7c9b GIT binary patch literal 6076 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 - - - 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

- -