@@ -19,26 +19,37 @@ import { GDBTargetDebugTracker, GDBTargetDebugSession } from '../../debug-sessio
1919import { ComponentViewerInstance } from './component-viewer-instance' ;
2020import { URI } from 'vscode-uri' ;
2121import { ComponentViewerTreeDataProvider } from './component-viewer-tree-view' ;
22+ import { logger } from '../../logger' ;
23+ import type { ScvdGuiInterface } from './model/scvd-gui-interface' ;
2224
23-
25+ export type fifoUpdateReason = 'sessionChanged' | 'refreshTimer' | 'stackTrace' ;
26+ interface UpdateQueueItem {
27+ updateId : number ;
28+ debugSession : GDBTargetDebugSession ;
29+ updateReason : fifoUpdateReason ;
30+ }
2431export class ComponentViewer {
2532 private _activeSession : GDBTargetDebugSession | undefined ;
2633 private _instances : ComponentViewerInstance [ ] = [ ] ;
2734 private _componentViewerTreeDataProvider : ComponentViewerTreeDataProvider | undefined ;
2835 private _context : vscode . ExtensionContext ;
2936 private _instanceUpdateCounter : number = 0 ;
3037 private _loadingCounter : number = 0 ;
38+ // Update queue is currently used for logging purposes only
39+ private _updateQueue : UpdateQueueItem [ ] = [ ] ;
40+ private _pendingUpdateTimer : NodeJS . Timeout | undefined ;
41+ private _pendingUpdate : boolean = false ;
42+ private _runningUpdate : boolean = false ;
43+ private static readonly pendingUpdateDelayMs = 200 ;
3144
3245 public constructor ( context : vscode . ExtensionContext ) {
3346 this . _context = context ;
3447 }
3548
3649 public activate ( tracker : GDBTargetDebugTracker ) : void {
37- /* Create Tree Viewer */
3850 this . _componentViewerTreeDataProvider = new ComponentViewerTreeDataProvider ( ) ;
3951 const treeProviderDisposable = vscode . window . registerTreeDataProvider ( 'cmsis-debugger.componentViewer' , this . _componentViewerTreeDataProvider ) ;
40- this . _context . subscriptions . push (
41- treeProviderDisposable ) ;
52+ this . _context . subscriptions . push ( treeProviderDisposable ) ;
4253 // Subscribe to debug tracker events to update active session
4354 this . subscribetoDebugTrackerEvents ( this . _context , tracker ) ;
4455 }
@@ -111,14 +122,16 @@ export class ComponentViewer {
111122 this . _activeSession = undefined ;
112123 }
113124 // Update component viewer instance(s)
114- await this . updateInstances ( ) ;
125+ this . schedulePendingUpdate ( 'stackTrace' ) ;
115126 }
116127
117128 private async handleOnWillStopSession ( session : GDBTargetDebugSession ) : Promise < void > {
118129 // Clear active session if it is the one being stopped
119130 if ( this . _activeSession ?. session . id === session . session . id ) {
120131 this . _activeSession = undefined ;
121132 }
133+ // Clearing update queue
134+ this . _updateQueue = [ ] ;
122135 }
123136
124137 private async handleOnWillStartSession ( session : GDBTargetDebugSession ) : Promise < void > {
@@ -130,7 +143,7 @@ export class ComponentViewer {
130143 // if new session is not the current active session, erase old instances and read the new ones
131144 if ( this . _activeSession ?. session . id !== session . session . id ) {
132145 this . _instances = [ ] ;
133- this . _componentViewerTreeDataProvider ?. deleteModels ( ) ;
146+ this . _componentViewerTreeDataProvider ?. clear ( ) ;
134147 }
135148 // Update debug session
136149 this . _activeSession = session ;
@@ -141,42 +154,76 @@ export class ComponentViewer {
141154 private async handleRefreshTimerEvent ( session : GDBTargetDebugSession ) : Promise < void > {
142155 if ( this . _activeSession ?. session . id === session . session . id ) {
143156 // Update component viewer instance(s)
144- await this . updateInstances ( ) ;
157+ this . schedulePendingUpdate ( 'refreshTimer' ) ;
145158 }
146159 }
147160
148161 private async handleOnDidChangeActiveDebugSession ( session : GDBTargetDebugSession | undefined ) : Promise < void > {
149162 // Update debug session
150163 this . _activeSession = session ;
151- if ( ! session ) {
152- this . _instances = [ ] ;
153- this . _componentViewerTreeDataProvider ?. deleteModels ( ) ;
164+ if ( session === undefined ) {
154165 return ;
155166 }
156- // Update Active Session in all instances
157- for ( const instance of this . _instances ) {
158- instance . updateActiveSession ( session ) ;
167+ // update active debug session for all instances
168+ this . _instances . forEach ( ( instance ) => instance . updateActiveSession ( session ) ) ;
169+ this . schedulePendingUpdate ( 'sessionChanged' ) ;
170+ }
171+
172+ private schedulePendingUpdate ( updateReason : fifoUpdateReason ) : void {
173+ this . _pendingUpdate = true ;
174+ if ( this . _pendingUpdateTimer ) {
175+ clearTimeout ( this . _pendingUpdateTimer ) ;
159176 }
160- // Update component viewer instance(s)
161- await this . updateInstances ( ) ;
177+ this . _pendingUpdateTimer = setTimeout ( ( ) => {
178+ this . _pendingUpdateTimer = undefined ;
179+ void this . runUpdate ( updateReason ) ;
180+ } , ComponentViewer . pendingUpdateDelayMs ) ;
162181 }
163182
164- private async updateInstances ( ) : Promise < void > {
165- this . _instanceUpdateCounter = 0 ;
183+ private async runUpdate ( updateReason : fifoUpdateReason ) : Promise < void > {
184+ if ( this . _runningUpdate ) {
185+ return ;
186+ }
187+ this . _runningUpdate = true ;
188+ while ( this . _pendingUpdate ) {
189+ this . _pendingUpdate = false ;
190+ try {
191+ await this . updateInstances ( updateReason ) ;
192+ } finally {
193+ this . _runningUpdate = false ;
194+ logger . error ( 'Component Viewer: Error during update' ) ;
195+ }
196+ }
197+ this . _runningUpdate = false ;
198+ }
199+
200+ private async updateInstances ( updateReason : fifoUpdateReason ) : Promise < void > {
166201 if ( ! this . _activeSession ) {
167- this . _componentViewerTreeDataProvider ?. deleteModels ( ) ;
202+ this . _componentViewerTreeDataProvider ?. clear ( ) ;
168203 return ;
169204 }
205+ logger . debug ( `Component Viewer: Queuing update due to '${ updateReason } ', that is update #${ this . _updateQueue . length + 1 } in the queue` ) ;
206+ this . _updateQueue . push ( {
207+ updateId : this . _updateQueue . length + 1 ,
208+ debugSession : this . _activeSession ,
209+ updateReason : updateReason
210+ } ) ;
211+ this . _instanceUpdateCounter = 0 ;
170212 if ( this . _instances . length === 0 ) {
171213 return ;
172214 }
173- this . _componentViewerTreeDataProvider ?. resetModelCache ( ) ;
215+ const roots : ScvdGuiInterface [ ] = [ ] ;
174216 for ( const instance of this . _instances ) {
175217 this . _instanceUpdateCounter ++ ;
218+ logger . debug ( `Updating Component Viewer Instance #${ this . _instanceUpdateCounter } due to '${ updateReason } ' (queue position #${ this . _updateQueue . length } )` ) ;
176219 console . log ( `Updating Component Viewer Instance #${ this . _instanceUpdateCounter } ` ) ;
177220 await instance . update ( ) ;
178- this . _componentViewerTreeDataProvider ?. addGuiOut ( instance . getGuiTree ( ) ) ;
221+ const guiTree = instance . getGuiTree ( ) ;
222+ if ( guiTree ) {
223+ roots . push ( ...guiTree ) ;
224+ }
179225 }
180- this . _componentViewerTreeDataProvider ?. showModelData ( ) ;
226+ this . _componentViewerTreeDataProvider ?. setRoots ( roots ) ;
181227 }
182228}
229+
0 commit comments