Edi Weitz | 3 Mar 11:24 2008
Picon

Updating a CAPI GUI during phases of heavy computation

[Attention: Running this test code might lock up your Lisp image!]

I have an application with a somewhat complicated GUI from which you
can start a heavy computation.  What I want is that the intermediate
results of the computation are reported in the main interface while a
little window pops up which shows the overall progress and also
provides a button to stop the computation.  The attached code is a
gross simplification of the actual situation, but it should hopefully
be enough to illustrate my problem.

My first approach was to just do it in a straightforward way.  Update
the GUI whenever there's a reason to update it.  That's what you get
if you run (TEST).  If you do that, the progress window is updated,
but the "main" window is kind of dead - try to move the progress
window around and you'll note that the main window isn't repainted.

Not good.  So I thought that this happened because the heavy
computation runs in the thread of the main window and prevents it from
taking care of windoing events.  The next thing I tried was equivalent
to (TEST :SEPARATE-THREAD T).  If I try this, everything locks up, no
progress is reported at all.  If you're lucky, you can find the
"worker" process in the Process Browser and kill it.

Hmmm.  I tend to think that this wouldn't happen (see previous
discussions), if we had real SMP.  Anyway, I tried a third solution.
That'd be (TEST :WAIT T).  In this case, the computation thread
actually waits until the progress window has been updated.  This
doesn't seem like an ideal solution to me as it kind of serializes the
events and takes all the fun out of multi-threading, but at least it
works.  More or less, that is, as the whole computation now has to
(Continue reading)

Dmitriy Ivanov | 3 Mar 13:13 2008
Picon

Re: Updating a CAPI GUI during phases of heavy computation


Edi Weitz wrote on Mon, 03 Mar 2008 11:24:26 +0100 13:24:

| I have an application with a somewhat complicated GUI from which you
| can start a heavy computation.  What I want is that the intermediate
| results of the computation are reported in the main interface while a
| little window pops up which shows the overall progress and also
| provides a button to stop the computation.  The attached code is a
| gross simplification of the actual situation, but it should hopefully
| be enough to illustrate my problem.
|...snip...|

In my version of progress-dialog packed within ywidgets and based on Michal
Krupka's code, I am running heavy computation in the process of the progress
popup window itself. I have basically tested this with the simplest progress
function only updating the popup's meter. IIRC, updating the caller window
also worked.
--
Sincerely,
Dmitriy Ivanov
lisp.ystok.ru

Edi Weitz | 3 Mar 16:02 2008
Picon

Re: Updating a CAPI GUI during phases of heavy computation

On Mon, 3 Mar 2008 15:13:47 +0300, "Dmitriy Ivanov" <divanov <at> aha.ru> wrote:

> In my version of progress-dialog packed within ywidgets and based on
> Michal Krupka's code, I am running heavy computation in the process
> of the progress popup window itself. I have basically tested this
> with the simplest progress function only updating the popup's
> meter. IIRC, updating the caller window also worked.

I've tried your progress dialog with the attached code, but the
results were similar to what I had in my failed attempts - the status
was updated only rarely (most of the time the status line was blank)
and the interface sometimes "disappeared" (turned white) without me
trying any GUI interaction.

Thanks,
Edi.

Attachment (progress3.lisp): application/octet-stream, 1110 bytes
John DeSoi | 3 Mar 16:14 2008

Re: Updating a CAPI GUI during phases of heavy computation


On Mar 3, 2008, at 4:24 AM, Edi Weitz wrote:

> Am I missing a solution that's substantially better?  Why do I only
> have to wait for the progress window and not for the main window?  Why
> do (TEST :WAIT T :SEPARATE-THREAD T) and (TEST :WAIT T) behave the
> same?
>
> BTW, all this might be specific to Windows as each top-level interface
> has its own thread there.

My approach to this is to run the operation in a separate faceless  
process which calls back to the interface with progress information.  
The interface switches to a progress display with a cancel button that  
can be used to kill the computation process.

This works for me on both Mac and Windows.

John DeSoi, Ph.D.

Edi Weitz | 3 Mar 16:28 2008
Picon

Re: Updating a CAPI GUI during phases of heavy computation


On Mon, 3 Mar 2008 09:14:21 -0600, John DeSoi <desoi <at> pgedit.com> wrote:

> My approach to this is to run the operation in a separate faceless
> process which calls back to the interface with progress information.
> The interface switches to a progress display with a cancel button
> that can be used to kill the computation process.

Yes, that's what I'm also doing in my example code (see the
:SEPARATE-THREAD keyword).  Except that I don't want to
MP:PROCESS-KILL the background process at some random point.  That
seems too big a hammer for my taste.

> This works for me on both Mac and Windows.

My impression is that this only works reliably if the background
procress isn't able to saturate the CPU (core) for a longer period.
Or if there are enough places in the background process where LW
releases the "big lock".

John DeSoi | 3 Mar 17:06 2008

Re: Updating a CAPI GUI during phases of heavy computation


On Mar 3, 2008, at 9:28 AM, Edi Weitz wrote:

> Yes, that's what I'm also doing in my example code (see the
> :SEPARATE-THREAD keyword).  Except that I don't want to
> MP:PROCESS-KILL the background process at some random point.  That
> seems too big a hammer for my taste.
>
>> This works for me on both Mac and Windows.
>
> My impression is that this only works reliably if the background
> procress isn't able to saturate the CPU (core) for a longer period.
> Or if there are enough places in the background process where LW
> releases the "big lock".

Sorry for not looking more carefully at the example. It looks similar  
to what I'm using. You are probably right - the case where I'm using  
this does a lot of file I/O so it may not work for something more CPU  
intensive.

John DeSoi, Ph.D.

Denis Pousseur | 3 Mar 17:11 2008
Picon

Re: Updating a CAPI GUI during phases of heavy computation


In this kind of situation I force the computation to slow down with some
calls to process-wait-with-time-out (rather than process-allow-scheduling).
This let a chance to the display operations to run.
The problem is to find the good delay. Here, with a delay of one millisecond
it's run on my intel Mac :

(defun test-in-separate-threads ()
  (let* ((update-callback
          (lambda (iteration text)
            (mp:process-wait-with-timeout nil 0.001)
            (update-output-pane text)
            (update-progress-pane iteration)))
         (start-function
          (lambda ()
            (mp:process-run-function "worker" nil
                                     (lambda ()
                                       (work update-callback))))))
    (setq *test-interface*
          (make-instance 'test-interface :button-args `(:callback
,start-function)))
    (capi:display *test-interface*)))

Naturally it's probably not the faster way...

Best

Denis

Le 3/03/08 11:24, « [NOM] » <[ADRESSE]> a écrit :
(Continue reading)

Mitch Berkson | 3 Mar 17:32 2008

Unit testing of graphics


Is there a ready-made way to unit test the windowed output of functions 
(for Windows)?

I have scanned the unit test libraries here

(http://www.cl-user.net/asp/BK9t6/sdataQIrH-xEyOeShDQjr-br2cQTk8yBX8yBX8oQ5Ss9v-ujg$Np5/sdataQu3F$sSHnB==) 
and have started using lisp-unit, but that doesn't have anything along 
those lines.

Mitch Berkson

Mitch Berkson | 3 Mar 20:00 2008

Re: Unit testing of graphics


Thanks. I'll look at that.

What I was envisioning was something that would first capture the image 
of a pane which I originally manually verify as acceptable and then 
subsequently compare the captured image to the results of a unit test.

Mitch

Geoffrey D. Cooper wrote:
> If you just want to test that the end result is the same there are a 
> number of macro recorders available for windows that will execute 
> keystroke and mouse actions.  You would of course have to personally 
> verify that the end result is correct. http://www.autohotkey.com/ is a 
> free download that should fulfill those needs.
> 
> If you are looking for a fully automated test suite, on the order of 
> expect, then I think you're pretty much out of luck unless there is some 
> for profit software out there that does dll hooking to capture window 
> events for result comparison.
> 
> cooper
> 
> Mitch Berkson wrote:
>>
>> Is there a ready-made way to unit test the windowed output of 
>> functions (for Windows)?
>>
>> I have scanned the unit test libraries here 
>>
(Continue reading)

Chris Dean | 3 Mar 21:10 2008

Re: Unit testing of graphics


Mitch Berkson <mitch <at> bermita.com> writes:
> Is there a ready-made way to unit test the windowed output of
> functions (for Windows)?

As the earlier poster said, if you want to do automated testing of a
GUI you'll need some sort of record and replay software.  As far as I
know there is no good software where you can write gui tests in Common
Lisp as you would for "normal" unit tests.

I've used http://en.wikipedia.org/wiki/HP_QuickTest_Professional in a
previous project for this purpose.  That was a web-based app in Scheme
(about 75k loc if I remember right), but it's the same idea for any
gui.

Cheers,
Chris Dean

P.S. If you ever switch to a web-based app, there are now some
     JavaScript based testing frameworks available.


Gmane