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
index 0fd59f1a441..96a68ec621e 100644
--- 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
@@ -4,12 +4,71 @@
DSF Common Patterns
-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.
- Build the examples plugin:
- Execute the build the first time to build and run the
-excercises preprocessor.
+exercises preprocessor.
- Refresh the resources in the plugin (right-click on project in Navigator and select Refresh), in order to recognize the
@@ -48,28 +107,29 @@ sources generated by the preprocessor.
- Launch the examples
- - Examples in data org.eclipse.dd.examples.dsf.requestmonitor and
-org.eclipse.dd.examples.dsf.dataviewer packages each contain a public
+
- 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
+ - The timers example in org.eclipse.dd.examples.dsf.timers
+requires an Eclipse Application to be launched (see the Timers Example section for more details).
+
-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.
- Line 36 marks the callback as completed and
-implicilty invokes
+implicitly 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 bug
+but often subtle and difficult to track down bug
+
+
+
+ 
+ |
+
+
+ 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.
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.
|
@@ -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().
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.
|
-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.
AsyncDataViewer - Table-based viewer which implements an
asynchronous ILazyContentProvider 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.
Image 1: Detailed sequence of calling
+ style="font-weight: bold;">Image 2: Detailed sequence of calling
IDataGenerator.getCount() in SyncDataViewer.getElements().
|
@@ -440,7 +519,7 @@ for completion of the asynchronous methods called by execute().
-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.
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.
|
@@ -668,21 +747,21 @@ threads can call a request monitor when finished.
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.
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.
|
-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.
- 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.
|
@@ -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.
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.
|
-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.
Image 4: Screen shot of the Timers view.
+ style="font-weight: bold;">Image 5: Screen shot of the Timers view.
|
@@ -885,8 +965,8 @@ editor - changes the value of the selected trigger.
-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.
- Session Lifecycle Events - Clients may register to listen when
+ Session Life cycle Events - Clients may register to listen when
sessions are started and ended.
DSF Executor -
-Eash session has a (single-threaded) DSF Executor associated with
+Each session has a (single-threaded) DSF Executor associated with
it, though multiple sessions could share a single executor. More
about session executor in the next section.
Service Events -
The session is used to dispatch service events. More on events in
following sections.
Model Adapters -
-A session allws an adapter to be registered, which will be returned by
+A session allows an adapter to be registered, which will be returned by
all Data Model contexts in a given session for a given adapter
type. More information about Data Model is described in the Data
Model section.
-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
|
- open() - Starts
-tracking maching services.
+tracking matching services.
- close() - Shuts
down and un-gets all service references.
@@ -1065,7 +1146,7 @@ down and un-gets all service references.
|
- <constructor>
-- DSF services tracker can be used immediately after being constucted.
+- DSF services tracker can be used immediately after being constructed.
- dispose() -
Disposes and un-gets all service references held by the tracker.
@@ -1086,7 +1167,8 @@ service reference leak.
|
-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.
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.
-
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.
-
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.
+
+
+
+ 
+ |
+
+
+ Image 6: Diagram illustrating problem of
+multiple views sharing a single element, when using the adapter
+mechanism.
+ |
+
+
+
+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.
-
-TODO: add a diagram of the View
-Model hierarchy adapter pattern use
-
-IVMAdapter -> IVMProvider -> IVMNode -> IVMContext
-
-
-
+
+
+
+ 
+ |
+
+
+ Image 7: Diagram illustrating use of
+wrappers to allow different adapters to be associated with the same
+element, for use with different views.
+ |
+
+
+
+8.4 API
+The View Model uses four principal types of elements when processing
+adapter requests from flexible hierarchy viewers. These are:
+
+ - IVMAdapter - The
+adapter is the top-level object in the view model hierarchy. It
+implements some of the flexible hierarchy provider interfaces and it is
+returned by the elements as the single adapter implementing those
+interfaces The main function the VM Adapter is to redirect the
+provider requests based on the view ID that the requests originated
+from.
+
+ - IVMProvider - In
+the View Model hierarchy, the provider object supplies view content for
+a single view.
+ - IVMNode - The
+node allows for grouping of like-elements in the view. Examples
+of such nodes are: threads node, stack frames node, variables node, etc.
+ - IVMContext - The
+VM Context is the interface of the wrapper objects that are held by the
+flexible hierarchy viewers. The context holds a reference to the
+element that is being wrapped, as well as to the VM Node and VM Adapter
+that it originated from.
+
+
+8.5 Content Provider
+The most important job of the View Model is to supply the content, in
+form of element wrappers, to the viewers. The flexible hierarchy
+interface for this provider is listed below:
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 {
22: /** 23: * Updates the number of children for the given parent elements in the 24: * specified requests. 25: * 26: * @param updates Each update specifies an element to update and provides 27: * a store for the result. The update array is guaranteed to have at least 28: * one element, and for all updates to have the same presentation context. 29: */ 30: public void update(IChildrenCountUpdate[] updates); 31: ... 39: public void update(IChildrenUpdate[] updates); 40: ... 48: public void update(IHasChildrenUpdate[] updates); 49: 50: }
|
+Notice that each request for data is
+encapsulated inside an update
+object. Every update
+implements the IViewerUpdate interface listed here:
+
+
+
+
+
+ org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate
+ |
+
+
+
+ |
+
+ 23: public interface IViewerUpdate extends IRequest {
25: /** 26: * Returns the context this update was requested in. 27: * 28: * @return context this update was requested in 29: */ 30: public IPresentationContext getPresentationContext(); 31: 32: /** 33: * Returns the model element associated with this request. 34: * 35: * @return associated model element 36: */ 37: public Object getElement(); 38: 39: /** 40: * Returns the viewer tree path to the model element associated with this 41: * request. An empty path indicates a root element. 42: * 43: * @return tree path, possibly empty 44: */ 45: public TreePath getElementPath(); 46: 47: /** 48: * Returns the element that was the viewer input at the time the 49: * request was made, possibly <code>null</code>. 50: * 51: * @return viewer input element, possibly <code>null</code> 52: */ 53: public Object getViewerInput(); 54: }
+ |
+
+
+
+
+
+These update requests are received by the adapter object in the View
+Model hierarchy and are channeled to the correct node that should
+process the given update. This procedure is described in a few
+steps:
+
+ - VM Adapter receives the update request. For example the
+update(IChildrenUpdate[]) method is called by a viewer.
+ - VM Adapter retrieves the ID in the IPresentationContext object
+associated with the update.
+ - VM Adapter finds the VM Provider that is assigned for that
+presentation context, creating it if necessary.
+ - VM Provider finds and calls the VM Node (or nodes) that should
+process the
+given update.
+
+ - VM Node retrieves fills the data in the update and marks it as
+completed.
+
+
-
+ | 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.
+ |
+As a sample from the Timers example of the VM Node logic that fulfills
+the content update request:
+
+
+
+
+ org.eclipse.dd.examples.dsf.timers.TimersVMNode
+ |
+
+
+
+ |
+
+ 86: protected void updateElementsInSessionThread(final IChildrenUpdate update) { 87: if (!checkService(AlarmService.class, null, update)) return;
89: // Retrieve the timer DMContexts, create the corresponding VMCs array, and 90: // set them as result. 91: TimerDMContext[] timers = 92: getServicesTracker().getService(TimerService.class).getTimers(); 93: fillUpdateWithVMCs(update, timers); 94: update.done(); 95: }
+ |
+
+
+
+
+
+ - Lines 91-92 retrieve the Data Model contexts from the service.
+ - Line 93 calls a convenience method which creates VM Context
+wrappers for each element in the timers
+array, and sets those VM Contexts to the update.
+ - Line 94 completes the update.
+
+
+8.6 Model Event Proxy
+Another important job of the View Model is to translate the events that
+originate from the Data Model into generic events (deltas) that the viewer can
+understand. For this purpose, the Flexible Hierarchy has the IModelProxy interface which is used
+in the following manner:
+
+ - An root element is
+added into the view. The root
+element could be the view input or another element which is designated
+as the root of a model hierarchy.
+ - The viewer gets the IModelProxyFactory
+adapter from the element.
+ - The viewer calls IModelProxyFactory.createModelProxy()
+which returns the IModelProxy instance.
+ - The viewer adds itself as a listener
+to model events with the model proxy
+object.
+ - The model proxy notifies its listeners (including the viewer)
+with model deltas whenever
+the model has changed.
+ - When the root element is removed from the viewer, the viewer
+disposes the model proxy.
+
+
+For View Model users, much of the logic of creating the model proxy
+factory is implemented using abstract base classes in the org.eclipse.dd.dsf.ui.viewmodel
+package. Instead, a typical DSF application only has to implement
+two interfaces in order to support event proxying:
+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 109: public void eventDispatched(final TimersChangedEvent event) { 110: if (isDisposed()) return;
112: try { 113: getExecutor().execute(new Runnable() { 114: public void run() { 115: if (isDisposed()) return; 116: handleEvent(event); 117: } 118: }); 119: } catch (RejectedExecutionException e) {} 120: }
+ |
+
+
+
+
+
+ - Line 108 declares the eventDispatched()
+method as a service event handler.
+ - Line 113 switches execution to the View Model executor
+thread. The event handler is called on the session executor
+thread, however the standard View Model implementation classes have
+their own single-threaded executor which is used to protect its state.
+ - Line 116 calls the AbstractVMProvider.handleEvent() protected
+method which continues the event processing.
+
+
+Processing events in VM Nodes
+The following listing shows how the nodes translate the events into
+model delta components:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.timers.TimersVMNode
+ |
+
+
+
+ |
+
+ 141: public int getDeltaFlags(Object e) { 142: // This node generates delta if the timers have changed, or if the 143: // label has changed. 144: if (e instanceof TimerService.TimerTickDMEvent) { 145: return IModelDelta.STATE; 146: } else if (e instanceof TimerService.TimersChangedEvent) { 147: return IModelDelta.CONTENT; 148: } 149: return IModelDelta.NO_CHANGE; 150: }
152: public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor requestMonitor) { 153: if (e instanceof TimerService.TimerTickDMEvent) { 154: // Add delta indicating that the given timer has changed. 155: parentDelta.addNode( createVMContext(((TimerService.TimerTickDMEvent)e).getDMContext()), IModelDelta.STATE ); 156: } else if (e instanceof TimerService.TimersChangedEvent) { 157: // The list of timers has changed, which means that the parent 158: // node needs to refresh its contents, which in turn will re-fetch the 159: // elements from this node. 160: parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); 161: } 162: requestMonitor.done(); 163: }
+ |
+
+
+
+
+
+ - Lines 141 declares the getDeltaFlags()
+method, which tells the event processing logic what flags if any can be
+generated by the given node for the given event. Depending on its
+return value, the event processing logic may or may not call the buildDelta() method.
+ - Lines 144-148 return appropriate flags for the events that this
+node can process.
+ - Lines 153-155 process the TimerTickEvent.
+They add a delta element corresponding to the changed timer instructing
+the viewer to repaint this timer.
+ - Lines 156-160 process the TimersChangedEvent.
+They add a flag to the parent delta element, instructing it to refresh
+all the elements managed by this node.
+
+
+8.7 Property Provider
+/ Label Provider
+
+The IElementPropertyProvider
+interface is not actually part of the Flexible Hierarchy API, but an
+extension interface added by DSF. View Model implementers can use
+the property provider to configure an IElementLabelProvider
+object
+that the Flexible Hierarchy viewers call in order to get element
+presentation details.
+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; 54: static { 55: fgLabelProvider = new PropertyBasedLabelProvider();
57: LabelColumnInfo idCol = new LabelColumnInfo( 58: new LabelAttribute[] { 59: new LabelText(new MessageFormat("Timer #{0}"), 60: new String[] { PROP_TIMER_NUMBER }), 61: new LabelImage(DsfExamplesPlugin.getDefault().getImageRegistry(). 62: getDescriptor(DsfExamplesPlugin.IMG_ALARM)) 63: }); 64: fgLabelProvider.setColumnInfo(TimersViewColumnPresentation.COL_ID, idCol); 65: 66: LabelColumnInfo valueCol = ... ... 74: }
+ |
+
+
+
+
+
+ - Line 55 creates the label provider.
+ - Lines 58-62 create the display attributes to use in the Name
+column. These attributes use named properties as parameters in
+calculating the data, such as the label string.
+ - Line 64 registers the column info object with the label provider.
+
+All that is left is to implement the property provider:
+
+
+
+
+
+ org.eclipse.dd.examples.dsf.timers.TimersVMNode
+ |
+
+
+
+ |
+
+ 98: public void update(final IPropertiesUpdate[] updates) { 99: // Switch to the session thread before processing the updates. 100: try { 101: getSession().getExecutor().execute(new DsfRunnable() { 102: public void run() { 103: for (IPropertiesUpdate update : updates) { 104: updatePropertiesInSessionThread(update); 105: } 106: }}); 107: } catch (RejectedExecutionException e) { 108: for (IViewerUpdate update : updates) { 109: handleFailedUpdate(update); 110: } 111: } 112: }
114: @ConfinedToDsfExecutor("getSession#getExecutor") 115: private void updatePropertiesInSessionThread(final IPropertiesUpdate update) { 116: // Find the timer context in the element being updated 117: final TimerDMContext dmc = findDmcInPath( 118: update.getViewerInput(), update.getElementPath(), TimerDMContext.class); 119: 120: // If either update or service are not valid, fail the update and exit. 121: if (!checkDmc(dmc, update) || 122: !checkService(TimerService.class, null, update)) 123: { 124: return; 125: } 126: 127: TimerService timerService = 128: getServicesTracker().getService(TimerService.class, null); 129: int value = timerService.getTimerValue(dmc); 130: 131: if (value == -1) { 132: handleFailedUpdate(update); 133: return; 134: }
136: update.setProperty(PROP_TIMER_NUMBER, dmc.getTimerNumber()); 137: update.setProperty(PROP_TIMER_VALUE, value); 138: update.done(); 139: }
+ |
+
+
+
+
+
+
+ - Lines 98-112 handle switching into the session executor thread.
+ - Lines 117-118 call a convenience method to extract the Data Model
+timer context from the viewer update. Normally this requires
+casting the object returned by IViewerUpdate.getElement() to the
+expected VM Context class. Then extracting the model object from
+the VM Context wrapper.
+ - Line 127 retrieves element data from the service.
+ - Lines 136-137 write the element properties into the property
+update.
+
+