VDBThreadPresenter.st
author Jan Vrany <jan.vrany@labware.com>
Thu, 10 Dec 2020 20:28:06 +0000
changeset 208 719dfb28b819
parent 207 27e7fa4229b3
child 212 62bb14c71a71
permissions -rw-r--r--
UX: avoid round trip to GDB until thread node is expanded ...by assuming a thread has always a child. This is not strictly true, but speeds up the UI significantly for multi-threaded applications since usually user is debugging one, two threads and this avoids fetching stack for all threads unless absolutely necessary.

"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany
Copyright (C) 2020 LabWare

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
"{ Package: 'jv:vdb' }"

"{ NameSpace: Smalltalk }"

VDBAbstractPresenter subclass:#VDBThreadPresenter
	instanceVariableNames:'thread name'
	classVariableNames:''
	poolDictionaries:''
	category:'VDB-Presentation'
!

!VDBThreadPresenter class methodsFor:'documentation'!

copyright
"
jv:vdb - Visual / VM Debugger
Copyright (C) 2015-now Jan Vrany
Copyright (C) 2020 LabWare

This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'

You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
"
! !

!VDBThreadPresenter class methodsFor:'menu specs'!

contextMenu
    "This resource specification was automatically generated
     by the MenuEditor of ST/X."

    "Do not manually edit this!! If it is corrupted,
     the MenuEditor may not be able to read the specification."


    "
     MenuEditor new openOnClass:VDBThreadPresenter andSelector:#contextMenu
     (Menu new fromLiteralArrayEncoding:(VDBThreadPresenter contextMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(Menu (
         (MenuItem
            enabled: canCopyBacktrace
            label: 'Copy Backtrace To Clipboard'
            itemValue: doCopyBacktraceToClipboard
            isVisible: true
         )
       ) nil
        nil
     )
! !

!VDBThreadPresenter methodsFor:'accessing'!

icon
    thread isRunning ifTrue:[ ^ VDBIconLibrary threadRunning16x16 ].
    thread isStopped ifTrue:[ ^ VDBIconLibrary threadStopped16x16 ].
    thread isTerminated ifTrue:[ ^ VDBIconLibrary threadTerminated16x16 ].

    ^ nil

    "Created: / 22-09-2014 / 22:00:20 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

label
    name isNil ifTrue:[ 
        thread isRunning ifFalse:[
            name := '"' , thread name , '"'
        ]
    ].
    ^ 'Thread %1 [%2] %3' bindWith: (thread id printStringRadix: 10 size: 2 fill: Character space) with: thread status with: name ? ''

    "Created: / 22-09-2014 / 00:14:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-07-2017 / 14:23:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 27-11-2020 / 13:44:36 / Jan Vrany <jan.vrany@labware.com>"
!

subject
    "Return an instance of GDB object that this presenter displays."

    ^ thread

    "Modified: / 05-02-2018 / 13:08:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

thread
    ^ thread
! !

!VDBThreadPresenter methodsFor:'initialization'!

setThread: aGDBThread
    thread := aGDBThread.

    "Created: / 21-09-2014 / 23:39:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-07-2017 / 14:21:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBThreadPresenter methodsFor:'menu actions'!

doCopyBacktraceToClipboard
    | backtrace |

    backtrace := String streamContents:[:s|
        thread stack 
            do: [:frame | frame dumpOn: s ]
            separatedBy: [ s cr; nextPutAll: '--'; cr ]       
    ].
    self doCopy: backtrace

    "Modified: / 09-08-2020 / 07:15:42 / Jan Vrany <jan.vrany@labware.com>"
! !

!VDBThreadPresenter methodsFor:'menu queries'!

canCopyBacktrace
    ^ [ thread isStopped ]

    "Modified: / 09-08-2020 / 07:01:35 / Jan Vrany <jan.vrany@labware.com>"
! !

!VDBThreadPresenter methodsFor:'protocol-accessing'!

fetchChildren
    "should compute the list of children via the model.
     Be aware, that the somewhat stupid 'optimization' of how the model is fetched may lead to
     a O(n*log n) or even O(n^2) behavior here.
     *** to optimize: redefine by subClass"

     thread isDead ifTrue:[ ^ #() ].
     thread isRunning ifTrue:[ ^ #() ].
     ^ thread stack collect:[ :f | VDBFramePresenter new setFrame: f; parent: self ]

    "Created: / 21-09-2014 / 23:42:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 30-09-2014 / 00:04:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBThreadPresenter methodsFor:'protocol-queries'!

hasChildren

    "/ Here we assume a thread has at least one frame.
    "/ This is NOT true is certain corner cases, however,
    "/ unconditionally answering `true` here avoids round-trip
    "/ to GDB until thread node is actually "expanded".
    ^ true

    "Created: / 10-12-2020 / 00:05:41 / Jan Vrany <jan.vrany@labware.com>"
    "Modified (comment): / 10-12-2020 / 20:17:56 / Jan Vrany <jan.vrany@labware.com>"
! !

!VDBThreadPresenter methodsFor:'testing'!

isThreadPresenter
    ^ true

    "Created: / 21-09-2014 / 23:54:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBThreadPresenter class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !