From e75b2b1a1fbddb4af76ceca3dbe9129dbf98efcc Mon Sep 17 00:00:00 2001
From: Pawel Piech Look
-for comments preceeded with "// TODO Excercise 1" in the
+for comments preceded with "// TODO Exercise 1" in the
org.eclipse.dd.examples.dsf.requestmonitor.AsyncHelloWorld
module. Look
-for comments preceeded with "// TODO Excercise 2" in the
+for comments preceeded with "// TODO Exercise 2" in the
org.eclipse.dd.examples.dsf.requestmonitor.AsyncQuicksort
module. Look
-for comments preceeded with "// TODO Excercise 3" in the
+for comments preceeded with "// TODO Exercise 3" in the
org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExcecutor
module. Excercise 4:
+ Exercise 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
+for comments preceeded with "// TODO Exercise 4" in the
org.eclipse.dd.examples.dsf.dataviewer.DataGeneratorWithExcecutor
module. Look
-for comments preceeded with "// TODO Excercise 5" in the
+for comments preceeded with "// TODO Exercise 5" in the
org.eclipse.dd.examples.dsf.dataviewer.SyncDataViewer
module. Starting up a large number of DSF services requires calling a number
of asynchronous method in a pre-defined sequence. Implementing
-this startup code can be cumbersome and DSF provides a quitility for
+this startup code can be cumbersome and DSF provides a utility for
implementing it: org.eclipse.dd.dsf.concurrent.Sequence. Here's
@@ -1247,7 +1329,7 @@ custom request monitor to be invoked at the completion of the sequence. TODO: add a diagram of the
-adapter pattern used by multiple views. To overcome the adapter pattern limitation, the View Model uses
+adding a new view can force changing a large number of modules.
+DSF Common Patterns
+DSF Common Patterns
-
Summary
-Examples
+
+
+
+1 Introduction
+This document contains a tutorial for the basic features of the
+Debugger Services Framework (DSF), created by the DSDP Device Debugging
+project.
+2 Examples
-Running example code is and performing included excercises is very
+Running example code is and performing included exercises is very
helpful in following this tutorial. In order to run the examples
in this tutorial the following is needed:
@@ -39,7 +98,7 @@ directory.
-
-
+ Asynchronous Methods
+3 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
+methods can be very contagious 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
+(or risk blocking its calling thread).
+3.1 Request Monitor
There is a standard callback object used in DSF, the request
monitor. A request monitor has the following features:
@@ -137,13 +197,30 @@ program does not
perform any processing after the callback is invoked, so it does not
override RequestMonitor's completion methods.
+
+
+
+
+
+
+
+
+
+Image 1: Sequence diagram of the
+AsyncHelloWorld example.
+
+
@@ -151,12 +228,12 @@ but often suble and difficult to track down bug
Excercise 1: A common
+ style="text-decoration: underline;">Exercise 1: A common
problem in DSF is implementing nested asynchronous methods, this
-excercise adds a second-level asynchronous method to
+exercise adds a second-level asynchronous method to
AsyncHelloWorld.
@@ -164,7 +241,8 @@ module.
-Data Request Monitor
+3.2 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
@@ -214,7 +292,8 @@ methods.
the calculation to the console.
-Multi-Request Monitor
+3. 4 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.
@@ -279,19 +358,19 @@ execution paths!
-Excercise 2: Converting a
+ style="text-decoration: underline;">Exercise 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().
Concurrency
+4 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
@@ -343,7 +422,7 @@ synchronous IStructuredContentProvider interface.
Query
+4.1 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
@@ -418,7 +497,7 @@ the request monitor from the execute() method is completed.
@@ -440,7 +519,7 @@ for completion of the asynchronous methods called by execute().
Image 1: Detailed sequence of calling
+ style="font-weight: bold;">Image 2: Detailed sequence of calling
IDataGenerator.getCount() in SyncDataViewer.getElements().
Synchronization
+4.2 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
@@ -513,11 +592,11 @@ left out.
@@ -668,21 +747,21 @@ threads can call a request monitor when finished.Image 2: Synchronization using multiple
+ style="font-weight: bold;">Image 3: Synchronization using multiple
locks on data.
Image 3: Synchronization using a single
+ style="font-weight: bold;">Image 4: Synchronization using a single
DSF executor thread.
-Excercise 3: One benefit of
+ style="text-decoration: underline;">Exercise 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.
Annotations
+4.3 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
@@ -742,12 +821,12 @@ add them.
-
@@ -763,20 +842,21 @@ module.
-Excercise 5: It is all too
+ style="text-decoration: underline;">Exercise 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.
Timers Example
+5 Timers Example
The Timers example, found in the org.eclipse.dd.examples.dsf.timers
@@ -859,7 +939,7 @@ and are automatically selected upon a triggered event.
@@ -885,8 +965,8 @@ editor - changes the value of the selected trigger.Image 4: Screen shot of the Timers view.
+ style="font-weight: bold;">Image 5: Screen shot of the Timers view.
-Services
-OSGi
+6 Services
+6.1 OSGi
DSF builds on top of OSGi services APIs. OSGi offers a rich
API for managing services and it is important to understand some of the
OSGi service API basics in order to use DSF
@@ -938,7 +1018,7 @@ down the debugger.
-Session
+6.2 Session
DSF-based debugger integrations can register many services and there
can be multiple instances of debuggers registering services with the
same interfaces. To help coordinate services in a give debugger
@@ -952,24 +1032,24 @@ debuggers, DSF services are organized into sessions.
sessions. Clients may also obtain a session instance using an ID
through a static method.
-
Executor
+6.3 Executor
All the services registered with the same session share a single DSF
Executor. By convention, all public service interfaces should be
restricted to being called in this executor thread. This point
@@ -988,11 +1068,12 @@ should be called using the session's DSF executor.
-Tracker
+6.4 Tracker
Using the OSGi APIs for accessing services directly can be very
cumbersome. A client retrieving a service reference is
responsible for retaining the ServiceReference object and for calling
-BundleContext.ungetService() to avoid leaking the refernce. Also,
+BundleContext.ungetService() to avoid leaking the reference.
+Also,
since a service may be un-registered at any time, the clients need to
listen for events indicating when a service is unregistered.
Fortunately there are two utilities which help with this task
@@ -1027,7 +1108,7 @@ safety
executor thread.
-
-Accessor
+ Accessors
methods
@@ -1057,7 +1138,7 @@ methods
@@ -1065,7 +1146,7 @@ down and un-gets all service references.
Initialization / Shutdown
+6.5 Initialization /
+Shutdown
Every DSF service must
implement the IDsfService.initialize() and IDsfService.shutdown()
methods. These methods can only be called in the session executor
@@ -1099,7 +1181,7 @@ the startup number of the service. This number is used in
prioritizing the service events.
-Events
+6.6 Events
DSF provides a somewhat unusual event mechanism, where event listeners
do not implement any particular listener interface. Instead,
event listeners use the DsfServiceEventHandler
@@ -1298,21 +1380,21 @@ called in the session executor thread.
Note: Service events are
prioritized. Listeners which themselves are services are called
first, in the order that they were initialized. All other
-listenres are called after the services.
-
+listeners are called after the services.
Data Model
+7 Data Model
The term Data Model refers to
the natural structure of data that is being retrieved by the DSF
-services. One of the great challanges of creating an user
+services. One of the great challenges of creating an user
interface for a debugger is that the amount of of data that is
-available on the target is much greater than what can be practially
-presented to the user. Therefere the debugger services need to
+available on the target is much greater than what can be practically
+presented to the user. Therefore the debugger services need to
break up the data into chunks with appropriate granularity to achieve
maximum performance and usability.
-IDMContext
+7.1 IDMContext
The IDMContext represents a handle to a chunk of data in the Data
Model. This interface is a minimal, yet central feature of the
Data Model API.
@@ -1371,7 +1453,7 @@ use is optional.
-Context Hierarchy
+7.2 Context Hierarchy
One of the most powerful features of the IDMContext interface is that
is is hierarchical. The IDMContext.getParents()
method returns the immediate ancestors of a given context and following
@@ -1453,7 +1535,7 @@ between service interfaces.
-DMContexts
+7.3 DMContexts
Searching the context hierarchy can be tedious to implement, the
DMContexts utility class contains a few static methods to simplify this
task:
@@ -1468,14 +1550,14 @@ the other.
Converts all the contexts in a hierarchy of the give context into a
list.
-View Model
+8 View Model
View Model refers to the ideal user-presentable
structure of the data. This is in contrast to the Data Model,
which refers to the natural
data structure, although the two often end up being the same.
Never the less, the needs of the user presentation often change so the
central feature of the View Model is the ability to customize it.
-Flexible Hierarchy
+8.1 Flexible Hierarchy
View Model builds on the flexible
hierarchy API introduced by Debug
Platform team in release 3.2. The flexible hierarchy API has a
@@ -1507,7 +1589,7 @@ related to packaging.
-Adapter Problem
+8.2 Adapter Problem
The number two feature of flexible hierarchy API is implemented using
the adapter pattern. One down-side of the adapter pattern is that
@@ -1515,22 +1597,76 @@ there can only be one instance of an adapter of a particular type
registered for a given element. For flexible hierarchy providers,
it means that each provider must implement the element presentation
logic for every view that the element appears in, and as a result
-adding a new view can force changing a large number of modules.
-
-
+
+
+To overcome the adapter pattern limitation, the View Model uses
wrapper objects. The wrapper objects are held by the viewer and
they redirect the requests for different flexible hierarchy providers
to the appropriate modules.
+
+
+
+
+
+
+Image 6: Diagram illustrating problem of
+multiple views sharing a single element, when using the adapter
+mechanism.
+
+
-
TODO: add a diagram of the View
-Model hierarchy adapter pattern use
-
![]() + |
+
Image 7: Diagram illustrating use of
+wrappers to allow different adapters to be associated with the same
+element, for use with different views. + |
+
org.eclipse.dd.examples.dsf.requestmonitor.Async2Plus2 + style="font-family: monospace; font-weight: bold;">org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider |
||
+ |
+ 20: public interface IElementContentProvider { |
org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate + | +|
+ |
+
+ 23: public interface IViewerUpdate extends IRequest {+ |
+
+ | Note: In Step 4, the logic used to
+determine which VM Node should process the content request is
+customizable. However, in general VM Nodes are arranged in a
+parent-child hierarchy which mirrors the layout of elements in the view. |
Excercise abc: xyz | + Note: Also in Step 4, the VM
+Provider may be customized to do additional processing on the
+update. For example, the provider may cache the results of
+previous updates and return cached results without ever calling the VM
+Node. + |
org.eclipse.dd.examples.dsf.timers.TimersVMNode + |
+ |
+ |
+
+ 86: protected void updateElementsInSessionThread(final IChildrenUpdate update) {+ |
+
Event handling in VM
+Provider
+The following listing from the Timers example shows the handling
+of a model event:
+
org.eclipse.dd.examples.dsf.timers.TimersVMProvider + | +|
+ |
+
+ 108: @DsfServiceEventHandler+ |
+
org.eclipse.dd.examples.dsf.timers.TimersVMNode + | +|
+ |
+
+ 141: public int getDeltaFlags(Object e) {+ |
+
Below is the listing from the Timers VM Node that configures the
+label provider:
+
org.eclipse.dd.examples.dsf.timers.TimersVMNode + | +|
+ |
+
+ 53: private static final PropertyBasedLabelProvider fgLabelProvider;+ |
+
org.eclipse.dd.examples.dsf.timers.TimersVMNode + | +|
+ |
+
+ 98: public void update(final IPropertiesUpdate[] updates) {+ |
+